diff -Nru ip4r-2.3/debian/changelog ip4r-2.4/debian/changelog --- ip4r-2.3/debian/changelog 2018-10-11 20:29:19.000000000 +0000 +++ ip4r-2.4/debian/changelog 2018-11-29 09:22:50.000000000 +0000 @@ -1,3 +1,9 @@ +ip4r (2.4-1) unstable; urgency=medium + + * New upstream version. + + -- Christoph Berg Thu, 29 Nov 2018 10:22:50 +0100 + ip4r (2.3-2) unstable; urgency=medium * Upload for PostgreSQL 11. diff -Nru ip4r-2.3/debian/patches/Makefile-docs ip4r-2.4/debian/patches/Makefile-docs --- ip4r-2.3/debian/patches/Makefile-docs 2016-09-21 17:19:15.000000000 +0000 +++ ip4r-2.4/debian/patches/Makefile-docs 2018-11-29 09:22:50.000000000 +0000 @@ -1,11 +1,11 @@ --- a/Makefile +++ b/Makefile -@@ -11,7 +11,7 @@ EXTRA_CLEAN += ip4r.sql.in sql/ip4r-lega - REGRESS = ip4r-legacy - endif +@@ -22,7 +22,7 @@ endif --DOCS = README.ip4r -+#DOCS = README.ip4r - OBJS = ip4r_module.o ip4r.o ip6r.o ipaddr.o iprange.o raw_io.o + objdir = src - ifndef NO_PGXS +-DOCS = README.ip4r ++#DOCS = README.ip4r + OBJS_C = ip4r_module.o ip4r.o ip6r.o ipaddr.o iprange.o raw_io.o + OBJS = $(addprefix src/, $(OBJS_C)) + INCS = ipr.h ipr_internal.h diff -Nru ip4r-2.3/debian/source/lintian-overrides ip4r-2.4/debian/source/lintian-overrides --- ip4r-2.3/debian/source/lintian-overrides 1970-01-01 00:00:00.000000000 +0000 +++ ip4r-2.4/debian/source/lintian-overrides 2018-11-29 09:22:50.000000000 +0000 @@ -0,0 +1,3 @@ +# don't bug people uploading from @work +source: changelog-should-mention-nmu +source: source-nmu-has-incorrect-version-number diff -Nru ip4r-2.3/.dir-locals.el ip4r-2.4/.dir-locals.el --- ip4r-2.3/.dir-locals.el 1970-01-01 00:00:00.000000000 +0000 +++ ip4r-2.4/.dir-locals.el 2018-11-21 06:35:30.000000000 +0000 @@ -0,0 +1,28 @@ +;; largely stolen from pg itself + +((c-mode . ((c-basic-offset . 4) + (c-file-style . "bsd") + (c-file-offsets (case-label . +) (label . -) (statement-case-open . +)) + (fill-column . 78) + (indent-tabs-mode . t) + (tab-width . 4) + (eval add-hook 'before-save-hook 'delete-trailing-whitespace nil t))) + (css-mode . ((tab-width . 4) + (eval add-hook 'before-save-hook 'delete-trailing-whitespace nil t))) + (dsssl-mode . ((indent-tabs-mode . nil))) + (nxml-mode . ((indent-tabs-mode . nil)))) + +;; c-file-offsets is not marked safe by default, but you can either +;; accept the specific value given as safe always, or do something +;; like this in your .emacs to accept only the simplest offset lists +;; automatically: +;; (defun my-safe-c-file-offsets-p (alist) +;; (catch 'break +;; (and (listp alist) +;; (dolist (elt alist t) +;; (pcase elt +;; (`(,(pred symbolp) . ,(or `+ `- `++ `-- `* `/)) t) +;; (`(,(pred symbolp) . ,(or (pred null) (pred integerp))) t) +;; (`(,(pred symbolp) . [ ,(pred integerp) ]) t) +;; (_ (throw 'break nil))))))) +;; (put 'c-file-offsets 'safe-local-variable 'my-safe-c-file-offsets-p) diff -Nru ip4r-2.3/.editorconfig ip4r-2.4/.editorconfig --- ip4r-2.3/.editorconfig 1970-01-01 00:00:00.000000000 +0000 +++ ip4r-2.4/.editorconfig 2018-11-21 06:35:30.000000000 +0000 @@ -0,0 +1,6 @@ + +[*] +tab_width = 4 + +[Makefile] +tab_width = 8 diff -Nru ip4r-2.3/expected/ip4r.out ip4r-2.4/expected/ip4r.out --- ip4r-2.3/expected/ip4r.out 2018-05-24 21:30:28.000000000 +0000 +++ ip4r-2.4/expected/ip4r.out 2018-11-21 06:35:30.000000000 +0000 @@ -1,5 +1,37 @@ -- +/*CUT-HERE*/ CREATE EXTENSION ip4r; +-- Check whether any of our opclasses fail amvalidate +DO $d$ + DECLARE + r record; + BEGIN + IF current_setting('server_version_num')::integer >= 90600 THEN + FOR r IN SELECT amname, + CASE amname WHEN 'btree' THEN 6 + WHEN 'hash' THEN 6 + WHEN 'gist' THEN 3 + ELSE 0 END as expected, + count(nullif(amvalidate(opc.oid),false)) as actual + FROM pg_opclass opc + LEFT JOIN pg_am am ON am.oid = opcmethod + WHERE opcintype IN ('ip4'::regtype, + 'ip4r'::regtype, + 'ip6'::regtype, + 'ip6r'::regtype, + 'ipaddress'::regtype, + 'iprange'::regtype) + GROUP BY amname + ORDER BY amname + LOOP + IF r.expected IS DISTINCT FROM r.actual THEN + RAISE INFO '% % operator classes did not validate', r.expected - r.actual, r.amname; + END IF; + END LOOP; + END IF; + END; +$d$; +/*CUT-END*/ \set VERBOSITY terse -- -- Valid and invalid addresses @@ -6098,6 +6130,200 @@ ERROR: invalid IP value in cast to IP4 select '0.0.0.0'::ipaddress::ip6; ERROR: invalid IP value in cast to IP4 +-- bit casts +select (x'01020304')::ip4; + ip4 +--------- + 1.2.3.4 +(1 row) + +select (x'fff0fff1fff2fff3000000000000fff4')::ip6; + ip6 +--------------------------- + fff0:fff1:fff2:fff3::fff4 +(1 row) + +select (x'01020304')::ipaddress; + ipaddress +----------- + 1.2.3.4 +(1 row) + +select (x'fff0fff1fff2fff3000000000000fff4')::ipaddress; + ipaddress +--------------------------- + fff0:fff1:fff2:fff3::fff4 +(1 row) + +select (b'0001')::varbit::ip4r; + ip4r +------------ + 16.0.0.0/4 +(1 row) + +select (b'0001')::varbit::ip6r; + ip6r +---------- + 1000::/4 +(1 row) + +select (x'fff0fff1fff2fff3000000000000fff')::varbit::ip6r; + ip6r +------------------------------- + fff0:fff1:fff2:fff3::fff0/124 +(1 row) + +select (ip4 '1.2.3.4')::varbit; + varbit +---------------------------------- + 00000001000000100000001100000100 +(1 row) + +select (ip6 'fff0:fff1:fff2:fff3::fff4')::varbit; + varbit +---------------------------------------------------------------------------------------------------------------------------------- + 11111111111100001111111111110001111111111111001011111111111100110000000000000000000000000000000000000000000000001111111111110100 +(1 row) + +select (ipaddress '1.2.3.4')::varbit; + varbit +---------------------------------- + 00000001000000100000001100000100 +(1 row) + +select (ipaddress 'fff0:fff1:fff2:fff3::fff4')::varbit; + varbit +---------------------------------------------------------------------------------------------------------------------------------- + 11111111111100001111111111110001111111111111001011111111111100110000000000000000000000000000000000000000000000001111111111110100 +(1 row) + +select (ip4r '1.2.3.0/24')::varbit; + varbit +-------------------------- + 000000010000001000000011 +(1 row) + +select (ip6r 'fff0::/12')::varbit; + varbit +-------------- + 111111111111 +(1 row) + +select (ip6r 'fff0::/127')::varbit; + varbit +--------------------------------------------------------------------------------------------------------------------------------- + 1111111111110000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 +(1 row) + +select (iprange '-')::varbit; + varbit +-------- + +(1 row) + +select (iprange '1.2.3.0/24')::varbit; + varbit +-------------------------- + 000000010000001000000011 +(1 row) + +select (iprange '1.2.3.1-1.2.3.2')::varbit; + varbit +-------- + +(1 row) + +select (iprange 'fff0::/12')::varbit; + varbit +-------------- + 111111111111 +(1 row) + +select (iprange 'fff0::0001-fff0::0002')::varbit; + varbit +-------- + +(1 row) + +-- invalid bit casts +select (x'0102030')::ip4; +ERROR: invalid BIT value for conversion to IP4 +select (x'0102030405')::ip4; +ERROR: invalid BIT value for conversion to IP4 +select (x'fff0fff1fff2fff3000000000000fff')::ip6; +ERROR: invalid BIT value for conversion to IP6 +select (x'fff0fff1fff2fff3000000000000fff4f')::ip6; +ERROR: invalid BIT value for conversion to IP6 +select (x'0102030')::ipaddress; +ERROR: invalid BIT value for conversion to IPADDRESS +select (x'0102030405')::ipaddress; +ERROR: invalid BIT value for conversion to IPADDRESS +select (x'fff0fff1fff2fff3000000000000fff')::ipaddress; +ERROR: invalid BIT value for conversion to IPADDRESS +select (x'fff0fff1fff2fff3000000000000fff4f')::ipaddress; +ERROR: invalid BIT value for conversion to IPADDRESS +-- bytea casts +select (decode('01020304','hex'))::ip4; + decode +--------- + 1.2.3.4 +(1 row) + +select (decode('fff0fff1fff2fff3000000000000fff4','hex'))::ip6; + decode +--------------------------- + fff0:fff1:fff2:fff3::fff4 +(1 row) + +select (decode('01020304','hex'))::ipaddress; + decode +--------- + 1.2.3.4 +(1 row) + +select (decode('fff0fff1fff2fff3000000000000fff4','hex'))::ipaddress; + decode +--------------------------- + fff0:fff1:fff2:fff3::fff4 +(1 row) + +select encode((ip4 '1.2.3.4')::bytea,'hex'); + encode +---------- + 01020304 +(1 row) + +select encode((ip6 'fff0:fff1:fff2:fff3::fff4')::bytea,'hex'); + encode +---------------------------------- + fff0fff1fff2fff3000000000000fff4 +(1 row) + +select encode((ipaddress '1.2.3.4')::bytea,'hex'); + encode +---------- + 01020304 +(1 row) + +select encode((ipaddress 'fff0:fff1:fff2:fff3::fff4')::bytea,'hex'); + encode +---------------------------------- + fff0fff1fff2fff3000000000000fff4 +(1 row) + +-- invalid bytea casts +select (decode('010203','hex'))::ip4; +ERROR: invalid BYTEA value for conversion to IP4 +select (decode('0102030405','hex'))::ip4; +ERROR: invalid BYTEA value for conversion to IP4 +select (decode('fff0fff1fff2fff3000000000000ff','hex'))::ip6; +ERROR: invalid BYTEA value for conversion to IP4 +select (decode('0102030405','hex'))::ipaddress; +ERROR: invalid BYTEA value for conversion to IPADDRESS +select (decode('fff0fff1fff2fff3000000000000ff','hex'))::ipaddress; +ERROR: invalid BYTEA value for conversion to IPADDRESS +select (decode('fff0fff1fff2fff3000000000000ffffff','hex'))::ipaddress; +ERROR: invalid BYTEA value for conversion to IPADDRESS -- constructor functions select ip4r('0.0.0.0','255.255.255.255'); ip4r @@ -6879,6 +7105,297 @@ 3000::-5000:: (1 row) +-- split +select * from cidr_split(ip4r '1.2.3.4-5.6.7.8'); + cidr_split +-------------- + 1.2.3.4/30 + 1.2.3.8/29 + 1.2.3.16/28 + 1.2.3.32/27 + 1.2.3.64/26 + 1.2.3.128/25 + 1.2.4.0/22 + 1.2.8.0/21 + 1.2.16.0/20 + 1.2.32.0/19 + 1.2.64.0/18 + 1.2.128.0/17 + 1.3.0.0/16 + 1.4.0.0/14 + 1.8.0.0/13 + 1.16.0.0/12 + 1.32.0.0/11 + 1.64.0.0/10 + 1.128.0.0/9 + 2.0.0.0/7 + 4.0.0.0/8 + 5.0.0.0/14 + 5.4.0.0/15 + 5.6.0.0/22 + 5.6.4.0/23 + 5.6.6.0/24 + 5.6.7.0/29 + 5.6.7.8 +(28 rows) + +select * from cidr_split(ip4r '1.2.3.5-5.6.7.7'); + cidr_split +-------------- + 1.2.3.5 + 1.2.3.6/31 + 1.2.3.8/29 + 1.2.3.16/28 + 1.2.3.32/27 + 1.2.3.64/26 + 1.2.3.128/25 + 1.2.4.0/22 + 1.2.8.0/21 + 1.2.16.0/20 + 1.2.32.0/19 + 1.2.64.0/18 + 1.2.128.0/17 + 1.3.0.0/16 + 1.4.0.0/14 + 1.8.0.0/13 + 1.16.0.0/12 + 1.32.0.0/11 + 1.64.0.0/10 + 1.128.0.0/9 + 2.0.0.0/7 + 4.0.0.0/8 + 5.0.0.0/14 + 5.4.0.0/15 + 5.6.0.0/22 + 5.6.4.0/23 + 5.6.6.0/24 + 5.6.7.0/29 +(28 rows) + +select * from cidr_split(ip4r '1.0.0.0-1.0.255.255'); + cidr_split +------------ + 1.0.0.0/16 +(1 row) + +select * from cidr_split(ip4r '0.0.0.0-255.255.255.255'); + cidr_split +------------ + 0.0.0.0/0 +(1 row) + +select * from cidr_split(ip4r '0.0.0.0-0.0.0.9'); + cidr_split +------------ + 0.0.0.0/29 + 0.0.0.8/31 +(2 rows) + +select * from cidr_split(ip4r '255.255.255.251-255.255.255.255'); + cidr_split +-------------------- + 255.255.255.251 + 255.255.255.252/30 +(2 rows) + +select * from cidr_split(ip6r 'ffff::1234-ffff::1243'); + cidr_split +---------------- + ffff::1234/126 + ffff::1238/125 + ffff::1240/126 +(3 rows) + +select * from cidr_split(ip6r 'ffff:0:0:1234::-ffff:0:0:1243::'); + cidr_split +-------------------- + ffff:0:0:1234::/62 + ffff:0:0:1238::/61 + ffff:0:0:1240::/63 + ffff:0:0:1242::/64 + ffff:0:0:1243:: +(5 rows) + +select * from cidr_split(ip6r 'aaaa::cdef-aaaa::fedc'); + cidr_split +---------------- + aaaa::cdef + aaaa::cdf0/124 + aaaa::ce00/119 + aaaa::d000/116 + aaaa::e000/116 + aaaa::f000/117 + aaaa::f800/118 + aaaa::fc00/119 + aaaa::fe00/121 + aaaa::fe80/122 + aaaa::fec0/124 + aaaa::fed0/125 + aaaa::fed8/126 + aaaa::fedc +(14 rows) + +select * from cidr_split(ip6r 'ffff:0:0:aaaa::/64'); + cidr_split +-------------------- + ffff:0:0:aaaa::/64 +(1 row) + +select * from cidr_split(ip6r '::-::0009'); + cidr_split +------------ + ::/125 + ::8/127 +(2 rows) + +select * from cidr_split(ip6r 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff3-ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff'); + cidr_split +--------------------------------------------- + ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff3 + ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff4/126 + ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff8/125 +(3 rows) + +select * from cidr_split(iprange '1.2.3.4-5.6.7.8'); + cidr_split +-------------- + 1.2.3.4/30 + 1.2.3.8/29 + 1.2.3.16/28 + 1.2.3.32/27 + 1.2.3.64/26 + 1.2.3.128/25 + 1.2.4.0/22 + 1.2.8.0/21 + 1.2.16.0/20 + 1.2.32.0/19 + 1.2.64.0/18 + 1.2.128.0/17 + 1.3.0.0/16 + 1.4.0.0/14 + 1.8.0.0/13 + 1.16.0.0/12 + 1.32.0.0/11 + 1.64.0.0/10 + 1.128.0.0/9 + 2.0.0.0/7 + 4.0.0.0/8 + 5.0.0.0/14 + 5.4.0.0/15 + 5.6.0.0/22 + 5.6.4.0/23 + 5.6.6.0/24 + 5.6.7.0/29 + 5.6.7.8 +(28 rows) + +select * from cidr_split(iprange '1.2.3.5-5.6.7.7'); + cidr_split +-------------- + 1.2.3.5 + 1.2.3.6/31 + 1.2.3.8/29 + 1.2.3.16/28 + 1.2.3.32/27 + 1.2.3.64/26 + 1.2.3.128/25 + 1.2.4.0/22 + 1.2.8.0/21 + 1.2.16.0/20 + 1.2.32.0/19 + 1.2.64.0/18 + 1.2.128.0/17 + 1.3.0.0/16 + 1.4.0.0/14 + 1.8.0.0/13 + 1.16.0.0/12 + 1.32.0.0/11 + 1.64.0.0/10 + 1.128.0.0/9 + 2.0.0.0/7 + 4.0.0.0/8 + 5.0.0.0/14 + 5.4.0.0/15 + 5.6.0.0/22 + 5.6.4.0/23 + 5.6.6.0/24 + 5.6.7.0/29 +(28 rows) + +select * from cidr_split(iprange 'ffff::1234-ffff::1243'); + cidr_split +---------------- + ffff::1234/126 + ffff::1238/125 + ffff::1240/126 +(3 rows) + +select * from cidr_split(iprange 'aaaa::cdef-aaaa::fedc'); + cidr_split +---------------- + aaaa::cdef + aaaa::cdf0/124 + aaaa::ce00/119 + aaaa::d000/116 + aaaa::e000/116 + aaaa::f000/117 + aaaa::f800/118 + aaaa::fc00/119 + aaaa::fe00/121 + aaaa::fe80/122 + aaaa::fec0/124 + aaaa::fed0/125 + aaaa::fed8/126 + aaaa::fedc +(14 rows) + +select * from cidr_split(iprange '1.0.0.0/16'); + cidr_split +------------ + 1.0.0.0/16 +(1 row) + +select * from cidr_split(iprange 'ffff:0:0:aaaa::/64'); + cidr_split +-------------------- + ffff:0:0:aaaa::/64 +(1 row) + +select * from cidr_split(iprange '-'); + cidr_split +------------ + 0.0.0.0/0 + ::/0 +(2 rows) + +-- rescan +with d(a) as (values (ip4r '1.2.3.4-1.2.4.3'),(ip4r '10.2.3.5-10.2.4.4')) +select *, (select * from cidr_split(a) limit 1) as s from d; + a | s +-------------------+------------ + 1.2.3.4-1.2.4.3 | 1.2.3.4/30 + 10.2.3.5-10.2.4.4 | 10.2.3.5 +(2 rows) + +with d(a) as (values (ip6r 'ffff::1234-ffff::1243'),(ip6r 'aaaa::cdef-aaaa::fedc')) +select *, (select * from cidr_split(a) limit 1) as s from d; + a | s +-----------------------+---------------- + ffff::1234-ffff::1243 | ffff::1234/126 + aaaa::cdef-aaaa::fedc | aaaa::cdef +(2 rows) + +with d(a) as (values (iprange '-'),(iprange '1.2.3.4-1.2.4.3'), + (iprange 'aaaa::fedc-aaaa::cdef'),(iprange '-')) +select *, (select * from cidr_split(a) limit 1) as s from d; + a | s +-----------------------+------------ + - | 0.0.0.0/0 + 1.2.3.4-1.2.4.3 | 1.2.3.4/30 + aaaa::cdef-aaaa::fedc | aaaa::cdef + - | 0.0.0.0/0 +(4 rows) + -- operators select ip4 '255.255.255.255' / 32; ?column? diff -Nru ip4r-2.3/expected/ip4r-v11.out ip4r-2.4/expected/ip4r-v11.out --- ip4r-2.3/expected/ip4r-v11.out 1970-01-01 00:00:00.000000000 +0000 +++ ip4r-2.4/expected/ip4r-v11.out 2018-11-21 06:35:30.000000000 +0000 @@ -0,0 +1,616 @@ +-- Tests for pg11+ +-- RANGE support +select a4, + array_agg(a4) over (order by a4 range between 268435456 preceding and 268435456 following) + from ipaddrs + where a4 is not null; + a4 | array_agg +-----------------+------------------------------------------------------------- + 12.174.29.15 | {12.174.29.15} + 33.8.16.211 | {33.8.16.211} + 55.224.125.146 | {55.224.125.146} + 73.239.169.71 | {73.239.169.71,76.178.38.194} + 76.178.38.194 | {73.239.169.71,76.178.38.194} + 96.76.124.246 | {96.76.124.246,104.175.11.72} + 104.175.11.72 | {96.76.124.246,104.175.11.72} + 163.145.90.183 | {163.145.90.183} + 189.85.58.60 | {189.85.58.60,195.58.214.186,203.156.110.93} + 195.58.214.186 | {189.85.58.60,195.58.214.186,203.156.110.93} + 203.156.110.93 | {189.85.58.60,195.58.214.186,203.156.110.93} + 223.213.219.214 | {223.213.219.214,235.64.97.205} + 235.64.97.205 | {223.213.219.214,235.64.97.205,240.116.30.226} + 240.116.30.226 | {235.64.97.205,240.116.30.226,254.251.8.237,255.226.130.53} + 254.251.8.237 | {240.116.30.226,254.251.8.237,255.226.130.53} + 255.226.130.53 | {240.116.30.226,254.251.8.237,255.226.130.53} +(16 rows) + +select a4, + array_agg(a4) over (order by a4 range between ip4 '16.0.0.0' preceding and ip4 '16.0.0.0' following) + from ipaddrs + where a4 is not null; + a4 | array_agg +-----------------+------------------------------------------------------------- + 12.174.29.15 | {12.174.29.15} + 33.8.16.211 | {33.8.16.211} + 55.224.125.146 | {55.224.125.146} + 73.239.169.71 | {73.239.169.71,76.178.38.194} + 76.178.38.194 | {73.239.169.71,76.178.38.194} + 96.76.124.246 | {96.76.124.246,104.175.11.72} + 104.175.11.72 | {96.76.124.246,104.175.11.72} + 163.145.90.183 | {163.145.90.183} + 189.85.58.60 | {189.85.58.60,195.58.214.186,203.156.110.93} + 195.58.214.186 | {189.85.58.60,195.58.214.186,203.156.110.93} + 203.156.110.93 | {189.85.58.60,195.58.214.186,203.156.110.93} + 223.213.219.214 | {223.213.219.214,235.64.97.205} + 235.64.97.205 | {223.213.219.214,235.64.97.205,240.116.30.226} + 240.116.30.226 | {235.64.97.205,240.116.30.226,254.251.8.237,255.226.130.53} + 254.251.8.237 | {240.116.30.226,254.251.8.237,255.226.130.53} + 255.226.130.53 | {240.116.30.226,254.251.8.237,255.226.130.53} +(16 rows) + +select a4, + array_agg(a4) over (order by a4 range between -3 preceding and -3 following) + from ipaddrs + where a4 is not null; + a4 | array_agg +-----------------+------------------------------------------------------------- + 12.174.29.15 | {12.174.29.15} + 33.8.16.211 | {33.8.16.211,55.224.125.146} + 55.224.125.146 | {33.8.16.211,55.224.125.146} + 73.239.169.71 | {73.239.169.71,76.178.38.194} + 76.178.38.194 | {73.239.169.71,76.178.38.194} + 96.76.124.246 | {96.76.124.246,104.175.11.72} + 104.175.11.72 | {96.76.124.246,104.175.11.72} + 163.145.90.183 | {163.145.90.183,189.85.58.60} + 189.85.58.60 | {163.145.90.183,189.85.58.60} + 195.58.214.186 | {195.58.214.186,203.156.110.93,223.213.219.214} + 203.156.110.93 | {195.58.214.186,203.156.110.93,223.213.219.214} + 223.213.219.214 | {195.58.214.186,203.156.110.93,223.213.219.214} + 235.64.97.205 | {235.64.97.205,240.116.30.226,254.251.8.237,255.226.130.53} + 240.116.30.226 | {235.64.97.205,240.116.30.226,254.251.8.237,255.226.130.53} + 254.251.8.237 | {235.64.97.205,240.116.30.226,254.251.8.237,255.226.130.53} + 255.226.130.53 | {235.64.97.205,240.116.30.226,254.251.8.237,255.226.130.53} +(16 rows) + +select a6, + array_agg(a6) over (order by a6 range between -10 preceding and -10 following) + from ipaddrs + where a6 is not null; + a6 | array_agg +-----------------------------------------+-------------------------------------------------------------------------------------------------------------------------- + 73:3c34:57a:2a84:b1df:81b0:eb40:61cd | {73:3c34:57a:2a84:b1df:81b0:eb40:61cd} + b6:8ebc:c326:48a6:5615:a65e:e87a:25d7 | {b6:8ebc:c326:48a6:5615:a65e:e87a:25d7} + 166:b8ea:1fc5:8913:17ea:d6a0:ac2b:90e1 | {166:b8ea:1fc5:8913:17ea:d6a0:ac2b:90e1} + 227:b768:d43b:773d:6168:5133:867c:13f2 | {227:b768:d43b:773d:6168:5133:867c:13f2} + 453:2d:fbd3:191:95c6:3751:eb62:e90 | {453:2d:fbd3:191:95c6:3751:eb62:e90} + 4a6:7a28:b05b:f9b4:cc5b:9c4c:eefe:3e06 | {4a6:7a28:b05b:f9b4:cc5b:9c4c:eefe:3e06} + 550:fe90:bd02:a3ed:35a2:3254:e280:cd20 | {550:fe90:bd02:a3ed:35a2:3254:e280:cd20} + 75d:e701:5702:6087:a69a:1a2d:376e:4eb | {75d:e701:5702:6087:a69a:1a2d:376e:4eb} + 7e1:a608:dadd:684d:679e:698b:4db:c8c2 | {7e1:a608:dadd:684d:679e:698b:4db:c8c2} + 9ec:8fec:9a0e:3f2a:66e2:9b5c:498a:1090 | {9ec:8fec:9a0e:3f2a:66e2:9b5c:498a:1090} + a4b:4e55:7510:69b9:ba73:6550:eaa7:f16e | {a4b:4e55:7510:69b9:ba73:6550:eaa7:f16e} + bdb:15d3:fbaf:4bf6:194e:4d0d:4cb2:26c2 | {bdb:15d3:fbaf:4bf6:194e:4d0d:4cb2:26c2} + cc6:3030:8e26:ed4a:ae48:4496:63c3:94d0 | {cc6:3030:8e26:ed4a:ae48:4496:63c3:94d0,ce0:f080:aff1:6780:4951:55a7:4c23:f108} + ce0:f080:aff1:6780:4951:55a7:4c23:f108 | {cc6:3030:8e26:ed4a:ae48:4496:63c3:94d0,ce0:f080:aff1:6780:4951:55a7:4c23:f108} + d6b:f94a:4040:ba81:2347:d486:ac79:96f7 | {d6b:f94a:4040:ba81:2347:d486:ac79:96f7} + d9a:933a:3c47:801a:51d4:5a48:13bb:f59b | {d9a:933a:3c47:801a:51d4:5a48:13bb:f59b} + ded:898a:e003:6046:72e6:5584:1012:62cc | {ded:898a:e003:6046:72e6:5584:1012:62cc} + f47:6def:21e4:4620:3bc:9abc:8abd:aba2 | {f47:6def:21e4:4620:3bc:9abc:8abd:aba2} + 1009:d4ec:fe15:7946:eff2:6827:349e:6f0c | {1009:d4ec:fe15:7946:eff2:6827:349e:6f0c} + 10a5:994f:884d:9f98:4920:408d:1504:561d | {10a5:994f:884d:9f98:4920:408d:1504:561d} + 1378:f0c0:8ca:c76d:f062:4b7a:2573:5710 | {1378:f0c0:8ca:c76d:f062:4b7a:2573:5710} + 1395:59cf:33f6:988:1cf8:5ef3:3c2f:64dc | {1395:59cf:33f6:988:1cf8:5ef3:3c2f:64dc} + 13d9:9e39:ff4a:875f:82a0:77bc:1559:cf8d | {13d9:9e39:ff4a:875f:82a0:77bc:1559:cf8d,13fb:9738:a243:f879:730:2b72:783f:75e9} + 13fb:9738:a243:f879:730:2b72:783f:75e9 | {13d9:9e39:ff4a:875f:82a0:77bc:1559:cf8d,13fb:9738:a243:f879:730:2b72:783f:75e9} + 14fd:6de8:95f:fade:a20c:81d3:98da:c560 | {14fd:6de8:95f:fade:a20c:81d3:98da:c560} + 1520:c2bc:8426:2927:9e12:5f90:f4b0:30e6 | {1520:c2bc:8426:2927:9e12:5f90:f4b0:30e6} + 163a:503e:a2d7:c0d8:f5ee:657e:7f23:ea52 | {163a:503e:a2d7:c0d8:f5ee:657e:7f23:ea52} + 1685:dcd3:5113:5d84:2e64:d9e2:a602:aab7 | {1685:dcd3:5113:5d84:2e64:d9e2:a602:aab7} + 1839:8d68:ec5f:a4e7:711d:124e:150b:cddf | {1839:8d68:ec5f:a4e7:711d:124e:150b:cddf} + 1863:bf8e:aef5:1ac4:f85a:6683:8f7c:d191 | {1863:bf8e:aef5:1ac4:f85a:6683:8f7c:d191} + 18e8:f97:72d0:5444:c94:99fe:4a9e:f657 | {18e8:f97:72d0:5444:c94:99fe:4a9e:f657,18eb:378d:f12f:6114:34d2:ce03:e0d8:cffc} + 18eb:378d:f12f:6114:34d2:ce03:e0d8:cffc | {18e8:f97:72d0:5444:c94:99fe:4a9e:f657,18eb:378d:f12f:6114:34d2:ce03:e0d8:cffc} + 1962:ff9f:665f:ba25:d25a:f530:a391:5ab7 | {1962:ff9f:665f:ba25:d25a:f530:a391:5ab7} + 1b96:6d23:348f:a5f2:1869:1cd5:eff5:d09a | {1b96:6d23:348f:a5f2:1869:1cd5:eff5:d09a} + 1bc2:3fea:257c:553e:eb87:d8c7:ef94:4c9 | {1bc2:3fea:257c:553e:eb87:d8c7:ef94:4c9,1be9:3504:b341:17a8:10ec:e646:b0:433} + 1be9:3504:b341:17a8:10ec:e646:b0:433 | {1bc2:3fea:257c:553e:eb87:d8c7:ef94:4c9,1be9:3504:b341:17a8:10ec:e646:b0:433} + 1c3e:17b6:1bfd:77ea:2185:9748:38d:ac80 | {1c3e:17b6:1bfd:77ea:2185:9748:38d:ac80} + 1c90:5c1b:9431:11ea:f6dd:bb7c:c57f:6cc6 | {1c90:5c1b:9431:11ea:f6dd:bb7c:c57f:6cc6} + 1cc5:18d6:116d:d727:86b:9655:f44d:4fb7 | {1cc5:18d6:116d:d727:86b:9655:f44d:4fb7} + 1dbf:c6d8:ce1a:e3e3:c9a2:8458:3674:f6b | {1dbf:c6d8:ce1a:e3e3:c9a2:8458:3674:f6b} + 1f38:cd00:b368:80e5:7579:df75:3c50:b21b | {1f38:cd00:b368:80e5:7579:df75:3c50:b21b} + 204f:510d:e7e9:9c02:9576:48b1:bfb7:468 | {204f:510d:e7e9:9c02:9576:48b1:bfb7:468} + 21ef:74a4:2571:e430:47b1:a582:9723:9b14 | {21ef:74a4:2571:e430:47b1:a582:9723:9b14} + 2394:74d2:f34d:3801:3a23:f022:dc17:2cf | {2394:74d2:f34d:3801:3a23:f022:dc17:2cf} + 23fd:5d2:8e6a:628:b4e:3ff2:d386:d2b0 | {23fd:5d2:8e6a:628:b4e:3ff2:d386:d2b0} + 2408:f23d:d1ac:746d:2c8f:3dd6:7ed0:5507 | {2408:f23d:d1ac:746d:2c8f:3dd6:7ed0:5507} + 25d9:67f6:f409:c774:60ad:9d6a:b95b:4ad2 | {25d9:67f6:f409:c774:60ad:9d6a:b95b:4ad2,25f0:72d:e515:bc9b:f9a2:6061:b18b:758e} + 25f0:72d:e515:bc9b:f9a2:6061:b18b:758e | {25d9:67f6:f409:c774:60ad:9d6a:b95b:4ad2,25f0:72d:e515:bc9b:f9a2:6061:b18b:758e} + 2689:eae5:4101:f97c:628a:58fa:f0b5:159 | {2689:eae5:4101:f97c:628a:58fa:f0b5:159,26a3:7ac5:3ce2:cb2d:994d:8f10:82b6:419d,26ad:4d5b:192c:f85a:71db:38be:c6ca:19de} + 26a3:7ac5:3ce2:cb2d:994d:8f10:82b6:419d | {2689:eae5:4101:f97c:628a:58fa:f0b5:159,26a3:7ac5:3ce2:cb2d:994d:8f10:82b6:419d,26ad:4d5b:192c:f85a:71db:38be:c6ca:19de} + 26ad:4d5b:192c:f85a:71db:38be:c6ca:19de | {2689:eae5:4101:f97c:628a:58fa:f0b5:159,26a3:7ac5:3ce2:cb2d:994d:8f10:82b6:419d,26ad:4d5b:192c:f85a:71db:38be:c6ca:19de} + 28a6:2032:8a38:de85:f6f3:47bd:5124:7dc8 | {28a6:2032:8a38:de85:f6f3:47bd:5124:7dc8} + 28e7:4441:e0a4:bf30:4cf4:edb0:638d:ad72 | {28e7:4441:e0a4:bf30:4cf4:edb0:638d:ad72} + 29a4:a288:457e:57a9:bbb3:2a76:b117:b1e8 | {29a4:a288:457e:57a9:bbb3:2a76:b117:b1e8,29b2:d3c1:26c4:86b6:19b5:14dc:ab2d:bc67} + 29b2:d3c1:26c4:86b6:19b5:14dc:ab2d:bc67 | {29a4:a288:457e:57a9:bbb3:2a76:b117:b1e8,29b2:d3c1:26c4:86b6:19b5:14dc:ab2d:bc67} + 2a8a:5b38:cbdd:5d1c:e1b0:d627:f31f:285a | {2a8a:5b38:cbdd:5d1c:e1b0:d627:f31f:285a} + 2b47:da0e:8c52:cc33:afaa:f85f:f143:88c6 | {2b47:da0e:8c52:cc33:afaa:f85f:f143:88c6} + 2ee9:6428:5482:9721:9e51:ca52:ba3:99eb | {2ee9:6428:5482:9721:9e51:ca52:ba3:99eb} + 2f48:4d4b:443c:6de6:9cbe:9766:fd5:c88b | {2f48:4d4b:443c:6de6:9cbe:9766:fd5:c88b} + 2ff2:b6b6:ffd1:dc5f:fc2:defe:fd16:a414 | {2ff2:b6b6:ffd1:dc5f:fc2:defe:fd16:a414} + 3138:9022:3412:4cfb:fc2a:729a:651c:40f9 | {3138:9022:3412:4cfb:fc2a:729a:651c:40f9} + 318f:1162:8f48:3397:cb9a:f54e:f1e8:d05d | {318f:1162:8f48:3397:cb9a:f54e:f1e8:d05d} + 32ca:6639:c07e:c474:fa11:c83:2886:516c | {32ca:6639:c07e:c474:fa11:c83:2886:516c} + 35f1:eb03:921c:f397:cd41:9201:f7e0:dfad | {35f1:eb03:921c:f397:cd41:9201:f7e0:dfad,35f3:d696:b49e:1a25:375:5e28:15c9:96ce} + 35f3:d696:b49e:1a25:375:5e28:15c9:96ce | {35f1:eb03:921c:f397:cd41:9201:f7e0:dfad,35f3:d696:b49e:1a25:375:5e28:15c9:96ce} + 3902:4c48:d872:37bd:2e53:678d:3a0a:3cf6 | {3902:4c48:d872:37bd:2e53:678d:3a0a:3cf6,390b:b7a:6606:af43:233b:2e27:8336:5b2e} + 390b:b7a:6606:af43:233b:2e27:8336:5b2e | {3902:4c48:d872:37bd:2e53:678d:3a0a:3cf6,390b:b7a:6606:af43:233b:2e27:8336:5b2e} + 39ec:d6ba:1f45:64d0:f4d2:3f0f:78e:a404 | {39ec:d6ba:1f45:64d0:f4d2:3f0f:78e:a404} + 3af7:2de9:30a7:818d:9715:3eaf:d8f7:2583 | {3af7:2de9:30a7:818d:9715:3eaf:d8f7:2583} + 3b13:802b:cfd:15ef:bab3:f337:8b00:5744 | {3b13:802b:cfd:15ef:bab3:f337:8b00:5744} + 3bc9:de98:c700:5aa:d993:223e:dad:1949 | {3bc9:de98:c700:5aa:d993:223e:dad:1949} + 4068:6d06:7463:589:3262:86d1:f1f1:f088 | {4068:6d06:7463:589:3262:86d1:f1f1:f088} + 4111:e35f:ce3:c4de:dc4e:8764:8cd:1686 | {4111:e35f:ce3:c4de:dc4e:8764:8cd:1686,4131:d8b6:82af:797d:25fd:7bd4:b94d:ce34} + 4131:d8b6:82af:797d:25fd:7bd4:b94d:ce34 | {4111:e35f:ce3:c4de:dc4e:8764:8cd:1686,4131:d8b6:82af:797d:25fd:7bd4:b94d:ce34} + 42e2:d76f:c784:7a61:67c1:b931:6f49:32c5 | {42e2:d76f:c784:7a61:67c1:b931:6f49:32c5} + 4430:8b98:82c8:3d6c:dbd6:579e:c3fc:ec9d | {4430:8b98:82c8:3d6c:dbd6:579e:c3fc:ec9d,4439:44b6:c04:de6a:c0af:cf35:d9f3:f8ee} + 4439:44b6:c04:de6a:c0af:cf35:d9f3:f8ee | {4430:8b98:82c8:3d6c:dbd6:579e:c3fc:ec9d,4439:44b6:c04:de6a:c0af:cf35:d9f3:f8ee} + 450b:493b:a4d7:f0d3:6fe4:6da0:b550:f4ca | {450b:493b:a4d7:f0d3:6fe4:6da0:b550:f4ca} + 454c:20ee:35b9:b48b:a59f:e4bc:7b76:f228 | {454c:20ee:35b9:b48b:a59f:e4bc:7b76:f228,454e:bfa0:ed21:4983:7572:22c9:413d:d4db} + 454e:bfa0:ed21:4983:7572:22c9:413d:d4db | {454c:20ee:35b9:b48b:a59f:e4bc:7b76:f228,454e:bfa0:ed21:4983:7572:22c9:413d:d4db} + 4620:c642:9985:6a1f:6c66:50c0:2108:10d3 | {4620:c642:9985:6a1f:6c66:50c0:2108:10d3} + 4647:353:5292:8bef:e5b5:c13a:1176:deef | {4647:353:5292:8bef:e5b5:c13a:1176:deef} + 4bd6:2076:745e:acbe:c511:3786:60be:b51d | {4bd6:2076:745e:acbe:c511:3786:60be:b51d} + 4d6a:edd6:a446:6d89:e2a3:ab27:79ec:e148 | {4d6a:edd6:a446:6d89:e2a3:ab27:79ec:e148} + 4ee3:bfaa:5f22:2c05:573e:e87c:a6c2:81e0 | {4ee3:bfaa:5f22:2c05:573e:e87c:a6c2:81e0} + 53ad:31ab:bc5e:c535:bc7c:5762:c11e:fcec | {53ad:31ab:bc5e:c535:bc7c:5762:c11e:fcec} + 53d6:7f94:6b26:59cb:9c16:2aa:9722:b8ef | {53d6:7f94:6b26:59cb:9c16:2aa:9722:b8ef} + 5412:a54d:dbd8:8448:4728:5fb0:ec6f:4381 | {5412:a54d:dbd8:8448:4728:5fb0:ec6f:4381} + 5466:93e3:8343:3686:394:778:79ac:772 | {5466:93e3:8343:3686:394:778:79ac:772} + 54b6:4a85:c1a5:89b0:b7ff:5306:32be:d30f | {54b6:4a85:c1a5:89b0:b7ff:5306:32be:d30f} + 5637:5e57:c050:53fe:e182:697:ab46:21cc | {5637:5e57:c050:53fe:e182:697:ab46:21cc} + 56fd:83db:3ff7:b0b:7d5:8378:a486:f20 | {56fd:83db:3ff7:b0b:7d5:8378:a486:f20} + 5721:3c79:a6ff:c8d8:5e3:c785:808:e40 | {5721:3c79:a6ff:c8d8:5e3:c785:808:e40} + 5889:8398:cb90:8df:b3d6:3f5c:72cb:cd64 | {5889:8398:cb90:8df:b3d6:3f5c:72cb:cd64} + 599b:9e01:9a22:aebf:a731:ce57:fefb:8ed | {599b:9e01:9a22:aebf:a731:ce57:fefb:8ed} + 5a0b:33a9:3407:aa9c:f1c7:a538:2f25:bf14 | {5a0b:33a9:3407:aa9c:f1c7:a538:2f25:bf14,5a3f:b436:785f:32a4:8c86:13f8:e682:8b6a} + 5a3f:b436:785f:32a4:8c86:13f8:e682:8b6a | {5a0b:33a9:3407:aa9c:f1c7:a538:2f25:bf14,5a3f:b436:785f:32a4:8c86:13f8:e682:8b6a} + 5d63:9613:7b87:5c26:5c80:bbd3:14b5:1e63 | {5d63:9613:7b87:5c26:5c80:bbd3:14b5:1e63} + 5e52:9aa9:8f83:2a67:5959:720d:f6ba:5d42 | {5e52:9aa9:8f83:2a67:5959:720d:f6ba:5d42} + 5ee2:4fab:1073:b2f5:61c1:eea6:302f:685 | {5ee2:4fab:1073:b2f5:61c1:eea6:302f:685} + 5fa8:25bb:15e8:5b35:758c:2044:d194:1962 | {5fa8:25bb:15e8:5b35:758c:2044:d194:1962} + 61f2:afe0:d1af:18e9:5d40:7a4d:f112:2d09 | {61f2:afe0:d1af:18e9:5d40:7a4d:f112:2d09} + 6251:ab4b:3b37:d71f:6b5f:1b2d:bd55:3a3c | {6251:ab4b:3b37:d71f:6b5f:1b2d:bd55:3a3c} + 62b8:256d:637a:82bf:3b69:420:eea5:300b | {62b8:256d:637a:82bf:3b69:420:eea5:300b} + 62db:eab9:a54e:3cea:46f3:b7c2:cb9c:6e5d | {62db:eab9:a54e:3cea:46f3:b7c2:cb9c:6e5d} + 6656:e87d:865c:3237:8d42:ff01:a82b:f308 | {6656:e87d:865c:3237:8d42:ff01:a82b:f308} + 6a93:ccd3:5002:233f:1c5f:400e:601c:75a | {6a93:ccd3:5002:233f:1c5f:400e:601c:75a} + 6b0c:4791:ccea:c286:437e:d268:87ef:b6ad | {6b0c:4791:ccea:c286:437e:d268:87ef:b6ad} + 6e1b:5e9c:f623:6134:7754:fdac:323a:dba2 | {6e1b:5e9c:f623:6134:7754:fdac:323a:dba2} + 6e81:4a6a:d383:140d:8416:c09b:af3b:5b45 | {6e81:4a6a:d383:140d:8416:c09b:af3b:5b45,6e9d:66e:27c5:c7c4:aefe:ecfc:6568:ccf} + 6e9d:66e:27c5:c7c4:aefe:ecfc:6568:ccf | {6e81:4a6a:d383:140d:8416:c09b:af3b:5b45,6e9d:66e:27c5:c7c4:aefe:ecfc:6568:ccf} + 6ff2:94f5:5755:164d:1301:28ce:8a04:eac0 | {6ff2:94f5:5755:164d:1301:28ce:8a04:eac0} + 72c4:104f:960c:baf1:8ef7:60d2:c58:8b03 | {72c4:104f:960c:baf1:8ef7:60d2:c58:8b03} + 7341:d21f:e576:f226:f690:a99c:6b55:9933 | {7341:d21f:e576:f226:f690:a99c:6b55:9933} + 739b:8093:31c6:a42f:a604:d5cb:1350:2d2f | {739b:8093:31c6:a42f:a604:d5cb:1350:2d2f} + 7524:1f76:fe52:991e:667b:a302:dfd5:dbd6 | {7524:1f76:fe52:991e:667b:a302:dfd5:dbd6} + 7608:50bf:a29a:6805:c760:9ae3:1216:8e4a | {7608:50bf:a29a:6805:c760:9ae3:1216:8e4a} + 78c8:1cde:4b95:55d8:b211:a95d:37e0:7d92 | {78c8:1cde:4b95:55d8:b211:a95d:37e0:7d92} + 7924:9e5b:2c7:3920:9c9f:bfb6:369d:fa4f | {7924:9e5b:2c7:3920:9c9f:bfb6:369d:fa4f} + 798f:ea8:61f6:5d79:1656:d8d8:9b6e:57f0 | {798f:ea8:61f6:5d79:1656:d8d8:9b6e:57f0} + 79c9:d301:92cd:c774:abbb:2f7d:92c3:3ccd | {79c9:d301:92cd:c774:abbb:2f7d:92c3:3ccd,79eb:6133:5173:8f43:87d4:cb1d:906b:e8c9} + 79eb:6133:5173:8f43:87d4:cb1d:906b:e8c9 | {79c9:d301:92cd:c774:abbb:2f7d:92c3:3ccd,79eb:6133:5173:8f43:87d4:cb1d:906b:e8c9} + 7cba:a835:f850:6409:dba7:1300:f2b8:1db3 | {7cba:a835:f850:6409:dba7:1300:f2b8:1db3} + 7cdf:1ed8:690e:9e54:6f39:613e:f187:8ef2 | {7cdf:1ed8:690e:9e54:6f39:613e:f187:8ef2} + 7dcc:877b:8e07:aeb4:d891:581e:c10c:af54 | {7dcc:877b:8e07:aeb4:d891:581e:c10c:af54} + 7e1f:eb76:49c9:39f8:deb9:c447:b40c:a13d | {7e1f:eb76:49c9:39f8:deb9:c447:b40c:a13d} + 7ec8:2b00:5994:7f0f:d765:5e16:c274:5645 | {7ec8:2b00:5994:7f0f:d765:5e16:c274:5645} + 7f3d:d8ea:7a7c:8700:5b81:412f:c33a:d6ba | {7f3d:d8ea:7a7c:8700:5b81:412f:c33a:d6ba} + 7fa2:dbdb:e889:e24b:4d30:962e:89f3:676f | {7fa2:dbdb:e889:e24b:4d30:962e:89f3:676f} + 8119:1220:b888:3d8a:1250:ce77:b2b9:bdcd | {8119:1220:b888:3d8a:1250:ce77:b2b9:bdcd,8129:3e9c:70ff:1df1:f26f:86aa:c7ba:8245} + 8129:3e9c:70ff:1df1:f26f:86aa:c7ba:8245 | {8119:1220:b888:3d8a:1250:ce77:b2b9:bdcd,8129:3e9c:70ff:1df1:f26f:86aa:c7ba:8245} + 8172:4609:d700:5bd2:24a2:8f78:f1cc:c1a0 | {8172:4609:d700:5bd2:24a2:8f78:f1cc:c1a0} + 8241:abe3:7537:de41:ef5a:7d2a:9e57:833b | {8241:abe3:7537:de41:ef5a:7d2a:9e57:833b} + 828e:fa1d:9bb1:ad4c:4874:9da8:40bf:25b5 | {828e:fa1d:9bb1:ad4c:4874:9da8:40bf:25b5,8298:9399:271f:a3fe:270c:21cf:7c34:7340} + 8298:9399:271f:a3fe:270c:21cf:7c34:7340 | {828e:fa1d:9bb1:ad4c:4874:9da8:40bf:25b5,8298:9399:271f:a3fe:270c:21cf:7c34:7340} + 82ed:ac69:4ea7:5301:b005:3e17:f541:4fbc | {82ed:ac69:4ea7:5301:b005:3e17:f541:4fbc} + 8357:a24:2f6e:f909:3853:899a:68af:b48 | {8357:a24:2f6e:f909:3853:899a:68af:b48} + 8474:e00a:5b49:6e2a:5074:ecd5:cece:7dad | {8474:e00a:5b49:6e2a:5074:ecd5:cece:7dad} + 84fe:7351:7b39:349e:1bb7:e333:daec:141a | {84fe:7351:7b39:349e:1bb7:e333:daec:141a} + 8586:595:7bdd:359b:2fd9:1ffa:49ef:a947 | {8586:595:7bdd:359b:2fd9:1ffa:49ef:a947} + 86fa:3a3:6a26:5ce3:fd8d:6267:b3c:4bf0 | {86fa:3a3:6a26:5ce3:fd8d:6267:b3c:4bf0} + 874b:a74e:e292:c13:cf80:778c:35b4:d37c | {874b:a74e:e292:c13:cf80:778c:35b4:d37c} + 88bb:cf40:1f19:c897:f001:2d56:8f4f:ac68 | {88bb:cf40:1f19:c897:f001:2d56:8f4f:ac68} + 8909:5e3:cff9:483c:1fb7:2ee2:ab05:222a | {8909:5e3:cff9:483c:1fb7:2ee2:ab05:222a,890b:aa44:e2b1:ff61:eb7a:c4df:5a25:2eaf} + 890b:aa44:e2b1:ff61:eb7a:c4df:5a25:2eaf | {8909:5e3:cff9:483c:1fb7:2ee2:ab05:222a,890b:aa44:e2b1:ff61:eb7a:c4df:5a25:2eaf} + 8a1f:674e:63cd:f241:8f53:aec9:d8db:8e5c | {8a1f:674e:63cd:f241:8f53:aec9:d8db:8e5c} + 8b0c:b103:3302:90bb:bac:809e:9c7d:3569 | {8b0c:b103:3302:90bb:bac:809e:9c7d:3569} + 8b61:6b31:d02c:87d3:22cf:f01c:c045:b822 | {8b61:6b31:d02c:87d3:22cf:f01c:c045:b822} + 8b87:864a:8e83:6783:c552:cb07:8e96:c0e5 | {8b87:864a:8e83:6783:c552:cb07:8e96:c0e5} + 8c86:2c19:c38d:626b:b5a4:e0cb:bbaf:476b | {8c86:2c19:c38d:626b:b5a4:e0cb:bbaf:476b} + 8ec2:3493:ad95:cb7e:ae1c:8c2c:6a34:eccb | {8ec2:3493:ad95:cb7e:ae1c:8c2c:6a34:eccb,8ecc:14db:7aba:bbde:f2a7:c4bc:7a1e:c8c1} + 8ecc:14db:7aba:bbde:f2a7:c4bc:7a1e:c8c1 | {8ec2:3493:ad95:cb7e:ae1c:8c2c:6a34:eccb,8ecc:14db:7aba:bbde:f2a7:c4bc:7a1e:c8c1} + 8f7a:5e8b:f526:a8ba:8c6f:3cae:7b7e:1a5 | {8f7a:5e8b:f526:a8ba:8c6f:3cae:7b7e:1a5} + 8fa1:e604:6ad4:c318:ba8f:eaec:76be:ad4b | {8fa1:e604:6ad4:c318:ba8f:eaec:76be:ad4b,8fac:3b7e:463d:1b38:2f59:6fdf:3bef:4aaf} + 8fac:3b7e:463d:1b38:2f59:6fdf:3bef:4aaf | {8fa1:e604:6ad4:c318:ba8f:eaec:76be:ad4b,8fac:3b7e:463d:1b38:2f59:6fdf:3bef:4aaf} + 933f:d5b:d307:c3e0:5e0:b947:1cb5:6928 | {933f:d5b:d307:c3e0:5e0:b947:1cb5:6928} + 9520:88f9:9498:8a73:ac7a:dc77:4495:3dfc | {9520:88f9:9498:8a73:ac7a:dc77:4495:3dfc} + 9631:3557:7591:6ade:1882:6dad:8413:c3b3 | {9631:3557:7591:6ade:1882:6dad:8413:c3b3} + 977b:de6f:3ef9:3cad:fb02:fb07:458c:e88e | {977b:de6f:3ef9:3cad:fb02:fb07:458c:e88e} + 982a:e6d8:49bc:49a7:80b:4417:45f7:4fb7 | {982a:e6d8:49bc:49a7:80b:4417:45f7:4fb7} + 9943:4095:cf6c:bf1d:f1b4:7883:f929:a315 | {9943:4095:cf6c:bf1d:f1b4:7883:f929:a315} + 99b7:bba0:206c:6042:6778:2f3b:9a:6393 | {99b7:bba0:206c:6042:6778:2f3b:9a:6393} + 9b3d:56d7:b18e:21b9:7448:3cea:2ec:77f8 | {9b3d:56d7:b18e:21b9:7448:3cea:2ec:77f8} + 9c51:8c1b:a051:a87e:c65a:cc8:a38e:4953 | {9c51:8c1b:a051:a87e:c65a:cc8:a38e:4953} + 9d35:9c4f:517d:2391:f59c:af03:1681:6d9b | {9d35:9c4f:517d:2391:f59c:af03:1681:6d9b} + 9da1:e3ce:660a:cde4:7576:554:55cc:38ad | {9da1:e3ce:660a:cde4:7576:554:55cc:38ad} + 9ee9:65bd:81d2:b2c6:c3c4:b36b:16a2:fc9e | {9ee9:65bd:81d2:b2c6:c3c4:b36b:16a2:fc9e} + a0d3:f0b5:7a50:2d3e:923e:3832:76c0:b15d | {a0d3:f0b5:7a50:2d3e:923e:3832:76c0:b15d} + a252:248:a123:3287:680f:a67c:2fcd:b2a0 | {a252:248:a123:3287:680f:a67c:2fcd:b2a0} + a300:d184:bf44:e8f1:4a80:723c:909:f178 | {a300:d184:bf44:e8f1:4a80:723c:909:f178,a335:f1a7:be5c:b341:5325:e8d3:2631:74ae} + a335:f1a7:be5c:b341:5325:e8d3:2631:74ae | {a300:d184:bf44:e8f1:4a80:723c:909:f178,a335:f1a7:be5c:b341:5325:e8d3:2631:74ae} + a42d:662e:1816:1fe3:a392:9190:7d4e:f418 | {a42d:662e:1816:1fe3:a392:9190:7d4e:f418} + a52f:f73a:413e:a43a:5000:cd8f:ef1f:3603 | {a52f:f73a:413e:a43a:5000:cd8f:ef1f:3603} + a75b:c708:8e74:b252:f8e8:7269:c214:dc07 | {a75b:c708:8e74:b252:f8e8:7269:c214:dc07} + a87b:8920:6e0:9c1b:92a8:3a1e:f074:1ee2 | {a87b:8920:6e0:9c1b:92a8:3a1e:f074:1ee2} + a884:9796:ca7c:ec37:9cb4:4158:ce4c:ced5 | {a884:9796:ca7c:ec37:9cb4:4158:ce4c:ced5} + a9e9:74a5:864a:dfeb:a5f0:4424:d294:95a1 | {a9e9:74a5:864a:dfeb:a5f0:4424:d294:95a1} + ac4c:23a6:9c5f:8a2a:ccfc:ea69:48cd:dffc | {ac4c:23a6:9c5f:8a2a:ccfc:ea69:48cd:dffc,ac71:fd2c:4352:c28a:2f4b:3cd1:4d6f:927b} + ac71:fd2c:4352:c28a:2f4b:3cd1:4d6f:927b | {ac4c:23a6:9c5f:8a2a:ccfc:ea69:48cd:dffc,ac71:fd2c:4352:c28a:2f4b:3cd1:4d6f:927b} + ad73:992f:b3d8:31f7:306d:a418:fdcf:3e60 | {ad73:992f:b3d8:31f7:306d:a418:fdcf:3e60} + ae64:d6a3:11d7:b6bc:aa3:60c6:b16f:4305 | {ae64:d6a3:11d7:b6bc:aa3:60c6:b16f:4305} + af5a:6507:2c50:f0a8:b211:fc0d:425e:bd47 | {af5a:6507:2c50:f0a8:b211:fc0d:425e:bd47} + afeb:a771:735e:1a18:9297:e9f4:2e53:c5e1 | {afeb:a771:735e:1a18:9297:e9f4:2e53:c5e1} + b105:5518:a963:9a0a:d10d:b42b:dfd1:96a2 | {b105:5518:a963:9a0a:d10d:b42b:dfd1:96a2,b113:66f:e222:f032:7161:1f27:b080:2111} + b113:66f:e222:f032:7161:1f27:b080:2111 | {b105:5518:a963:9a0a:d10d:b42b:dfd1:96a2,b113:66f:e222:f032:7161:1f27:b080:2111} + b218:c6f2:4929:7d70:8b4d:5458:fc85:d0fc | {b218:c6f2:4929:7d70:8b4d:5458:fc85:d0fc,b237:dac3:62d7:725e:d772:c88c:af71:cec5} + b237:dac3:62d7:725e:d772:c88c:af71:cec5 | {b218:c6f2:4929:7d70:8b4d:5458:fc85:d0fc,b237:dac3:62d7:725e:d772:c88c:af71:cec5} + b310:3d72:ea86:6ee:45fc:d57f:4a7a:bb43 | {b310:3d72:ea86:6ee:45fc:d57f:4a7a:bb43} + b3da:187b:cc2e:3c78:e060:aab6:63cb:1780 | {b3da:187b:cc2e:3c78:e060:aab6:63cb:1780} + b408:9874:22a3:9f56:35f:cfd1:b00:ddac | {b408:9874:22a3:9f56:35f:cfd1:b00:ddac} + b48c:eccb:32f4:2b4:e2ee:e787:a16f:8647 | {b48c:eccb:32f4:2b4:e2ee:e787:a16f:8647} + b8ef:17e2:febe:431d:9d8c:88c6:6604:a678 | {b8ef:17e2:febe:431d:9d8c:88c6:6604:a678} + ba0d:d2d4:b5e3:573f:98f4:98e:aac1:47fa | {ba0d:d2d4:b5e3:573f:98f4:98e:aac1:47fa} + baf9:2948:a8a1:8865:912a:839f:45e8:78d3 | {baf9:2948:a8a1:8865:912a:839f:45e8:78d3} + bb1b:6a20:8513:14e4:5fc6:c0e9:17df:9c0 | {bb1b:6a20:8513:14e4:5fc6:c0e9:17df:9c0} + bc1d:d3ba:50da:14d3:f496:6847:3b91:2830 | {bc1d:d3ba:50da:14d3:f496:6847:3b91:2830} + bc52:8171:9377:d593:1c0a:75e4:e2d:5e1a | {bc52:8171:9377:d593:1c0a:75e4:e2d:5e1a} + bd6f:44b9:45d3:529f:84c7:612:b25c:aaf8 | {bd6f:44b9:45d3:529f:84c7:612:b25c:aaf8} + bdc5:94f5:8249:7120:8132:ca25:d3fc:c394 | {bdc5:94f5:8249:7120:8132:ca25:d3fc:c394} + c0fc:f3ee:3707:19dc:62c1:5c9a:df3d:1b58 | {c0fc:f3ee:3707:19dc:62c1:5c9a:df3d:1b58} + c2e3:4cea:30dd:cb39:c5a0:86e7:8b05:3f7 | {c2e3:4cea:30dd:cb39:c5a0:86e7:8b05:3f7} + c36f:f4fd:4853:a07c:c25d:349f:3af4:3432 | {c36f:f4fd:4853:a07c:c25d:349f:3af4:3432} + c504:481e:2756:3ca2:f0c:a26a:4e64:7804 | {c504:481e:2756:3ca2:f0c:a26a:4e64:7804} + c6ff:8d3c:d2d1:ee46:65ca:27f9:cc07:8e6d | {c6ff:8d3c:d2d1:ee46:65ca:27f9:cc07:8e6d} + c8c0:5117:331a:f029:8d24:6775:fe7d:5976 | {c8c0:5117:331a:f029:8d24:6775:fe7d:5976} + c963:10d0:1586:d1d4:79bc:d7af:5486:43e5 | {c963:10d0:1586:d1d4:79bc:d7af:5486:43e5} + c99c:bd43:6161:d17d:2fdd:ab61:922:ba62 | {c99c:bd43:6161:d17d:2fdd:ab61:922:ba62} + cb2f:b8da:ba34:1c5c:4839:710a:f75b:bdd0 | {cb2f:b8da:ba34:1c5c:4839:710a:f75b:bdd0} + cb70:a0cc:6919:db7f:8fc8:cb69:6fcc:5f5b | {cb70:a0cc:6919:db7f:8fc8:cb69:6fcc:5f5b} + cc17:3814:d80f:41a1:1309:35d3:ea0a:d31e | {cc17:3814:d80f:41a1:1309:35d3:ea0a:d31e} + ce47:e5eb:41f3:23af:6209:5ade:82ce:3b00 | {ce47:e5eb:41f3:23af:6209:5ade:82ce:3b00} + cfb9:d37e:2427:af8d:b728:8f90:f54c:9141 | {cfb9:d37e:2427:af8d:b728:8f90:f54c:9141} + d066:f25b:e8a5:4ae6:4c99:2a98:8cb7:2530 | {d066:f25b:e8a5:4ae6:4c99:2a98:8cb7:2530} + d105:1597:c912:51c7:e5b6:f628:cae:1d0f | {d105:1597:c912:51c7:e5b6:f628:cae:1d0f} + d2de:7aa1:975:e510:dfa1:2a3:89bc:eedb | {d2de:7aa1:975:e510:dfa1:2a3:89bc:eedb} + d33e:e847:b4c6:d5ca:f75:216b:342c:3d04 | {d33e:e847:b4c6:d5ca:f75:216b:342c:3d04} + d395:c008:43a4:48d9:15a7:ce74:6546:c56b | {d395:c008:43a4:48d9:15a7:ce74:6546:c56b} + d452:6fb9:f2b0:d387:80ca:47d5:330f:577 | {d452:6fb9:f2b0:d387:80ca:47d5:330f:577} + d524:77db:2a21:e05b:68c4:575c:f04b:b0b7 | {d524:77db:2a21:e05b:68c4:575c:f04b:b0b7} + d6d1:e96c:cd2f:8396:23f2:c96d:9376:54cb | {d6d1:e96c:cd2f:8396:23f2:c96d:9376:54cb} + d76b:986d:d38b:252a:e6a2:254e:b0f7:db24 | {d76b:986d:d38b:252a:e6a2:254e:b0f7:db24} + d9f3:2018:6aa2:7ee4:64be:e2d:c32c:2d15 | {d9f3:2018:6aa2:7ee4:64be:e2d:c32c:2d15} + da3e:c57c:ccc8:edbf:f66e:85a5:e252:a3a4 | {da3e:c57c:ccc8:edbf:f66e:85a5:e252:a3a4} + da52:3791:27b8:f773:7a59:1414:6d76:bd8a | {da52:3791:27b8:f773:7a59:1414:6d76:bd8a} + da97:ecc5:bf17:1bb2:5710:f753:604c:7cf6 | {da97:ecc5:bf17:1bb2:5710:f753:604c:7cf6} + dc61:8bf4:4b82:90a4:8af0:6a43:a917:14ee | {dc61:8bf4:4b82:90a4:8af0:6a43:a917:14ee} + dd3b:ad95:1e55:a555:daae:8218:99d7:7bce | {dd3b:ad95:1e55:a555:daae:8218:99d7:7bce} + defd:c729:62b4:8959:6ad1:7b1f:5835:8ffb | {defd:c729:62b4:8959:6ad1:7b1f:5835:8ffb} + dfe2:c097:49ae:1d60:e3db:26c1:bb5d:c4e0 | {dfe2:c097:49ae:1d60:e3db:26c1:bb5d:c4e0} + e11c:4f21:dd57:c814:af4e:3f55:4adf:f1a0 | {e11c:4f21:dd57:c814:af4e:3f55:4adf:f1a0} + e199:2ea0:f3b4:3a31:5d15:dfc9:68cd:c948 | {e199:2ea0:f3b4:3a31:5d15:dfc9:68cd:c948} + e57b:76e8:3f3a:3020:a22a:38b7:9c02:5db4 | {e57b:76e8:3f3a:3020:a22a:38b7:9c02:5db4} + e6da:dc3c:a935:a718:4744:a216:84bd:cfa9 | {e6da:dc3c:a935:a718:4744:a216:84bd:cfa9} + e7a7:adbe:d6de:41ba:a34f:d10b:46a7:a4cf | {e7a7:adbe:d6de:41ba:a34f:d10b:46a7:a4cf} + e86d:edb4:8702:1774:c97d:cbee:394:a083 | {e86d:edb4:8702:1774:c97d:cbee:394:a083} + e97f:c466:f346:cf67:23e4:bd36:72be:af44 | {e97f:c466:f346:cf67:23e4:bd36:72be:af44} + ec36:7c6d:3077:267e:399a:d47:55a4:218a | {ec36:7c6d:3077:267e:399a:d47:55a4:218a} + ee1d:a078:25d4:94e3:9a89:707d:6fae:7573 | {ee1d:a078:25d4:94e3:9a89:707d:6fae:7573,ee34:9ba:9281:593c:ab74:57fa:e439:e0f3} + ee34:9ba:9281:593c:ab74:57fa:e439:e0f3 | {ee1d:a078:25d4:94e3:9a89:707d:6fae:7573,ee34:9ba:9281:593c:ab74:57fa:e439:e0f3} + ee76:e9ac:dd2:66c1:380:5f1e:1c4d:2867 | {ee76:e9ac:dd2:66c1:380:5f1e:1c4d:2867} + eea0:9aef:71b:3cfd:e2ad:864c:41b8:938c | {eea0:9aef:71b:3cfd:e2ad:864c:41b8:938c} + ef15:3aa9:3c5b:b993:5209:a130:2d37:3a64 | {ef15:3aa9:3c5b:b993:5209:a130:2d37:3a64} + ef9a:b980:e9:d50a:d867:8a88:2cae:8aa1 | {ef9a:b980:e9:d50a:d867:8a88:2cae:8aa1} + effb:1a90:1dd5:e52c:1d7f:c716:3744:170a | {effb:1a90:1dd5:e52c:1d7f:c716:3744:170a} + f0a1:e730:68b9:2e1c:649a:5450:a256:4665 | {f0a1:e730:68b9:2e1c:649a:5450:a256:4665} + f3df:f155:d5c6:d664:c93c:13fa:9d77:6bf2 | {f3df:f155:d5c6:d664:c93c:13fa:9d77:6bf2} + f499:668f:fbb8:f0dc:8e41:d43b:c025:26a | {f499:668f:fbb8:f0dc:8e41:d43b:c025:26a} + f57a:a3dc:3b11:f28a:8b25:8d5b:ec2f:c729 | {f57a:a3dc:3b11:f28a:8b25:8d5b:ec2f:c729} + f7b8:dfc:496c:9718:ae3c:5c3e:b98a:4c5f | {f7b8:dfc:496c:9718:ae3c:5c3e:b98a:4c5f} + fa78:68ce:4fb1:d54c:2007:1820:ffe2:8235 | {fa78:68ce:4fb1:d54c:2007:1820:ffe2:8235} + fbb6:2d70:42eb:55ab:6235:6867:2b3:8d47 | {fbb6:2d70:42eb:55ab:6235:6867:2b3:8d47} + fcea:f739:a97d:cefc:49c4:b3c3:c7b4:99d6 | {fcea:f739:a97d:cefc:49c4:b3c3:c7b4:99d6} + fda3:3e75:37c5:c1f:912b:5e32:6aa9:aeb2 | {fda3:3e75:37c5:c1f:912b:5e32:6aa9:aeb2} + ff3d:7d5b:b0fe:c30:9e6c:23e0:7b5:e9de | {ff3d:7d5b:b0fe:c30:9e6c:23e0:7b5:e9de} + ff4a:cbbf:695a:9e46:f27c:e1be:861f:9e7 | {ff4a:cbbf:695a:9e46:f27c:e1be:861f:9e7,ff6b:af36:5fc2:93d9:ebf3:3c62:a19f:307f} + ff6b:af36:5fc2:93d9:ebf3:3c62:a19f:307f | {ff4a:cbbf:695a:9e46:f27c:e1be:861f:9e7,ff6b:af36:5fc2:93d9:ebf3:3c62:a19f:307f} +(256 rows) + +select a6, + array_agg(a6) over (order by a6 range between ip6 '0010::' preceding and ip6 '0010::' following) + from ipaddrs + where a6 is not null; + a6 | array_agg +-----------------------------------------+----------------------------------------------------------------------------------- + 73:3c34:57a:2a84:b1df:81b0:eb40:61cd | {73:3c34:57a:2a84:b1df:81b0:eb40:61cd} + b6:8ebc:c326:48a6:5615:a65e:e87a:25d7 | {b6:8ebc:c326:48a6:5615:a65e:e87a:25d7} + 166:b8ea:1fc5:8913:17ea:d6a0:ac2b:90e1 | {166:b8ea:1fc5:8913:17ea:d6a0:ac2b:90e1} + 227:b768:d43b:773d:6168:5133:867c:13f2 | {227:b768:d43b:773d:6168:5133:867c:13f2} + 453:2d:fbd3:191:95c6:3751:eb62:e90 | {453:2d:fbd3:191:95c6:3751:eb62:e90} + 4a6:7a28:b05b:f9b4:cc5b:9c4c:eefe:3e06 | {4a6:7a28:b05b:f9b4:cc5b:9c4c:eefe:3e06} + 550:fe90:bd02:a3ed:35a2:3254:e280:cd20 | {550:fe90:bd02:a3ed:35a2:3254:e280:cd20} + 75d:e701:5702:6087:a69a:1a2d:376e:4eb | {75d:e701:5702:6087:a69a:1a2d:376e:4eb} + 7e1:a608:dadd:684d:679e:698b:4db:c8c2 | {7e1:a608:dadd:684d:679e:698b:4db:c8c2} + 9ec:8fec:9a0e:3f2a:66e2:9b5c:498a:1090 | {9ec:8fec:9a0e:3f2a:66e2:9b5c:498a:1090} + a4b:4e55:7510:69b9:ba73:6550:eaa7:f16e | {a4b:4e55:7510:69b9:ba73:6550:eaa7:f16e} + bdb:15d3:fbaf:4bf6:194e:4d0d:4cb2:26c2 | {bdb:15d3:fbaf:4bf6:194e:4d0d:4cb2:26c2} + cc6:3030:8e26:ed4a:ae48:4496:63c3:94d0 | {cc6:3030:8e26:ed4a:ae48:4496:63c3:94d0} + ce0:f080:aff1:6780:4951:55a7:4c23:f108 | {ce0:f080:aff1:6780:4951:55a7:4c23:f108} + d6b:f94a:4040:ba81:2347:d486:ac79:96f7 | {d6b:f94a:4040:ba81:2347:d486:ac79:96f7} + d9a:933a:3c47:801a:51d4:5a48:13bb:f59b | {d9a:933a:3c47:801a:51d4:5a48:13bb:f59b} + ded:898a:e003:6046:72e6:5584:1012:62cc | {ded:898a:e003:6046:72e6:5584:1012:62cc} + f47:6def:21e4:4620:3bc:9abc:8abd:aba2 | {f47:6def:21e4:4620:3bc:9abc:8abd:aba2} + 1009:d4ec:fe15:7946:eff2:6827:349e:6f0c | {1009:d4ec:fe15:7946:eff2:6827:349e:6f0c} + 10a5:994f:884d:9f98:4920:408d:1504:561d | {10a5:994f:884d:9f98:4920:408d:1504:561d} + 1378:f0c0:8ca:c76d:f062:4b7a:2573:5710 | {1378:f0c0:8ca:c76d:f062:4b7a:2573:5710} + 1395:59cf:33f6:988:1cf8:5ef3:3c2f:64dc | {1395:59cf:33f6:988:1cf8:5ef3:3c2f:64dc} + 13d9:9e39:ff4a:875f:82a0:77bc:1559:cf8d | {13d9:9e39:ff4a:875f:82a0:77bc:1559:cf8d} + 13fb:9738:a243:f879:730:2b72:783f:75e9 | {13fb:9738:a243:f879:730:2b72:783f:75e9} + 14fd:6de8:95f:fade:a20c:81d3:98da:c560 | {14fd:6de8:95f:fade:a20c:81d3:98da:c560} + 1520:c2bc:8426:2927:9e12:5f90:f4b0:30e6 | {1520:c2bc:8426:2927:9e12:5f90:f4b0:30e6} + 163a:503e:a2d7:c0d8:f5ee:657e:7f23:ea52 | {163a:503e:a2d7:c0d8:f5ee:657e:7f23:ea52} + 1685:dcd3:5113:5d84:2e64:d9e2:a602:aab7 | {1685:dcd3:5113:5d84:2e64:d9e2:a602:aab7} + 1839:8d68:ec5f:a4e7:711d:124e:150b:cddf | {1839:8d68:ec5f:a4e7:711d:124e:150b:cddf} + 1863:bf8e:aef5:1ac4:f85a:6683:8f7c:d191 | {1863:bf8e:aef5:1ac4:f85a:6683:8f7c:d191} + 18e8:f97:72d0:5444:c94:99fe:4a9e:f657 | {18e8:f97:72d0:5444:c94:99fe:4a9e:f657,18eb:378d:f12f:6114:34d2:ce03:e0d8:cffc} + 18eb:378d:f12f:6114:34d2:ce03:e0d8:cffc | {18e8:f97:72d0:5444:c94:99fe:4a9e:f657,18eb:378d:f12f:6114:34d2:ce03:e0d8:cffc} + 1962:ff9f:665f:ba25:d25a:f530:a391:5ab7 | {1962:ff9f:665f:ba25:d25a:f530:a391:5ab7} + 1b96:6d23:348f:a5f2:1869:1cd5:eff5:d09a | {1b96:6d23:348f:a5f2:1869:1cd5:eff5:d09a} + 1bc2:3fea:257c:553e:eb87:d8c7:ef94:4c9 | {1bc2:3fea:257c:553e:eb87:d8c7:ef94:4c9} + 1be9:3504:b341:17a8:10ec:e646:b0:433 | {1be9:3504:b341:17a8:10ec:e646:b0:433} + 1c3e:17b6:1bfd:77ea:2185:9748:38d:ac80 | {1c3e:17b6:1bfd:77ea:2185:9748:38d:ac80} + 1c90:5c1b:9431:11ea:f6dd:bb7c:c57f:6cc6 | {1c90:5c1b:9431:11ea:f6dd:bb7c:c57f:6cc6} + 1cc5:18d6:116d:d727:86b:9655:f44d:4fb7 | {1cc5:18d6:116d:d727:86b:9655:f44d:4fb7} + 1dbf:c6d8:ce1a:e3e3:c9a2:8458:3674:f6b | {1dbf:c6d8:ce1a:e3e3:c9a2:8458:3674:f6b} + 1f38:cd00:b368:80e5:7579:df75:3c50:b21b | {1f38:cd00:b368:80e5:7579:df75:3c50:b21b} + 204f:510d:e7e9:9c02:9576:48b1:bfb7:468 | {204f:510d:e7e9:9c02:9576:48b1:bfb7:468} + 21ef:74a4:2571:e430:47b1:a582:9723:9b14 | {21ef:74a4:2571:e430:47b1:a582:9723:9b14} + 2394:74d2:f34d:3801:3a23:f022:dc17:2cf | {2394:74d2:f34d:3801:3a23:f022:dc17:2cf} + 23fd:5d2:8e6a:628:b4e:3ff2:d386:d2b0 | {23fd:5d2:8e6a:628:b4e:3ff2:d386:d2b0,2408:f23d:d1ac:746d:2c8f:3dd6:7ed0:5507} + 2408:f23d:d1ac:746d:2c8f:3dd6:7ed0:5507 | {23fd:5d2:8e6a:628:b4e:3ff2:d386:d2b0,2408:f23d:d1ac:746d:2c8f:3dd6:7ed0:5507} + 25d9:67f6:f409:c774:60ad:9d6a:b95b:4ad2 | {25d9:67f6:f409:c774:60ad:9d6a:b95b:4ad2} + 25f0:72d:e515:bc9b:f9a2:6061:b18b:758e | {25f0:72d:e515:bc9b:f9a2:6061:b18b:758e} + 2689:eae5:4101:f97c:628a:58fa:f0b5:159 | {2689:eae5:4101:f97c:628a:58fa:f0b5:159} + 26a3:7ac5:3ce2:cb2d:994d:8f10:82b6:419d | {26a3:7ac5:3ce2:cb2d:994d:8f10:82b6:419d,26ad:4d5b:192c:f85a:71db:38be:c6ca:19de} + 26ad:4d5b:192c:f85a:71db:38be:c6ca:19de | {26a3:7ac5:3ce2:cb2d:994d:8f10:82b6:419d,26ad:4d5b:192c:f85a:71db:38be:c6ca:19de} + 28a6:2032:8a38:de85:f6f3:47bd:5124:7dc8 | {28a6:2032:8a38:de85:f6f3:47bd:5124:7dc8} + 28e7:4441:e0a4:bf30:4cf4:edb0:638d:ad72 | {28e7:4441:e0a4:bf30:4cf4:edb0:638d:ad72} + 29a4:a288:457e:57a9:bbb3:2a76:b117:b1e8 | {29a4:a288:457e:57a9:bbb3:2a76:b117:b1e8,29b2:d3c1:26c4:86b6:19b5:14dc:ab2d:bc67} + 29b2:d3c1:26c4:86b6:19b5:14dc:ab2d:bc67 | {29a4:a288:457e:57a9:bbb3:2a76:b117:b1e8,29b2:d3c1:26c4:86b6:19b5:14dc:ab2d:bc67} + 2a8a:5b38:cbdd:5d1c:e1b0:d627:f31f:285a | {2a8a:5b38:cbdd:5d1c:e1b0:d627:f31f:285a} + 2b47:da0e:8c52:cc33:afaa:f85f:f143:88c6 | {2b47:da0e:8c52:cc33:afaa:f85f:f143:88c6} + 2ee9:6428:5482:9721:9e51:ca52:ba3:99eb | {2ee9:6428:5482:9721:9e51:ca52:ba3:99eb} + 2f48:4d4b:443c:6de6:9cbe:9766:fd5:c88b | {2f48:4d4b:443c:6de6:9cbe:9766:fd5:c88b} + 2ff2:b6b6:ffd1:dc5f:fc2:defe:fd16:a414 | {2ff2:b6b6:ffd1:dc5f:fc2:defe:fd16:a414} + 3138:9022:3412:4cfb:fc2a:729a:651c:40f9 | {3138:9022:3412:4cfb:fc2a:729a:651c:40f9} + 318f:1162:8f48:3397:cb9a:f54e:f1e8:d05d | {318f:1162:8f48:3397:cb9a:f54e:f1e8:d05d} + 32ca:6639:c07e:c474:fa11:c83:2886:516c | {32ca:6639:c07e:c474:fa11:c83:2886:516c} + 35f1:eb03:921c:f397:cd41:9201:f7e0:dfad | {35f1:eb03:921c:f397:cd41:9201:f7e0:dfad,35f3:d696:b49e:1a25:375:5e28:15c9:96ce} + 35f3:d696:b49e:1a25:375:5e28:15c9:96ce | {35f1:eb03:921c:f397:cd41:9201:f7e0:dfad,35f3:d696:b49e:1a25:375:5e28:15c9:96ce} + 3902:4c48:d872:37bd:2e53:678d:3a0a:3cf6 | {3902:4c48:d872:37bd:2e53:678d:3a0a:3cf6,390b:b7a:6606:af43:233b:2e27:8336:5b2e} + 390b:b7a:6606:af43:233b:2e27:8336:5b2e | {3902:4c48:d872:37bd:2e53:678d:3a0a:3cf6,390b:b7a:6606:af43:233b:2e27:8336:5b2e} + 39ec:d6ba:1f45:64d0:f4d2:3f0f:78e:a404 | {39ec:d6ba:1f45:64d0:f4d2:3f0f:78e:a404} + 3af7:2de9:30a7:818d:9715:3eaf:d8f7:2583 | {3af7:2de9:30a7:818d:9715:3eaf:d8f7:2583} + 3b13:802b:cfd:15ef:bab3:f337:8b00:5744 | {3b13:802b:cfd:15ef:bab3:f337:8b00:5744} + 3bc9:de98:c700:5aa:d993:223e:dad:1949 | {3bc9:de98:c700:5aa:d993:223e:dad:1949} + 4068:6d06:7463:589:3262:86d1:f1f1:f088 | {4068:6d06:7463:589:3262:86d1:f1f1:f088} + 4111:e35f:ce3:c4de:dc4e:8764:8cd:1686 | {4111:e35f:ce3:c4de:dc4e:8764:8cd:1686} + 4131:d8b6:82af:797d:25fd:7bd4:b94d:ce34 | {4131:d8b6:82af:797d:25fd:7bd4:b94d:ce34} + 42e2:d76f:c784:7a61:67c1:b931:6f49:32c5 | {42e2:d76f:c784:7a61:67c1:b931:6f49:32c5} + 4430:8b98:82c8:3d6c:dbd6:579e:c3fc:ec9d | {4430:8b98:82c8:3d6c:dbd6:579e:c3fc:ec9d,4439:44b6:c04:de6a:c0af:cf35:d9f3:f8ee} + 4439:44b6:c04:de6a:c0af:cf35:d9f3:f8ee | {4430:8b98:82c8:3d6c:dbd6:579e:c3fc:ec9d,4439:44b6:c04:de6a:c0af:cf35:d9f3:f8ee} + 450b:493b:a4d7:f0d3:6fe4:6da0:b550:f4ca | {450b:493b:a4d7:f0d3:6fe4:6da0:b550:f4ca} + 454c:20ee:35b9:b48b:a59f:e4bc:7b76:f228 | {454c:20ee:35b9:b48b:a59f:e4bc:7b76:f228,454e:bfa0:ed21:4983:7572:22c9:413d:d4db} + 454e:bfa0:ed21:4983:7572:22c9:413d:d4db | {454c:20ee:35b9:b48b:a59f:e4bc:7b76:f228,454e:bfa0:ed21:4983:7572:22c9:413d:d4db} + 4620:c642:9985:6a1f:6c66:50c0:2108:10d3 | {4620:c642:9985:6a1f:6c66:50c0:2108:10d3} + 4647:353:5292:8bef:e5b5:c13a:1176:deef | {4647:353:5292:8bef:e5b5:c13a:1176:deef} + 4bd6:2076:745e:acbe:c511:3786:60be:b51d | {4bd6:2076:745e:acbe:c511:3786:60be:b51d} + 4d6a:edd6:a446:6d89:e2a3:ab27:79ec:e148 | {4d6a:edd6:a446:6d89:e2a3:ab27:79ec:e148} + 4ee3:bfaa:5f22:2c05:573e:e87c:a6c2:81e0 | {4ee3:bfaa:5f22:2c05:573e:e87c:a6c2:81e0} + 53ad:31ab:bc5e:c535:bc7c:5762:c11e:fcec | {53ad:31ab:bc5e:c535:bc7c:5762:c11e:fcec} + 53d6:7f94:6b26:59cb:9c16:2aa:9722:b8ef | {53d6:7f94:6b26:59cb:9c16:2aa:9722:b8ef} + 5412:a54d:dbd8:8448:4728:5fb0:ec6f:4381 | {5412:a54d:dbd8:8448:4728:5fb0:ec6f:4381} + 5466:93e3:8343:3686:394:778:79ac:772 | {5466:93e3:8343:3686:394:778:79ac:772} + 54b6:4a85:c1a5:89b0:b7ff:5306:32be:d30f | {54b6:4a85:c1a5:89b0:b7ff:5306:32be:d30f} + 5637:5e57:c050:53fe:e182:697:ab46:21cc | {5637:5e57:c050:53fe:e182:697:ab46:21cc} + 56fd:83db:3ff7:b0b:7d5:8378:a486:f20 | {56fd:83db:3ff7:b0b:7d5:8378:a486:f20} + 5721:3c79:a6ff:c8d8:5e3:c785:808:e40 | {5721:3c79:a6ff:c8d8:5e3:c785:808:e40} + 5889:8398:cb90:8df:b3d6:3f5c:72cb:cd64 | {5889:8398:cb90:8df:b3d6:3f5c:72cb:cd64} + 599b:9e01:9a22:aebf:a731:ce57:fefb:8ed | {599b:9e01:9a22:aebf:a731:ce57:fefb:8ed} + 5a0b:33a9:3407:aa9c:f1c7:a538:2f25:bf14 | {5a0b:33a9:3407:aa9c:f1c7:a538:2f25:bf14} + 5a3f:b436:785f:32a4:8c86:13f8:e682:8b6a | {5a3f:b436:785f:32a4:8c86:13f8:e682:8b6a} + 5d63:9613:7b87:5c26:5c80:bbd3:14b5:1e63 | {5d63:9613:7b87:5c26:5c80:bbd3:14b5:1e63} + 5e52:9aa9:8f83:2a67:5959:720d:f6ba:5d42 | {5e52:9aa9:8f83:2a67:5959:720d:f6ba:5d42} + 5ee2:4fab:1073:b2f5:61c1:eea6:302f:685 | {5ee2:4fab:1073:b2f5:61c1:eea6:302f:685} + 5fa8:25bb:15e8:5b35:758c:2044:d194:1962 | {5fa8:25bb:15e8:5b35:758c:2044:d194:1962} + 61f2:afe0:d1af:18e9:5d40:7a4d:f112:2d09 | {61f2:afe0:d1af:18e9:5d40:7a4d:f112:2d09} + 6251:ab4b:3b37:d71f:6b5f:1b2d:bd55:3a3c | {6251:ab4b:3b37:d71f:6b5f:1b2d:bd55:3a3c} + 62b8:256d:637a:82bf:3b69:420:eea5:300b | {62b8:256d:637a:82bf:3b69:420:eea5:300b} + 62db:eab9:a54e:3cea:46f3:b7c2:cb9c:6e5d | {62db:eab9:a54e:3cea:46f3:b7c2:cb9c:6e5d} + 6656:e87d:865c:3237:8d42:ff01:a82b:f308 | {6656:e87d:865c:3237:8d42:ff01:a82b:f308} + 6a93:ccd3:5002:233f:1c5f:400e:601c:75a | {6a93:ccd3:5002:233f:1c5f:400e:601c:75a} + 6b0c:4791:ccea:c286:437e:d268:87ef:b6ad | {6b0c:4791:ccea:c286:437e:d268:87ef:b6ad} + 6e1b:5e9c:f623:6134:7754:fdac:323a:dba2 | {6e1b:5e9c:f623:6134:7754:fdac:323a:dba2} + 6e81:4a6a:d383:140d:8416:c09b:af3b:5b45 | {6e81:4a6a:d383:140d:8416:c09b:af3b:5b45} + 6e9d:66e:27c5:c7c4:aefe:ecfc:6568:ccf | {6e9d:66e:27c5:c7c4:aefe:ecfc:6568:ccf} + 6ff2:94f5:5755:164d:1301:28ce:8a04:eac0 | {6ff2:94f5:5755:164d:1301:28ce:8a04:eac0} + 72c4:104f:960c:baf1:8ef7:60d2:c58:8b03 | {72c4:104f:960c:baf1:8ef7:60d2:c58:8b03} + 7341:d21f:e576:f226:f690:a99c:6b55:9933 | {7341:d21f:e576:f226:f690:a99c:6b55:9933} + 739b:8093:31c6:a42f:a604:d5cb:1350:2d2f | {739b:8093:31c6:a42f:a604:d5cb:1350:2d2f} + 7524:1f76:fe52:991e:667b:a302:dfd5:dbd6 | {7524:1f76:fe52:991e:667b:a302:dfd5:dbd6} + 7608:50bf:a29a:6805:c760:9ae3:1216:8e4a | {7608:50bf:a29a:6805:c760:9ae3:1216:8e4a} + 78c8:1cde:4b95:55d8:b211:a95d:37e0:7d92 | {78c8:1cde:4b95:55d8:b211:a95d:37e0:7d92} + 7924:9e5b:2c7:3920:9c9f:bfb6:369d:fa4f | {7924:9e5b:2c7:3920:9c9f:bfb6:369d:fa4f} + 798f:ea8:61f6:5d79:1656:d8d8:9b6e:57f0 | {798f:ea8:61f6:5d79:1656:d8d8:9b6e:57f0} + 79c9:d301:92cd:c774:abbb:2f7d:92c3:3ccd | {79c9:d301:92cd:c774:abbb:2f7d:92c3:3ccd} + 79eb:6133:5173:8f43:87d4:cb1d:906b:e8c9 | {79eb:6133:5173:8f43:87d4:cb1d:906b:e8c9} + 7cba:a835:f850:6409:dba7:1300:f2b8:1db3 | {7cba:a835:f850:6409:dba7:1300:f2b8:1db3} + 7cdf:1ed8:690e:9e54:6f39:613e:f187:8ef2 | {7cdf:1ed8:690e:9e54:6f39:613e:f187:8ef2} + 7dcc:877b:8e07:aeb4:d891:581e:c10c:af54 | {7dcc:877b:8e07:aeb4:d891:581e:c10c:af54} + 7e1f:eb76:49c9:39f8:deb9:c447:b40c:a13d | {7e1f:eb76:49c9:39f8:deb9:c447:b40c:a13d} + 7ec8:2b00:5994:7f0f:d765:5e16:c274:5645 | {7ec8:2b00:5994:7f0f:d765:5e16:c274:5645} + 7f3d:d8ea:7a7c:8700:5b81:412f:c33a:d6ba | {7f3d:d8ea:7a7c:8700:5b81:412f:c33a:d6ba} + 7fa2:dbdb:e889:e24b:4d30:962e:89f3:676f | {7fa2:dbdb:e889:e24b:4d30:962e:89f3:676f} + 8119:1220:b888:3d8a:1250:ce77:b2b9:bdcd | {8119:1220:b888:3d8a:1250:ce77:b2b9:bdcd} + 8129:3e9c:70ff:1df1:f26f:86aa:c7ba:8245 | {8129:3e9c:70ff:1df1:f26f:86aa:c7ba:8245} + 8172:4609:d700:5bd2:24a2:8f78:f1cc:c1a0 | {8172:4609:d700:5bd2:24a2:8f78:f1cc:c1a0} + 8241:abe3:7537:de41:ef5a:7d2a:9e57:833b | {8241:abe3:7537:de41:ef5a:7d2a:9e57:833b} + 828e:fa1d:9bb1:ad4c:4874:9da8:40bf:25b5 | {828e:fa1d:9bb1:ad4c:4874:9da8:40bf:25b5,8298:9399:271f:a3fe:270c:21cf:7c34:7340} + 8298:9399:271f:a3fe:270c:21cf:7c34:7340 | {828e:fa1d:9bb1:ad4c:4874:9da8:40bf:25b5,8298:9399:271f:a3fe:270c:21cf:7c34:7340} + 82ed:ac69:4ea7:5301:b005:3e17:f541:4fbc | {82ed:ac69:4ea7:5301:b005:3e17:f541:4fbc} + 8357:a24:2f6e:f909:3853:899a:68af:b48 | {8357:a24:2f6e:f909:3853:899a:68af:b48} + 8474:e00a:5b49:6e2a:5074:ecd5:cece:7dad | {8474:e00a:5b49:6e2a:5074:ecd5:cece:7dad} + 84fe:7351:7b39:349e:1bb7:e333:daec:141a | {84fe:7351:7b39:349e:1bb7:e333:daec:141a} + 8586:595:7bdd:359b:2fd9:1ffa:49ef:a947 | {8586:595:7bdd:359b:2fd9:1ffa:49ef:a947} + 86fa:3a3:6a26:5ce3:fd8d:6267:b3c:4bf0 | {86fa:3a3:6a26:5ce3:fd8d:6267:b3c:4bf0} + 874b:a74e:e292:c13:cf80:778c:35b4:d37c | {874b:a74e:e292:c13:cf80:778c:35b4:d37c} + 88bb:cf40:1f19:c897:f001:2d56:8f4f:ac68 | {88bb:cf40:1f19:c897:f001:2d56:8f4f:ac68} + 8909:5e3:cff9:483c:1fb7:2ee2:ab05:222a | {8909:5e3:cff9:483c:1fb7:2ee2:ab05:222a,890b:aa44:e2b1:ff61:eb7a:c4df:5a25:2eaf} + 890b:aa44:e2b1:ff61:eb7a:c4df:5a25:2eaf | {8909:5e3:cff9:483c:1fb7:2ee2:ab05:222a,890b:aa44:e2b1:ff61:eb7a:c4df:5a25:2eaf} + 8a1f:674e:63cd:f241:8f53:aec9:d8db:8e5c | {8a1f:674e:63cd:f241:8f53:aec9:d8db:8e5c} + 8b0c:b103:3302:90bb:bac:809e:9c7d:3569 | {8b0c:b103:3302:90bb:bac:809e:9c7d:3569} + 8b61:6b31:d02c:87d3:22cf:f01c:c045:b822 | {8b61:6b31:d02c:87d3:22cf:f01c:c045:b822} + 8b87:864a:8e83:6783:c552:cb07:8e96:c0e5 | {8b87:864a:8e83:6783:c552:cb07:8e96:c0e5} + 8c86:2c19:c38d:626b:b5a4:e0cb:bbaf:476b | {8c86:2c19:c38d:626b:b5a4:e0cb:bbaf:476b} + 8ec2:3493:ad95:cb7e:ae1c:8c2c:6a34:eccb | {8ec2:3493:ad95:cb7e:ae1c:8c2c:6a34:eccb,8ecc:14db:7aba:bbde:f2a7:c4bc:7a1e:c8c1} + 8ecc:14db:7aba:bbde:f2a7:c4bc:7a1e:c8c1 | {8ec2:3493:ad95:cb7e:ae1c:8c2c:6a34:eccb,8ecc:14db:7aba:bbde:f2a7:c4bc:7a1e:c8c1} + 8f7a:5e8b:f526:a8ba:8c6f:3cae:7b7e:1a5 | {8f7a:5e8b:f526:a8ba:8c6f:3cae:7b7e:1a5} + 8fa1:e604:6ad4:c318:ba8f:eaec:76be:ad4b | {8fa1:e604:6ad4:c318:ba8f:eaec:76be:ad4b,8fac:3b7e:463d:1b38:2f59:6fdf:3bef:4aaf} + 8fac:3b7e:463d:1b38:2f59:6fdf:3bef:4aaf | {8fa1:e604:6ad4:c318:ba8f:eaec:76be:ad4b,8fac:3b7e:463d:1b38:2f59:6fdf:3bef:4aaf} + 933f:d5b:d307:c3e0:5e0:b947:1cb5:6928 | {933f:d5b:d307:c3e0:5e0:b947:1cb5:6928} + 9520:88f9:9498:8a73:ac7a:dc77:4495:3dfc | {9520:88f9:9498:8a73:ac7a:dc77:4495:3dfc} + 9631:3557:7591:6ade:1882:6dad:8413:c3b3 | {9631:3557:7591:6ade:1882:6dad:8413:c3b3} + 977b:de6f:3ef9:3cad:fb02:fb07:458c:e88e | {977b:de6f:3ef9:3cad:fb02:fb07:458c:e88e} + 982a:e6d8:49bc:49a7:80b:4417:45f7:4fb7 | {982a:e6d8:49bc:49a7:80b:4417:45f7:4fb7} + 9943:4095:cf6c:bf1d:f1b4:7883:f929:a315 | {9943:4095:cf6c:bf1d:f1b4:7883:f929:a315} + 99b7:bba0:206c:6042:6778:2f3b:9a:6393 | {99b7:bba0:206c:6042:6778:2f3b:9a:6393} + 9b3d:56d7:b18e:21b9:7448:3cea:2ec:77f8 | {9b3d:56d7:b18e:21b9:7448:3cea:2ec:77f8} + 9c51:8c1b:a051:a87e:c65a:cc8:a38e:4953 | {9c51:8c1b:a051:a87e:c65a:cc8:a38e:4953} + 9d35:9c4f:517d:2391:f59c:af03:1681:6d9b | {9d35:9c4f:517d:2391:f59c:af03:1681:6d9b} + 9da1:e3ce:660a:cde4:7576:554:55cc:38ad | {9da1:e3ce:660a:cde4:7576:554:55cc:38ad} + 9ee9:65bd:81d2:b2c6:c3c4:b36b:16a2:fc9e | {9ee9:65bd:81d2:b2c6:c3c4:b36b:16a2:fc9e} + a0d3:f0b5:7a50:2d3e:923e:3832:76c0:b15d | {a0d3:f0b5:7a50:2d3e:923e:3832:76c0:b15d} + a252:248:a123:3287:680f:a67c:2fcd:b2a0 | {a252:248:a123:3287:680f:a67c:2fcd:b2a0} + a300:d184:bf44:e8f1:4a80:723c:909:f178 | {a300:d184:bf44:e8f1:4a80:723c:909:f178} + a335:f1a7:be5c:b341:5325:e8d3:2631:74ae | {a335:f1a7:be5c:b341:5325:e8d3:2631:74ae} + a42d:662e:1816:1fe3:a392:9190:7d4e:f418 | {a42d:662e:1816:1fe3:a392:9190:7d4e:f418} + a52f:f73a:413e:a43a:5000:cd8f:ef1f:3603 | {a52f:f73a:413e:a43a:5000:cd8f:ef1f:3603} + a75b:c708:8e74:b252:f8e8:7269:c214:dc07 | {a75b:c708:8e74:b252:f8e8:7269:c214:dc07} + a87b:8920:6e0:9c1b:92a8:3a1e:f074:1ee2 | {a87b:8920:6e0:9c1b:92a8:3a1e:f074:1ee2,a884:9796:ca7c:ec37:9cb4:4158:ce4c:ced5} + a884:9796:ca7c:ec37:9cb4:4158:ce4c:ced5 | {a87b:8920:6e0:9c1b:92a8:3a1e:f074:1ee2,a884:9796:ca7c:ec37:9cb4:4158:ce4c:ced5} + a9e9:74a5:864a:dfeb:a5f0:4424:d294:95a1 | {a9e9:74a5:864a:dfeb:a5f0:4424:d294:95a1} + ac4c:23a6:9c5f:8a2a:ccfc:ea69:48cd:dffc | {ac4c:23a6:9c5f:8a2a:ccfc:ea69:48cd:dffc} + ac71:fd2c:4352:c28a:2f4b:3cd1:4d6f:927b | {ac71:fd2c:4352:c28a:2f4b:3cd1:4d6f:927b} + ad73:992f:b3d8:31f7:306d:a418:fdcf:3e60 | {ad73:992f:b3d8:31f7:306d:a418:fdcf:3e60} + ae64:d6a3:11d7:b6bc:aa3:60c6:b16f:4305 | {ae64:d6a3:11d7:b6bc:aa3:60c6:b16f:4305} + af5a:6507:2c50:f0a8:b211:fc0d:425e:bd47 | {af5a:6507:2c50:f0a8:b211:fc0d:425e:bd47} + afeb:a771:735e:1a18:9297:e9f4:2e53:c5e1 | {afeb:a771:735e:1a18:9297:e9f4:2e53:c5e1} + b105:5518:a963:9a0a:d10d:b42b:dfd1:96a2 | {b105:5518:a963:9a0a:d10d:b42b:dfd1:96a2,b113:66f:e222:f032:7161:1f27:b080:2111} + b113:66f:e222:f032:7161:1f27:b080:2111 | {b105:5518:a963:9a0a:d10d:b42b:dfd1:96a2,b113:66f:e222:f032:7161:1f27:b080:2111} + b218:c6f2:4929:7d70:8b4d:5458:fc85:d0fc | {b218:c6f2:4929:7d70:8b4d:5458:fc85:d0fc} + b237:dac3:62d7:725e:d772:c88c:af71:cec5 | {b237:dac3:62d7:725e:d772:c88c:af71:cec5} + b310:3d72:ea86:6ee:45fc:d57f:4a7a:bb43 | {b310:3d72:ea86:6ee:45fc:d57f:4a7a:bb43} + b3da:187b:cc2e:3c78:e060:aab6:63cb:1780 | {b3da:187b:cc2e:3c78:e060:aab6:63cb:1780} + b408:9874:22a3:9f56:35f:cfd1:b00:ddac | {b408:9874:22a3:9f56:35f:cfd1:b00:ddac} + b48c:eccb:32f4:2b4:e2ee:e787:a16f:8647 | {b48c:eccb:32f4:2b4:e2ee:e787:a16f:8647} + b8ef:17e2:febe:431d:9d8c:88c6:6604:a678 | {b8ef:17e2:febe:431d:9d8c:88c6:6604:a678} + ba0d:d2d4:b5e3:573f:98f4:98e:aac1:47fa | {ba0d:d2d4:b5e3:573f:98f4:98e:aac1:47fa} + baf9:2948:a8a1:8865:912a:839f:45e8:78d3 | {baf9:2948:a8a1:8865:912a:839f:45e8:78d3} + bb1b:6a20:8513:14e4:5fc6:c0e9:17df:9c0 | {bb1b:6a20:8513:14e4:5fc6:c0e9:17df:9c0} + bc1d:d3ba:50da:14d3:f496:6847:3b91:2830 | {bc1d:d3ba:50da:14d3:f496:6847:3b91:2830} + bc52:8171:9377:d593:1c0a:75e4:e2d:5e1a | {bc52:8171:9377:d593:1c0a:75e4:e2d:5e1a} + bd6f:44b9:45d3:529f:84c7:612:b25c:aaf8 | {bd6f:44b9:45d3:529f:84c7:612:b25c:aaf8} + bdc5:94f5:8249:7120:8132:ca25:d3fc:c394 | {bdc5:94f5:8249:7120:8132:ca25:d3fc:c394} + c0fc:f3ee:3707:19dc:62c1:5c9a:df3d:1b58 | {c0fc:f3ee:3707:19dc:62c1:5c9a:df3d:1b58} + c2e3:4cea:30dd:cb39:c5a0:86e7:8b05:3f7 | {c2e3:4cea:30dd:cb39:c5a0:86e7:8b05:3f7} + c36f:f4fd:4853:a07c:c25d:349f:3af4:3432 | {c36f:f4fd:4853:a07c:c25d:349f:3af4:3432} + c504:481e:2756:3ca2:f0c:a26a:4e64:7804 | {c504:481e:2756:3ca2:f0c:a26a:4e64:7804} + c6ff:8d3c:d2d1:ee46:65ca:27f9:cc07:8e6d | {c6ff:8d3c:d2d1:ee46:65ca:27f9:cc07:8e6d} + c8c0:5117:331a:f029:8d24:6775:fe7d:5976 | {c8c0:5117:331a:f029:8d24:6775:fe7d:5976} + c963:10d0:1586:d1d4:79bc:d7af:5486:43e5 | {c963:10d0:1586:d1d4:79bc:d7af:5486:43e5} + c99c:bd43:6161:d17d:2fdd:ab61:922:ba62 | {c99c:bd43:6161:d17d:2fdd:ab61:922:ba62} + cb2f:b8da:ba34:1c5c:4839:710a:f75b:bdd0 | {cb2f:b8da:ba34:1c5c:4839:710a:f75b:bdd0} + cb70:a0cc:6919:db7f:8fc8:cb69:6fcc:5f5b | {cb70:a0cc:6919:db7f:8fc8:cb69:6fcc:5f5b} + cc17:3814:d80f:41a1:1309:35d3:ea0a:d31e | {cc17:3814:d80f:41a1:1309:35d3:ea0a:d31e} + ce47:e5eb:41f3:23af:6209:5ade:82ce:3b00 | {ce47:e5eb:41f3:23af:6209:5ade:82ce:3b00} + cfb9:d37e:2427:af8d:b728:8f90:f54c:9141 | {cfb9:d37e:2427:af8d:b728:8f90:f54c:9141} + d066:f25b:e8a5:4ae6:4c99:2a98:8cb7:2530 | {d066:f25b:e8a5:4ae6:4c99:2a98:8cb7:2530} + d105:1597:c912:51c7:e5b6:f628:cae:1d0f | {d105:1597:c912:51c7:e5b6:f628:cae:1d0f} + d2de:7aa1:975:e510:dfa1:2a3:89bc:eedb | {d2de:7aa1:975:e510:dfa1:2a3:89bc:eedb} + d33e:e847:b4c6:d5ca:f75:216b:342c:3d04 | {d33e:e847:b4c6:d5ca:f75:216b:342c:3d04} + d395:c008:43a4:48d9:15a7:ce74:6546:c56b | {d395:c008:43a4:48d9:15a7:ce74:6546:c56b} + d452:6fb9:f2b0:d387:80ca:47d5:330f:577 | {d452:6fb9:f2b0:d387:80ca:47d5:330f:577} + d524:77db:2a21:e05b:68c4:575c:f04b:b0b7 | {d524:77db:2a21:e05b:68c4:575c:f04b:b0b7} + d6d1:e96c:cd2f:8396:23f2:c96d:9376:54cb | {d6d1:e96c:cd2f:8396:23f2:c96d:9376:54cb} + d76b:986d:d38b:252a:e6a2:254e:b0f7:db24 | {d76b:986d:d38b:252a:e6a2:254e:b0f7:db24} + d9f3:2018:6aa2:7ee4:64be:e2d:c32c:2d15 | {d9f3:2018:6aa2:7ee4:64be:e2d:c32c:2d15} + da3e:c57c:ccc8:edbf:f66e:85a5:e252:a3a4 | {da3e:c57c:ccc8:edbf:f66e:85a5:e252:a3a4} + da52:3791:27b8:f773:7a59:1414:6d76:bd8a | {da52:3791:27b8:f773:7a59:1414:6d76:bd8a} + da97:ecc5:bf17:1bb2:5710:f753:604c:7cf6 | {da97:ecc5:bf17:1bb2:5710:f753:604c:7cf6} + dc61:8bf4:4b82:90a4:8af0:6a43:a917:14ee | {dc61:8bf4:4b82:90a4:8af0:6a43:a917:14ee} + dd3b:ad95:1e55:a555:daae:8218:99d7:7bce | {dd3b:ad95:1e55:a555:daae:8218:99d7:7bce} + defd:c729:62b4:8959:6ad1:7b1f:5835:8ffb | {defd:c729:62b4:8959:6ad1:7b1f:5835:8ffb} + dfe2:c097:49ae:1d60:e3db:26c1:bb5d:c4e0 | {dfe2:c097:49ae:1d60:e3db:26c1:bb5d:c4e0} + e11c:4f21:dd57:c814:af4e:3f55:4adf:f1a0 | {e11c:4f21:dd57:c814:af4e:3f55:4adf:f1a0} + e199:2ea0:f3b4:3a31:5d15:dfc9:68cd:c948 | {e199:2ea0:f3b4:3a31:5d15:dfc9:68cd:c948} + e57b:76e8:3f3a:3020:a22a:38b7:9c02:5db4 | {e57b:76e8:3f3a:3020:a22a:38b7:9c02:5db4} + e6da:dc3c:a935:a718:4744:a216:84bd:cfa9 | {e6da:dc3c:a935:a718:4744:a216:84bd:cfa9} + e7a7:adbe:d6de:41ba:a34f:d10b:46a7:a4cf | {e7a7:adbe:d6de:41ba:a34f:d10b:46a7:a4cf} + e86d:edb4:8702:1774:c97d:cbee:394:a083 | {e86d:edb4:8702:1774:c97d:cbee:394:a083} + e97f:c466:f346:cf67:23e4:bd36:72be:af44 | {e97f:c466:f346:cf67:23e4:bd36:72be:af44} + ec36:7c6d:3077:267e:399a:d47:55a4:218a | {ec36:7c6d:3077:267e:399a:d47:55a4:218a} + ee1d:a078:25d4:94e3:9a89:707d:6fae:7573 | {ee1d:a078:25d4:94e3:9a89:707d:6fae:7573} + ee34:9ba:9281:593c:ab74:57fa:e439:e0f3 | {ee34:9ba:9281:593c:ab74:57fa:e439:e0f3} + ee76:e9ac:dd2:66c1:380:5f1e:1c4d:2867 | {ee76:e9ac:dd2:66c1:380:5f1e:1c4d:2867} + eea0:9aef:71b:3cfd:e2ad:864c:41b8:938c | {eea0:9aef:71b:3cfd:e2ad:864c:41b8:938c} + ef15:3aa9:3c5b:b993:5209:a130:2d37:3a64 | {ef15:3aa9:3c5b:b993:5209:a130:2d37:3a64} + ef9a:b980:e9:d50a:d867:8a88:2cae:8aa1 | {ef9a:b980:e9:d50a:d867:8a88:2cae:8aa1} + effb:1a90:1dd5:e52c:1d7f:c716:3744:170a | {effb:1a90:1dd5:e52c:1d7f:c716:3744:170a} + f0a1:e730:68b9:2e1c:649a:5450:a256:4665 | {f0a1:e730:68b9:2e1c:649a:5450:a256:4665} + f3df:f155:d5c6:d664:c93c:13fa:9d77:6bf2 | {f3df:f155:d5c6:d664:c93c:13fa:9d77:6bf2} + f499:668f:fbb8:f0dc:8e41:d43b:c025:26a | {f499:668f:fbb8:f0dc:8e41:d43b:c025:26a} + f57a:a3dc:3b11:f28a:8b25:8d5b:ec2f:c729 | {f57a:a3dc:3b11:f28a:8b25:8d5b:ec2f:c729} + f7b8:dfc:496c:9718:ae3c:5c3e:b98a:4c5f | {f7b8:dfc:496c:9718:ae3c:5c3e:b98a:4c5f} + fa78:68ce:4fb1:d54c:2007:1820:ffe2:8235 | {fa78:68ce:4fb1:d54c:2007:1820:ffe2:8235} + fbb6:2d70:42eb:55ab:6235:6867:2b3:8d47 | {fbb6:2d70:42eb:55ab:6235:6867:2b3:8d47} + fcea:f739:a97d:cefc:49c4:b3c3:c7b4:99d6 | {fcea:f739:a97d:cefc:49c4:b3c3:c7b4:99d6} + fda3:3e75:37c5:c1f:912b:5e32:6aa9:aeb2 | {fda3:3e75:37c5:c1f:912b:5e32:6aa9:aeb2} + ff3d:7d5b:b0fe:c30:9e6c:23e0:7b5:e9de | {ff3d:7d5b:b0fe:c30:9e6c:23e0:7b5:e9de,ff4a:cbbf:695a:9e46:f27c:e1be:861f:9e7} + ff4a:cbbf:695a:9e46:f27c:e1be:861f:9e7 | {ff3d:7d5b:b0fe:c30:9e6c:23e0:7b5:e9de,ff4a:cbbf:695a:9e46:f27c:e1be:861f:9e7} + ff6b:af36:5fc2:93d9:ebf3:3c62:a19f:307f | {ff6b:af36:5fc2:93d9:ebf3:3c62:a19f:307f} +(256 rows) + +-- errors +select a4, + array_agg(a4) over (order by a4 range between -33 preceding and -33 following) + from ipaddrs + where a4 is not null; +ERROR: invalid preceding or following size in window function +DETAIL: Offset value -33 is outside the range -32 to 4294967295 +select a6, + array_agg(a6) over (order by a6 range between -129 preceding and -129 following) + from ipaddrs + where a6 is not null; +ERROR: invalid preceding or following size in window function +DETAIL: Offset value -129 is outside the range -128 to 2^63-1 +-- end diff -Nru ip4r-2.3/.gitattributes ip4r-2.4/.gitattributes --- ip4r-2.3/.gitattributes 1970-01-01 00:00:00.000000000 +0000 +++ ip4r-2.4/.gitattributes 2018-11-21 06:35:30.000000000 +0000 @@ -0,0 +1,10 @@ +# gitattributes +* whitespace=space-before-tab,trailing-space +*.[chly] whitespace=space-before-tab,trailing-space,indent-with-non-tab,tabwidth=4 +*.[ch] linguist-language=C + +src/*.h linguist-language=C +src/*.c linguist-language=C + +# Test output files that contain extra whitespace +*.out -whitespace diff -Nru ip4r-2.3/.gitignore ip4r-2.4/.gitignore --- ip4r-2.3/.gitignore 2018-05-24 21:30:28.000000000 +0000 +++ ip4r-2.4/.gitignore 2018-11-21 06:35:30.000000000 +0000 @@ -22,3 +22,4 @@ /ip4r.sql.in /sql/ip4r-legacy.sql /expected/ip4r-legacy.out +/build*/ diff -Nru ip4r-2.3/ip4r--2.0--2.1.sql ip4r-2.4/ip4r--2.0--2.1.sql --- ip4r-2.3/ip4r--2.0--2.1.sql 2018-05-24 21:30:28.000000000 +0000 +++ ip4r-2.4/ip4r--2.0--2.1.sql 1970-01-01 00:00:00.000000000 +0000 @@ -1,70 +0,0 @@ -/* ip4r--2.0--2.1.sql */ - --- complain if script is sourced in psql, rather than via ALTER EXTENSION -\echo Use "ALTER EXTENSION ip4r UPDATE TO '2.1'" to load this file. \quit - --- ugh. no ALTER CAST - -UPDATE pg_catalog.pg_cast SET castcontext = 'a' - WHERE (castsource,casttarget) IN ( - ('ipaddress'::regtype, 'ip4'::regtype), - ('ipaddress'::regtype, 'ip6'::regtype), - ('iprange'::regtype, 'ip4r'::regtype), - ('iprange'::regtype, 'ip6r'::regtype)); - --- double ugh, to finally fix long-standing issue with function signature --- of gist consistent functions - -WITH v(gname,gtype) AS ( - VALUES ('gip4r_consistent'::name, 'ip4r'::regtype), - ('gip6r_consistent'::name, 'ip6r'::regtype), - ('gipr_consistent'::name, 'iprange'::regtype)) -UPDATE pg_catalog.pg_proc - SET pronargs = 5, - proargtypes = array_to_string(array['internal', - v.gtype, - 'int2', - 'oid', - 'internal']::regtype[]::oid[], - ' ')::pg_catalog.oidvector - FROM v - WHERE proname = v.gname - AND probin = 'MODULE_PATHNAME'; - --- actual new stuff - -CREATE FUNCTION gip4r_fetch(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE FUNCTION gip6r_fetch(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE FUNCTION gipr_fetch(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; - -DO $s$ - BEGIN - IF current_setting('server_version_num')::integer >= 90500 THEN - ALTER OPERATOR FAMILY gist_ip4r_ops USING gist ADD - FUNCTION 9 (ip4r,ip4r) gip4r_fetch (internal); - ALTER OPERATOR FAMILY gist_ip6r_ops USING gist ADD - FUNCTION 9 (ip6r,ip6r) gip6r_fetch (internal); - ALTER OPERATOR FAMILY gist_iprange_ops USING gist ADD - FUNCTION 9 (iprange,iprange) gipr_fetch (internal); - END IF; - IF current_setting('server_version_num')::integer >= 90600 THEN - DECLARE - r record; - BEGIN - FOR r IN SELECT oid::regprocedure as fsig - FROM pg_catalog.pg_proc - WHERE (probin = 'MODULE_PATHNAME' - AND prolang = (SELECT oid FROM pg_catalog.pg_language l WHERE l.lanname='c')) - OR (oid in ('family(ip4)'::regprocedure, - 'family(ip6)'::regprocedure, - 'family(ip4r)'::regprocedure, - 'family(ip6r)'::regprocedure)) - LOOP - EXECUTE format('ALTER FUNCTION %s PARALLEL SAFE', r.fsig); - END LOOP; - END; - END IF; - END; -$s$; - --- end diff -Nru ip4r-2.3/ip4r--2.1--2.2.sql ip4r-2.4/ip4r--2.1--2.2.sql --- ip4r-2.3/ip4r--2.1--2.2.sql 2018-05-24 21:30:28.000000000 +0000 +++ ip4r-2.4/ip4r--2.1--2.2.sql 1970-01-01 00:00:00.000000000 +0000 @@ -1,25 +0,0 @@ -/* ip4r--2.1--2.2.sql */ - --- complain if script is sourced in psql, rather than via ALTER EXTENSION -\echo Use "ALTER EXTENSION ip4r UPDATE TO '2.2'" to load this file. \quit - --- There's nothing actually new in this version, but it fixes an --- incorrect fix in 2.1. - -WITH v(gname,gtype) AS ( - VALUES ('gip4r_consistent'::name, 'ip4r'::regtype), - ('gip6r_consistent'::name, 'ip6r'::regtype), - ('gipr_consistent'::name, 'iprange'::regtype)) -UPDATE pg_catalog.pg_proc - SET pronargs = 5, - proargtypes = array_to_string(array['internal', - v.gtype, - 'int2', - 'oid', - 'internal']::regtype[]::oid[], - ' ')::pg_catalog.oidvector - FROM v - WHERE proname = v.gname - AND probin = 'MODULE_PATHNAME'; - --- end diff -Nru ip4r-2.3/ip4r--2.2.sql ip4r-2.4/ip4r--2.2.sql --- ip4r-2.3/ip4r--2.2.sql 2018-05-24 21:30:28.000000000 +0000 +++ ip4r-2.4/ip4r--2.2.sql 1970-01-01 00:00:00.000000000 +0000 @@ -1,791 +0,0 @@ --- ip4r extension - --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "CREATE EXTENSION ip4r" to load this file. \quit - --- ---------------------------------------------------------------------- --- Type definitions - --- type creation is needlessly chatty - -CREATE TYPE ip4; - -CREATE FUNCTION ip4_in(cstring) RETURNS ip4 AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip4_out(ip4) RETURNS cstring AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip4_recv(internal) RETURNS ip4 AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip4_send(ip4) RETURNS bytea AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -CREATE TYPE ip4 ( - INPUT = ip4_in, OUTPUT = ip4_out, - RECEIVE = ip4_recv, SEND = ip4_send, - INTERNALLENGTH = 4, ALIGNMENT = int4, PASSEDBYVALUE -); - -COMMENT ON TYPE ip4 IS 'IPv4 address ''#.#.#.#'''; - -CREATE TYPE ip4r; - -CREATE FUNCTION ip4r_in(cstring) RETURNS ip4r AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip4r_out(ip4r) RETURNS cstring AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip4r_recv(internal) RETURNS ip4r AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip4r_send(ip4r) RETURNS bytea AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -CREATE TYPE ip4r ( - INPUT = ip4r_in, OUTPUT = ip4r_out, - RECEIVE = ip4r_recv, SEND = ip4r_send, - INTERNALLENGTH = 8, ALIGNMENT = int4 -); - -COMMENT ON TYPE ip4r IS 'IPv4 range ''#.#.#.#-#.#.#.#'' or ''#.#.#.#/#'' or ''#.#.#.#'''; - -CREATE TYPE ip6; - -CREATE FUNCTION ip6_in(cstring) RETURNS ip6 AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6_out(ip6) RETURNS cstring AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6_recv(internal) RETURNS ip6 AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6_send(ip6) RETURNS bytea AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -CREATE TYPE ip6 ( - INPUT = ip6_in, OUTPUT = ip6_out, - RECEIVE = ip6_recv, SEND = ip6_send, - INTERNALLENGTH = 16, ALIGNMENT = double -); - -COMMENT ON TYPE ip6 IS 'IPv6 address ''xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx'''; - -CREATE TYPE ip6r; - -CREATE FUNCTION ip6r_in(cstring) RETURNS ip6r AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6r_out(ip6r) RETURNS cstring AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6r_recv(internal) RETURNS ip6r AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6r_send(ip6r) RETURNS bytea AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -CREATE TYPE ip6r ( - INPUT = ip6r_in, OUTPUT = ip6r_out, - RECEIVE = ip6r_recv, SEND = ip6r_send, - INTERNALLENGTH = 32, ALIGNMENT = double -); - -COMMENT ON TYPE ip6r IS 'IPv6 range ''#-#'' or ''#/#'' or ''#'''; - -CREATE TYPE ipaddress; - -CREATE FUNCTION ipaddress_in(cstring) RETURNS ipaddress AS 'MODULE_PATHNAME','ipaddr_in' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ipaddress_out(ipaddress) RETURNS cstring AS 'MODULE_PATHNAME','ipaddr_out' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ipaddress_recv(internal) RETURNS ipaddress AS 'MODULE_PATHNAME','ipaddr_recv' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ipaddress_send(ipaddress) RETURNS bytea AS 'MODULE_PATHNAME','ipaddr_send' LANGUAGE C IMMUTABLE STRICT; - -CREATE TYPE ipaddress ( - INPUT = ipaddress_in, OUTPUT = ipaddress_out, - RECEIVE = ipaddress_recv, SEND = ipaddress_send, - INTERNALLENGTH = VARIABLE, ALIGNMENT = int4, STORAGE = main -); - -COMMENT ON TYPE ipaddress IS 'IPv4 or IPv6 address'; - -CREATE TYPE iprange; - -CREATE FUNCTION iprange_in(cstring) RETURNS iprange AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange_out(iprange) RETURNS cstring AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange_recv(internal) RETURNS iprange AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange_send(iprange) RETURNS bytea AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -CREATE TYPE iprange ( - INPUT = iprange_in, OUTPUT = iprange_out, - RECEIVE = iprange_recv, SEND = iprange_send, - INTERNALLENGTH = VARIABLE, ALIGNMENT = int4, STORAGE = main -); - -COMMENT ON TYPE iprange IS 'IPv4 or IPv6 range'; - --- ---------------------------------------------------------------------- --- Cast functions (inward) - -CREATE FUNCTION ip4(bigint) RETURNS ip4 AS 'MODULE_PATHNAME','ip4_cast_from_bigint' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip4(double precision) RETURNS ip4 AS 'MODULE_PATHNAME','ip4_cast_from_double' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip4(numeric) RETURNS ip4 AS 'MODULE_PATHNAME','ip4_cast_from_numeric' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip4(inet) RETURNS ip4 AS 'MODULE_PATHNAME','ip4_cast_from_inet' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip4(text) RETURNS ip4 AS 'MODULE_PATHNAME','ip4_cast_from_text' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip4(ipaddress) RETURNS ip4 AS 'MODULE_PATHNAME','ipaddr_cast_to_ip4' LANGUAGE C IMMUTABLE STRICT; - -CREATE FUNCTION ip6(numeric) RETURNS ip6 AS 'MODULE_PATHNAME','ip6_cast_from_numeric' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6(inet) RETURNS ip6 AS 'MODULE_PATHNAME','ip6_cast_from_inet' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6(text) RETURNS ip6 AS 'MODULE_PATHNAME','ip6_cast_from_text' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6(ipaddress) RETURNS ip6 AS 'MODULE_PATHNAME','ipaddr_cast_to_ip6' LANGUAGE C IMMUTABLE STRICT; - -CREATE FUNCTION ipaddress(inet) RETURNS ipaddress AS 'MODULE_PATHNAME','ipaddr_cast_from_inet' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ipaddress(ip4) RETURNS ipaddress AS 'MODULE_PATHNAME','ipaddr_cast_from_ip4' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ipaddress(ip6) RETURNS ipaddress AS 'MODULE_PATHNAME','ipaddr_cast_from_ip6' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ipaddress(text) RETURNS ipaddress AS 'MODULE_PATHNAME','ipaddr_cast_from_text' LANGUAGE C IMMUTABLE STRICT; - -CREATE FUNCTION ip4r(cidr) RETURNS ip4r AS 'MODULE_PATHNAME','ip4r_cast_from_cidr' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip4r(ip4) RETURNS ip4r AS 'MODULE_PATHNAME','ip4r_cast_from_ip4' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip4r(text) RETURNS ip4r AS 'MODULE_PATHNAME','ip4r_cast_from_text' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip4r(iprange) RETURNS ip4r AS 'MODULE_PATHNAME','iprange_cast_to_ip4r' LANGUAGE C IMMUTABLE STRICT; - -CREATE FUNCTION ip6r(cidr) RETURNS ip6r AS 'MODULE_PATHNAME','ip6r_cast_from_cidr' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6r(ip6) RETURNS ip6r AS 'MODULE_PATHNAME','ip6r_cast_from_ip6' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6r(text) RETURNS ip6r AS 'MODULE_PATHNAME','ip6r_cast_from_text' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6r(iprange) RETURNS ip6r AS 'MODULE_PATHNAME','iprange_cast_to_ip6r' LANGUAGE C IMMUTABLE STRICT; - -CREATE FUNCTION iprange(cidr) RETURNS iprange AS 'MODULE_PATHNAME','iprange_cast_from_cidr' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange(ip4) RETURNS iprange AS 'MODULE_PATHNAME','iprange_cast_from_ip4' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange(ip6) RETURNS iprange AS 'MODULE_PATHNAME','iprange_cast_from_ip6' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange(ip4r) RETURNS iprange AS 'MODULE_PATHNAME','iprange_cast_from_ip4r' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange(ip6r) RETURNS iprange AS 'MODULE_PATHNAME','iprange_cast_from_ip6r' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange(ipaddress) RETURNS iprange AS 'MODULE_PATHNAME','iprange_cast_from_ipaddr' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange(text) RETURNS iprange AS 'MODULE_PATHNAME','iprange_cast_from_text' LANGUAGE C IMMUTABLE STRICT; - --- ---------------------------------------------------------------------- --- Cast functions (outward) - -CREATE FUNCTION cidr(ip4) RETURNS cidr AS 'MODULE_PATHNAME','ip4_cast_to_cidr' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION cidr(ip4r) RETURNS cidr AS 'MODULE_PATHNAME','ip4r_cast_to_cidr' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION cidr(ip6) RETURNS cidr AS 'MODULE_PATHNAME','ip6_cast_to_cidr' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION cidr(ip6r) RETURNS cidr AS 'MODULE_PATHNAME','ip6r_cast_to_cidr' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION cidr(ipaddress) RETURNS cidr AS 'MODULE_PATHNAME','ipaddr_cast_to_cidr' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION cidr(iprange) RETURNS cidr AS 'MODULE_PATHNAME','iprange_cast_to_cidr' LANGUAGE C IMMUTABLE STRICT; - -CREATE FUNCTION text(ip4) RETURNS text AS 'MODULE_PATHNAME','ip4_cast_to_text' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION text(ip4r) RETURNS text AS 'MODULE_PATHNAME','ip4r_cast_to_text' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION text(ip6) RETURNS text AS 'MODULE_PATHNAME','ip6_cast_to_text' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION text(ip6r) RETURNS text AS 'MODULE_PATHNAME','ip6r_cast_to_text' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION text(ipaddress) RETURNS text AS 'MODULE_PATHNAME','ipaddr_cast_to_text' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION text(iprange) RETURNS text AS 'MODULE_PATHNAME','iprange_cast_to_text' LANGUAGE C IMMUTABLE STRICT; - -CREATE FUNCTION to_bigint(ip4) RETURNS bigint AS 'MODULE_PATHNAME','ip4_cast_to_bigint' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION to_double(ip4) RETURNS double precision AS 'MODULE_PATHNAME','ip4_cast_to_double' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION to_numeric(ip4) RETURNS numeric AS 'MODULE_PATHNAME','ip4_cast_to_numeric' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION to_numeric(ip6) RETURNS numeric AS 'MODULE_PATHNAME','ip6_cast_to_numeric' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION to_numeric(ipaddress) RETURNS numeric AS 'MODULE_PATHNAME','ipaddr_cast_to_numeric' LANGUAGE C IMMUTABLE STRICT; - --- ---------------------------------------------------------------------- --- Cast definitions (outward) - --- all these are explicit, with the exception of casts from single-address --- types to "cidr", which we make assignment casts since they are lossless --- and preserve general semantics. - -CREATE CAST (ip4 as bigint) WITH FUNCTION to_bigint(ip4); -CREATE CAST (ip4 as double precision) WITH FUNCTION to_double(ip4); -CREATE CAST (ip4 as numeric) WITH FUNCTION to_numeric(ip4); -CREATE CAST (ip4 as text) WITH FUNCTION text(ip4); - -CREATE CAST (ip4 as cidr) WITH FUNCTION cidr(ip4) AS ASSIGNMENT; - -CREATE CAST (ip4r as cidr) WITH FUNCTION cidr(ip4r); -CREATE CAST (ip4r as text) WITH FUNCTION text(ip4r); - -CREATE CAST (ip6 as numeric) WITH FUNCTION to_numeric(ip6); -CREATE CAST (ip6 as text) WITH FUNCTION text(ip6); - -CREATE CAST (ip6 as cidr) WITH FUNCTION cidr(ip6) AS ASSIGNMENT; - -CREATE CAST (ip6r as cidr) WITH FUNCTION cidr(ip6r); -CREATE CAST (ip6r as text) WITH FUNCTION text(ip6r); - -CREATE CAST (ipaddress as numeric) WITH FUNCTION to_numeric(ipaddress); -CREATE CAST (ipaddress as text) WITH FUNCTION text(ipaddress); - -CREATE CAST (ipaddress as cidr) WITH FUNCTION cidr(ipaddress) AS ASSIGNMENT; - -CREATE CAST (iprange as cidr) WITH FUNCTION cidr(iprange); -CREATE CAST (iprange as text) WITH FUNCTION text(iprange); - --- ---------------------------------------------------------------------- --- Cast definitions (inward) - --- these are explicit except for casts from inet/cidr types. Even though --- such casts are lossy for inet, since the masklen isn't preserved, the --- semantics and common usage are enough to justify an assignment cast. - -CREATE CAST (text as ip4) WITH FUNCTION ip4(text); -CREATE CAST (text as ip4r) WITH FUNCTION ip4r(text); -CREATE CAST (text as ip6) WITH FUNCTION ip6(text); -CREATE CAST (text as ip6r) WITH FUNCTION ip6r(text); -CREATE CAST (text as ipaddress) WITH FUNCTION ipaddress(text); -CREATE CAST (text as iprange) WITH FUNCTION iprange(text); - -CREATE CAST (bigint as ip4) WITH FUNCTION ip4(bigint); -CREATE CAST (double precision as ip4) WITH FUNCTION ip4(double precision); - -CREATE CAST (numeric as ip4) WITH FUNCTION ip4(numeric); -CREATE CAST (numeric as ip6) WITH FUNCTION ip6(numeric); - -CREATE CAST (cidr as ip4r) WITH FUNCTION ip4r(cidr) AS ASSIGNMENT; -CREATE CAST (cidr as ip6r) WITH FUNCTION ip6r(cidr) AS ASSIGNMENT; -CREATE CAST (cidr as iprange) WITH FUNCTION iprange(cidr) AS ASSIGNMENT; - -CREATE CAST (inet as ip4) WITH FUNCTION ip4(inet) AS ASSIGNMENT; -CREATE CAST (inet as ip6) WITH FUNCTION ip6(inet) AS ASSIGNMENT; -CREATE CAST (inet as ipaddress) WITH FUNCTION ipaddress(inet) AS ASSIGNMENT; - --- ---------------------------------------------------------------------- --- Cast definitions (cross-type) - --- the lossless "upward" casts are made implict. Downward casts are now --- assignment casts. - -CREATE CAST (ip4 as ip4r) WITH FUNCTION ip4r(ip4) AS IMPLICIT; -CREATE CAST (ip4 as ipaddress) WITH FUNCTION ipaddress(ip4) AS IMPLICIT; -CREATE CAST (ip4 as iprange) WITH FUNCTION iprange(ip4) AS IMPLICIT; -CREATE CAST (ip4r as iprange) WITH FUNCTION iprange(ip4r) AS IMPLICIT; - -CREATE CAST (ip6 as ip6r) WITH FUNCTION ip6r(ip6) AS IMPLICIT; -CREATE CAST (ip6 as ipaddress) WITH FUNCTION ipaddress(ip6) AS IMPLICIT; -CREATE CAST (ip6 as iprange) WITH FUNCTION iprange(ip6) AS IMPLICIT; -CREATE CAST (ip6r as iprange) WITH FUNCTION iprange(ip6r) AS IMPLICIT; - -CREATE CAST (ipaddress as iprange) WITH FUNCTION iprange(ipaddress) AS IMPLICIT; - -CREATE CAST (ipaddress as ip4) WITH FUNCTION ip4(ipaddress) AS ASSIGNMENT; -CREATE CAST (ipaddress as ip6) WITH FUNCTION ip6(ipaddress) AS ASSIGNMENT; - -CREATE CAST (iprange as ip4r) WITH FUNCTION ip4r(iprange) AS ASSIGNMENT; -CREATE CAST (iprange as ip6r) WITH FUNCTION ip6r(iprange) AS ASSIGNMENT; - --- ---------------------------------------------------------------------- --- Constructor functions - -CREATE FUNCTION ip4r(ip4,ip4) RETURNS ip4r AS 'MODULE_PATHNAME', 'ip4r_from_ip4s' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6r(ip6,ip6) RETURNS ip6r AS 'MODULE_PATHNAME', 'ip6r_from_ip6s' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange(ip4,ip4) RETURNS iprange AS 'MODULE_PATHNAME', 'iprange_from_ip4s' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange(ip6,ip6) RETURNS iprange AS 'MODULE_PATHNAME', 'iprange_from_ip6s' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange(ipaddress,ipaddress) RETURNS iprange AS 'MODULE_PATHNAME', 'iprange_from_ipaddrs' LANGUAGE C IMMUTABLE STRICT; - --- ---------------------------------------------------------------------- --- Utility functions (no operator equivalent) - -CREATE FUNCTION family(ip4) RETURNS integer AS $f$ select 4; $f$ LANGUAGE SQL IMMUTABLE; -CREATE FUNCTION family(ip4r) RETURNS integer AS $f$ select 4; $f$ LANGUAGE SQL IMMUTABLE; -CREATE FUNCTION family(ip6) RETURNS integer AS $f$ select 6; $f$ LANGUAGE SQL IMMUTABLE; -CREATE FUNCTION family(ip6r) RETURNS integer AS $f$ select 6; $f$ LANGUAGE SQL IMMUTABLE; -CREATE FUNCTION family(ipaddress) RETURNS integer AS 'MODULE_PATHNAME', 'ipaddr_family' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION family(iprange) RETURNS integer AS 'MODULE_PATHNAME', 'iprange_family' LANGUAGE C IMMUTABLE STRICT; - -CREATE FUNCTION ip4_netmask(integer) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_netmask' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6_netmask(integer) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_netmask' LANGUAGE C IMMUTABLE STRICT; - -CREATE FUNCTION is_cidr(ip4r) RETURNS boolean AS 'MODULE_PATHNAME', 'ip4r_is_cidr' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION is_cidr(ip6r) RETURNS boolean AS 'MODULE_PATHNAME', 'ip6r_is_cidr' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION is_cidr(iprange) RETURNS boolean AS 'MODULE_PATHNAME', 'iprange_is_cidr' LANGUAGE C IMMUTABLE STRICT; - -CREATE FUNCTION masklen(ip4r) RETURNS integer AS 'MODULE_PATHNAME','ip4r_prefixlen' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION masklen(ip6r) RETURNS integer AS 'MODULE_PATHNAME','ip6r_prefixlen' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION masklen(iprange) RETURNS integer AS 'MODULE_PATHNAME','iprange_prefixlen' LANGUAGE C IMMUTABLE STRICT; - -CREATE FUNCTION lower(ip4r) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4r_lower' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION lower(ip6r) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6r_lower' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION lower(iprange) RETURNS ipaddress AS 'MODULE_PATHNAME', 'iprange_lower' LANGUAGE C IMMUTABLE STRICT; - -CREATE FUNCTION upper(ip4r) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4r_upper' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION upper(ip6r) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6r_upper' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION upper(iprange) RETURNS ipaddress AS 'MODULE_PATHNAME', 'iprange_upper' LANGUAGE C IMMUTABLE STRICT; - -CREATE FUNCTION ip4_net_lower(ip4,integer) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_net_lower' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6_net_lower(ip6,integer) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_net_lower' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ipaddress_net_lower(ipaddress,integer) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_net_lower' LANGUAGE C IMMUTABLE STRICT; - -CREATE FUNCTION ip4_net_upper(ip4,integer) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_net_upper' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6_net_upper(ip6,integer) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_net_upper' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ipaddress_net_upper(ipaddress,integer) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_net_upper' LANGUAGE C IMMUTABLE STRICT; - -CREATE FUNCTION ip4r_union(ip4r, ip4r) RETURNS ip4r AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6r_union(ip6r, ip6r) RETURNS ip6r AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange_union(iprange, iprange) RETURNS iprange AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -CREATE FUNCTION ip4r_inter(ip4r,ip4r) RETURNS ip4r AS 'MODULE_PATHNAME','ip4r_inter' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6r_inter(ip6r,ip6r) RETURNS ip6r AS 'MODULE_PATHNAME','ip6r_inter' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange_inter(iprange,iprange) RETURNS iprange AS 'MODULE_PATHNAME','iprange_inter' LANGUAGE C IMMUTABLE STRICT; - --- ---------------------------------------------------------------------- --- Functions with operator equivalents - --- it's intended that either the function form or the operator form be used, --- as desired. - --- (ip / len) or (ip / mask) - -CREATE FUNCTION ip4r_net_mask(ip4,ip4) RETURNS ip4r AS 'MODULE_PATHNAME','ip4r_net_mask' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6r_net_mask(ip6,ip6) RETURNS ip6r AS 'MODULE_PATHNAME','ip6r_net_mask' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange_net_mask(ip4,ip4) RETURNS iprange AS 'MODULE_PATHNAME','iprange_net_mask_ip4' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange_net_mask(ip6,ip6) RETURNS iprange AS 'MODULE_PATHNAME','iprange_net_mask_ip6' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange_net_mask(ipaddress,ipaddress) RETURNS iprange AS 'MODULE_PATHNAME','iprange_net_mask' LANGUAGE C IMMUTABLE STRICT; - -CREATE FUNCTION ip4r_net_prefix(ip4,integer) RETURNS ip4r AS 'MODULE_PATHNAME','ip4r_net_prefix' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6r_net_prefix(ip6,integer) RETURNS ip6r AS 'MODULE_PATHNAME','ip6r_net_prefix' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange_net_prefix(ip4,integer) RETURNS iprange AS 'MODULE_PATHNAME','iprange_net_prefix_ip4' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange_net_prefix(ip6,integer) RETURNS iprange AS 'MODULE_PATHNAME','iprange_net_prefix_ip6' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange_net_prefix(ipaddress,integer) RETURNS iprange AS 'MODULE_PATHNAME','iprange_net_prefix' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR / ( LEFTARG = ip4, RIGHTARG = ip4, PROCEDURE = ip4r_net_mask ); -CREATE OPERATOR / ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6r_net_mask ); -CREATE OPERATOR / ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = iprange_net_mask ); -CREATE OPERATOR / ( LEFTARG = ip4, RIGHTARG = integer, PROCEDURE = ip4r_net_prefix ); -CREATE OPERATOR / ( LEFTARG = ip6, RIGHTARG = integer, PROCEDURE = ip6r_net_prefix ); -CREATE OPERATOR / ( LEFTARG = ipaddress, RIGHTARG = integer, PROCEDURE = iprange_net_prefix ); - --- @ ipr (approximate size) or @@ ipr (exact size) - -CREATE FUNCTION ip4r_size(ip4r) RETURNS double precision AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6r_size(ip6r) RETURNS double precision AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange_size(iprange) RETURNS double precision AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -CREATE FUNCTION ip4r_size_exact(ip4r) RETURNS numeric AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6r_size_exact(ip6r) RETURNS numeric AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange_size_exact(iprange) RETURNS numeric AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR @ ( RIGHTARG = ip4r, PROCEDURE = ip4r_size ); -CREATE OPERATOR @ ( RIGHTARG = ip6r, PROCEDURE = ip6r_size ); -CREATE OPERATOR @ ( RIGHTARG = iprange, PROCEDURE = iprange_size ); - -CREATE OPERATOR @@ ( RIGHTARG = ip4r, PROCEDURE = ip4r_size_exact ); -CREATE OPERATOR @@ ( RIGHTARG = ip6r, PROCEDURE = ip6r_size_exact ); -CREATE OPERATOR @@ ( RIGHTARG = iprange, PROCEDURE = iprange_size_exact ); - --- ---------------------------------------------------------------------- --- Operators - --- the function forms of these aren't intended for general use - --- bitwise ops: and (a & b), or (a | b), xor (a # b), not (~a) - -CREATE FUNCTION ip4_and(ip4,ip4) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_and' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6_and(ip6,ip6) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_and' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ipaddress_and(ipaddress,ipaddress) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_and' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR & ( LEFTARG = ip4, RIGHTARG = ip4, PROCEDURE = ip4_and ); -CREATE OPERATOR & ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_and ); -CREATE OPERATOR & ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_and ); - -CREATE FUNCTION ip4_or(ip4,ip4) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_or' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6_or(ip6,ip6) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_or' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ipaddress_or(ipaddress,ipaddress) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_or' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR | ( LEFTARG = ip4, RIGHTARG = ip4, PROCEDURE = ip4_or ); -CREATE OPERATOR | ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_or ); -CREATE OPERATOR | ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_or ); - -CREATE FUNCTION ip4_not(ip4) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_not' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6_not(ip6) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_not' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ipaddress_not(ipaddress) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_not' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR ~ ( RIGHTARG = ip4, PROCEDURE = ip4_not ); -CREATE OPERATOR ~ ( RIGHTARG = ip6, PROCEDURE = ip6_not ); -CREATE OPERATOR ~ ( RIGHTARG = ipaddress, PROCEDURE = ipaddress_not ); - -CREATE FUNCTION ip4_xor(ip4,ip4) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_xor' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6_xor(ip6,ip6) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_xor' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ipaddress_xor(ipaddress,ipaddress) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_xor' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR # ( LEFTARG = ip4, RIGHTARG = ip4, PROCEDURE = ip4_xor ); -CREATE OPERATOR # ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_xor ); -CREATE OPERATOR # ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_xor ); - --- arithmetic ops: (ip + n), (ip - n), (ip - ip) where n is a numeric or integer type - -CREATE FUNCTION ip4_plus_bigint(ip4,bigint) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_plus_bigint' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip4_plus_int(ip4,integer) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_plus_int' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip4_plus_numeric(ip4,numeric) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_plus_numeric' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR + ( LEFTARG = ip4, RIGHTARG = bigint, PROCEDURE = ip4_plus_bigint ); -CREATE OPERATOR + ( LEFTARG = ip4, RIGHTARG = integer, PROCEDURE = ip4_plus_int ); -CREATE OPERATOR + ( LEFTARG = ip4, RIGHTARG = numeric, PROCEDURE = ip4_plus_numeric ); - -CREATE FUNCTION ip6_plus_bigint(ip6,bigint) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_plus_bigint' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6_plus_int(ip6,integer) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_plus_int' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6_plus_numeric(ip6,numeric) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_plus_numeric' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR + ( LEFTARG = ip6, RIGHTARG = bigint, PROCEDURE = ip6_plus_bigint ); -CREATE OPERATOR + ( LEFTARG = ip6, RIGHTARG = integer, PROCEDURE = ip6_plus_int ); -CREATE OPERATOR + ( LEFTARG = ip6, RIGHTARG = numeric, PROCEDURE = ip6_plus_numeric ); - -CREATE FUNCTION ipaddress_plus_bigint(ipaddress,bigint) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_plus_bigint' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ipaddress_plus_int(ipaddress,integer) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_plus_int' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ipaddress_plus_numeric(ipaddress,numeric) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_plus_numeric' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR + ( LEFTARG = ipaddress, RIGHTARG = bigint, PROCEDURE = ipaddress_plus_bigint ); -CREATE OPERATOR + ( LEFTARG = ipaddress, RIGHTARG = integer, PROCEDURE = ipaddress_plus_int ); -CREATE OPERATOR + ( LEFTARG = ipaddress, RIGHTARG = numeric, PROCEDURE = ipaddress_plus_numeric ); - -CREATE FUNCTION ip4_minus_bigint(ip4,bigint) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_minus_bigint' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip4_minus_int(ip4,integer) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_minus_int' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip4_minus_numeric(ip4,numeric) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_minus_numeric' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR - ( LEFTARG = ip4, RIGHTARG = bigint, PROCEDURE = ip4_minus_bigint ); -CREATE OPERATOR - ( LEFTARG = ip4, RIGHTARG = integer, PROCEDURE = ip4_minus_int ); -CREATE OPERATOR - ( LEFTARG = ip4, RIGHTARG = numeric, PROCEDURE = ip4_minus_numeric ); - -CREATE FUNCTION ip6_minus_bigint(ip6,bigint) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_minus_bigint' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6_minus_int(ip6,integer) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_minus_int' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6_minus_numeric(ip6,numeric) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_minus_numeric' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR - ( LEFTARG = ip6, RIGHTARG = bigint, PROCEDURE = ip6_minus_bigint ); -CREATE OPERATOR - ( LEFTARG = ip6, RIGHTARG = integer, PROCEDURE = ip6_minus_int ); -CREATE OPERATOR - ( LEFTARG = ip6, RIGHTARG = numeric, PROCEDURE = ip6_minus_numeric ); - -CREATE FUNCTION ipaddress_minus_bigint(ipaddress,bigint) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_minus_bigint' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ipaddress_minus_int(ipaddress,integer) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_minus_int' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ipaddress_minus_numeric(ipaddress,numeric) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_minus_numeric' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR - ( LEFTARG = ipaddress, RIGHTARG = bigint, PROCEDURE = ipaddress_minus_bigint ); -CREATE OPERATOR - ( LEFTARG = ipaddress, RIGHTARG = integer, PROCEDURE = ipaddress_minus_int ); -CREATE OPERATOR - ( LEFTARG = ipaddress, RIGHTARG = numeric, PROCEDURE = ipaddress_minus_numeric ); - -CREATE FUNCTION ip4_minus_ip4(ip4,ip4) RETURNS bigint AS 'MODULE_PATHNAME', 'ip4_minus_ip4' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6_minus_ip6(ip6,ip6) RETURNS numeric AS 'MODULE_PATHNAME', 'ip6_minus_ip6' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ipaddress_minus_ipaddress(ipaddress,ipaddress) RETURNS numeric AS 'MODULE_PATHNAME', 'ipaddr_minus_ipaddr' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR - ( LEFTARG = ip4, RIGHTARG = ip4, PROCEDURE = ip4_minus_ip4 ); -CREATE OPERATOR - ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_minus_ip6 ); -CREATE OPERATOR - ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_minus_ipaddress ); - --- containment predicates: (a >>= b), (a >> b), (a <<= b), (a << b), (a && b) - -CREATE FUNCTION ip4r_contained_by(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6r_contained_by(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange_contained_by(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR <<= ( LEFTARG = ip4r, RIGHTARG = ip4r, PROCEDURE = ip4r_contained_by, COMMUTATOR = '>>=', RESTRICT = contsel, JOIN = contjoinsel ); -CREATE OPERATOR <<= ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_contained_by, COMMUTATOR = '>>=', RESTRICT = contsel, JOIN = contjoinsel ); -CREATE OPERATOR <<= ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_contained_by, COMMUTATOR = '>>=', RESTRICT = contsel, JOIN = contjoinsel ); - -CREATE FUNCTION ip4r_contained_by_strict(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6r_contained_by_strict(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange_contained_by_strict(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR << ( LEFTARG = ip4r, RIGHTARG = ip4r, PROCEDURE = ip4r_contained_by_strict, COMMUTATOR = '>>', RESTRICT = contsel, JOIN = contjoinsel ); -CREATE OPERATOR << ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_contained_by_strict, COMMUTATOR = '>>', RESTRICT = contsel, JOIN = contjoinsel ); -CREATE OPERATOR << ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_contained_by_strict, COMMUTATOR = '>>', RESTRICT = contsel, JOIN = contjoinsel ); - -CREATE FUNCTION ip4r_contains(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6r_contains(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange_contains(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR >>= ( LEFTARG = ip4r, RIGHTARG = ip4r, PROCEDURE = ip4r_contains, COMMUTATOR = '<<=', RESTRICT = contsel, JOIN = contjoinsel ); -CREATE OPERATOR >>= ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_contains, COMMUTATOR = '<<=', RESTRICT = contsel, JOIN = contjoinsel ); -CREATE OPERATOR >>= ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_contains, COMMUTATOR = '<<=', RESTRICT = contsel, JOIN = contjoinsel ); - -CREATE FUNCTION ip4r_contains_strict(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6r_contains_strict(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange_contains_strict(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR >> ( LEFTARG = ip4r, RIGHTARG = ip4r, PROCEDURE = ip4r_contains_strict, COMMUTATOR = '<<', RESTRICT = contsel, JOIN = contjoinsel ); -CREATE OPERATOR >> ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_contains_strict, COMMUTATOR = '<<', RESTRICT = contsel, JOIN = contjoinsel ); -CREATE OPERATOR >> ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_contains_strict, COMMUTATOR = '<<', RESTRICT = contsel, JOIN = contjoinsel ); - -CREATE FUNCTION ip4r_overlaps(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6r_overlaps(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange_overlaps(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR && ( LEFTARG = ip4r, RIGHTARG = ip4r, PROCEDURE = ip4r_overlaps, COMMUTATOR = '&&', RESTRICT = areasel, JOIN = areajoinsel ); -CREATE OPERATOR && ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_overlaps, COMMUTATOR = '&&', RESTRICT = areasel, JOIN = areajoinsel ); -CREATE OPERATOR && ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_overlaps, COMMUTATOR = '&&', RESTRICT = areasel, JOIN = areajoinsel ); - --- cross-type containment --- no operators for these since they seem to do more harm than good. These cases --- are handled by implicit casts instead. - -CREATE FUNCTION ip4_contained_by(ip4,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip4_contained_by(ip4,iprange) RETURNS bool AS 'MODULE_PATHNAME','iprange_ip4_contained_by' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6_contained_by(ip6,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6_contained_by(ip6,iprange) RETURNS bool AS 'MODULE_PATHNAME','iprange_ip6_contained_by' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ipaddress_contained_by(ipaddress,iprange) RETURNS bool AS 'MODULE_PATHNAME','iprange_ip_contained_by' LANGUAGE C IMMUTABLE STRICT; - -CREATE FUNCTION ip4_contains(ip4r,ip4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6_contains(ip6r,ip6) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip4_contains(iprange,ip4) RETURNS bool AS 'MODULE_PATHNAME','iprange_contains_ip4' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6_contains(iprange,ip6) RETURNS bool AS 'MODULE_PATHNAME','iprange_contains_ip6' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ipaddress_contains(iprange,ipaddress) RETURNS bool AS 'MODULE_PATHNAME','iprange_contains_ip' LANGUAGE C IMMUTABLE STRICT; - --- btree (strict weak) ordering operators --- meaning of < > for ip4 and ip6 is obvious. --- for ipaddress, all ip4 addresses are less than all ip6 addresses --- for ip4r/ip6r, the order is lexicographic on (lower,upper) --- for iprange, the universal range is lowest, then all ip4 ranges, then ip6 - -CREATE FUNCTION ip4_eq(ip4,ip4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip4r_eq(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6_eq(ip6,ip6) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6r_eq(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ipaddress_eq(ipaddress,ipaddress) RETURNS bool AS 'MODULE_PATHNAME','ipaddr_eq' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange_eq(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR = ( LEFTARG = ip4, RIGHTARG = ip4, PROCEDURE = ip4_eq, COMMUTATOR = '=', NEGATOR = '<>', RESTRICT = eqsel, JOIN = eqjoinsel, SORT1 = '<', SORT2 = '<', HASHES ); -CREATE OPERATOR = ( LEFTARG = ip4r, RIGHTARG = ip4r, PROCEDURE = ip4r_eq, COMMUTATOR = '=', NEGATOR = '<>', RESTRICT = eqsel, JOIN = eqjoinsel, SORT1 = '<', SORT2 = '<', HASHES ); -CREATE OPERATOR = ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_eq, COMMUTATOR = '=', NEGATOR = '<>', RESTRICT = eqsel, JOIN = eqjoinsel, SORT1 = '<', SORT2 = '<', HASHES ); -CREATE OPERATOR = ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_eq, COMMUTATOR = '=', NEGATOR = '<>', RESTRICT = eqsel, JOIN = eqjoinsel, SORT1 = '<', SORT2 = '<', HASHES ); -CREATE OPERATOR = ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_eq, COMMUTATOR = '=', NEGATOR = '<>', RESTRICT = eqsel, JOIN = eqjoinsel, SORT1 = '<', SORT2 = '<', HASHES ); -CREATE OPERATOR = ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_eq, COMMUTATOR = '=', NEGATOR = '<>', RESTRICT = eqsel, JOIN = eqjoinsel, SORT1 = '<', SORT2 = '<', HASHES ); - -CREATE FUNCTION ip4_ge(ip4,ip4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip4r_ge(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6_ge(ip6,ip6) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6r_ge(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ipaddress_ge(ipaddress,ipaddress) RETURNS bool AS 'MODULE_PATHNAME','ipaddr_ge' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange_ge(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR >= ( LEFTARG = ip4, RIGHTARG = ip4, PROCEDURE = ip4_ge, COMMUTATOR = '<=', NEGATOR = '<', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); -CREATE OPERATOR >= ( LEFTARG = ip4r, RIGHTARG = ip4r, PROCEDURE = ip4r_ge, COMMUTATOR = '<=', NEGATOR = '<', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); -CREATE OPERATOR >= ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_ge, COMMUTATOR = '<=', NEGATOR = '<', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); -CREATE OPERATOR >= ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_ge, COMMUTATOR = '<=', NEGATOR = '<', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); -CREATE OPERATOR >= ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_ge, COMMUTATOR = '<=', NEGATOR = '<', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); -CREATE OPERATOR >= ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_ge, COMMUTATOR = '<=', NEGATOR = '<', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); - -CREATE FUNCTION ip4_gt(ip4,ip4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip4r_gt(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6_gt(ip6,ip6) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6r_gt(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ipaddress_gt(ipaddress,ipaddress) RETURNS bool AS 'MODULE_PATHNAME','ipaddr_gt' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange_gt(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR > ( LEFTARG = ip4, RIGHTARG = ip4, PROCEDURE = ip4_gt, COMMUTATOR = '<', NEGATOR = '<=', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); -CREATE OPERATOR > ( LEFTARG = ip4r, RIGHTARG = ip4r, PROCEDURE = ip4r_gt, COMMUTATOR = '<', NEGATOR = '<=', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); -CREATE OPERATOR > ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_gt, COMMUTATOR = '<', NEGATOR = '<=', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); -CREATE OPERATOR > ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_gt, COMMUTATOR = '<', NEGATOR = '<=', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); -CREATE OPERATOR > ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_gt, COMMUTATOR = '<', NEGATOR = '<=', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); -CREATE OPERATOR > ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_gt, COMMUTATOR = '<', NEGATOR = '<=', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); - -CREATE FUNCTION ip4_le(ip4,ip4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip4r_le(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6_le(ip6,ip6) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6r_le(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ipaddress_le(ipaddress,ipaddress) RETURNS bool AS 'MODULE_PATHNAME','ipaddr_le' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange_le(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR <= ( LEFTARG = ip4, RIGHTARG = ip4, PROCEDURE = ip4_le, COMMUTATOR = '>=', NEGATOR = '>', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); -CREATE OPERATOR <= ( LEFTARG = ip4r, RIGHTARG = ip4r, PROCEDURE = ip4r_le, COMMUTATOR = '>=', NEGATOR = '>', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); -CREATE OPERATOR <= ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_le, COMMUTATOR = '>=', NEGATOR = '>', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); -CREATE OPERATOR <= ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_le, COMMUTATOR = '>=', NEGATOR = '>', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); -CREATE OPERATOR <= ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_le, COMMUTATOR = '>=', NEGATOR = '>', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); -CREATE OPERATOR <= ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_le, COMMUTATOR = '>=', NEGATOR = '>', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); - -CREATE FUNCTION ip4_lt(ip4,ip4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip4r_lt(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6_lt(ip6,ip6) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6r_lt(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ipaddress_lt(ipaddress,ipaddress) RETURNS bool AS 'MODULE_PATHNAME','ipaddr_lt' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange_lt(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR < ( LEFTARG = ip4, RIGHTARG = ip4, PROCEDURE = ip4_lt, COMMUTATOR = '>', NEGATOR = '>=', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); -CREATE OPERATOR < ( LEFTARG = ip4r, RIGHTARG = ip4r, PROCEDURE = ip4r_lt, COMMUTATOR = '>', NEGATOR = '>=', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); -CREATE OPERATOR < ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_lt, COMMUTATOR = '>', NEGATOR = '>=', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); -CREATE OPERATOR < ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_lt, COMMUTATOR = '>', NEGATOR = '>=', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); -CREATE OPERATOR < ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_lt, COMMUTATOR = '>', NEGATOR = '>=', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); -CREATE OPERATOR < ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_lt, COMMUTATOR = '>', NEGATOR = '>=', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); - -CREATE FUNCTION ip4_neq(ip4,ip4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip4r_neq(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6_neq(ip6,ip6) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6r_neq(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ipaddress_neq(ipaddress,ipaddress) RETURNS bool AS 'MODULE_PATHNAME','ipaddr_neq' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange_neq(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR <> ( LEFTARG = ip4, RIGHTARG = ip4, PROCEDURE = ip4_neq, COMMUTATOR = '<>', NEGATOR = '=', RESTRICT = neqsel, JOIN = neqjoinsel ); -CREATE OPERATOR <> ( LEFTARG = ip4r, RIGHTARG = ip4r, PROCEDURE = ip4r_neq, COMMUTATOR = '<>', NEGATOR = '=', RESTRICT = neqsel, JOIN = neqjoinsel ); -CREATE OPERATOR <> ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_neq, COMMUTATOR = '<>', NEGATOR = '=', RESTRICT = neqsel, JOIN = neqjoinsel ); -CREATE OPERATOR <> ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_neq, COMMUTATOR = '<>', NEGATOR = '=', RESTRICT = neqsel, JOIN = neqjoinsel ); -CREATE OPERATOR <> ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_neq, COMMUTATOR = '<>', NEGATOR = '=', RESTRICT = neqsel, JOIN = neqjoinsel ); -CREATE OPERATOR <> ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_neq, COMMUTATOR = '<>', NEGATOR = '=', RESTRICT = neqsel, JOIN = neqjoinsel ); - --- ---------------------------------------------------------------------- --- Btree index - -CREATE FUNCTION ip4_cmp(ip4,ip4) RETURNS integer AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip4r_cmp(ip4r,ip4r) RETURNS integer AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6_cmp(ip6,ip6) RETURNS integer AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6r_cmp(ip6r,ip6r) RETURNS integer AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ipaddress_cmp(ipaddress,ipaddress) RETURNS integer AS 'MODULE_PATHNAME','ipaddr_cmp' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprange_cmp(iprange,iprange) RETURNS integer AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR CLASS btree_ip4_ops DEFAULT FOR TYPE ip4 USING btree AS - OPERATOR 1 < , - OPERATOR 2 <= , - OPERATOR 3 = , - OPERATOR 4 >= , - OPERATOR 5 > , - FUNCTION 1 ip4_cmp(ip4, ip4); - -CREATE OPERATOR CLASS btree_ip4r_ops DEFAULT FOR TYPE ip4r USING btree AS - OPERATOR 1 < , - OPERATOR 2 <= , - OPERATOR 3 = , - OPERATOR 4 >= , - OPERATOR 5 > , - FUNCTION 1 ip4r_cmp(ip4r, ip4r); - -CREATE OPERATOR CLASS btree_ip6_ops DEFAULT FOR TYPE ip6 USING btree AS - OPERATOR 1 < , - OPERATOR 2 <= , - OPERATOR 3 = , - OPERATOR 4 >= , - OPERATOR 5 > , - FUNCTION 1 ip6_cmp(ip6, ip6); - -CREATE OPERATOR CLASS btree_ip6r_ops DEFAULT FOR TYPE ip6r USING btree AS - OPERATOR 1 < , - OPERATOR 2 <= , - OPERATOR 3 = , - OPERATOR 4 >= , - OPERATOR 5 > , - FUNCTION 1 ip6r_cmp(ip6r, ip6r); - -CREATE OPERATOR CLASS btree_ipaddress_ops DEFAULT FOR TYPE ipaddress USING btree AS - OPERATOR 1 < , - OPERATOR 2 <= , - OPERATOR 3 = , - OPERATOR 4 >= , - OPERATOR 5 > , - FUNCTION 1 ipaddress_cmp(ipaddress, ipaddress); - -CREATE OPERATOR CLASS btree_iprange_ops DEFAULT FOR TYPE iprange USING btree AS - OPERATOR 1 < , - OPERATOR 2 <= , - OPERATOR 3 = , - OPERATOR 4 >= , - OPERATOR 5 > , - FUNCTION 1 iprange_cmp(iprange, iprange); - --- ---------------------------------------------------------------------- --- Hash index - --- the hash index definitions are needed for hashagg, hashjoin, hash-distinct, hashsetop --- etc. even if no actual hash indexes are used. - -CREATE FUNCTION ip4hash(ip4) RETURNS integer AS 'MODULE_PATHNAME', 'ip4hash' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6hash(ip6) RETURNS integer AS 'MODULE_PATHNAME', 'ip6hash' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ipaddresshash(ipaddress) RETURNS integer AS 'MODULE_PATHNAME', 'ipaddr_hash' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip4rhash(ip4r) RETURNS integer AS 'MODULE_PATHNAME', 'ip4rhash' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION ip6rhash(ip6r) RETURNS integer AS 'MODULE_PATHNAME', 'ip6rhash' LANGUAGE C IMMUTABLE STRICT; -CREATE FUNCTION iprangehash(iprange) RETURNS integer AS 'MODULE_PATHNAME', 'iprange_hash' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR CLASS hash_ip4_ops DEFAULT FOR TYPE ip4 USING hash AS - OPERATOR 1 = , - FUNCTION 1 ip4hash(ip4); - -CREATE OPERATOR CLASS hash_ip4r_ops DEFAULT FOR TYPE ip4r USING hash AS - OPERATOR 1 = , - FUNCTION 1 ip4rhash(ip4r); - -CREATE OPERATOR CLASS hash_ip6_ops DEFAULT FOR TYPE ip6 USING hash AS - OPERATOR 1 = , - FUNCTION 1 ip6hash(ip6); - -CREATE OPERATOR CLASS hash_ip6r_ops DEFAULT FOR TYPE ip6r USING hash AS - OPERATOR 1 = , - FUNCTION 1 ip6rhash(ip6r); - -CREATE OPERATOR CLASS hash_ipaddress_ops DEFAULT FOR TYPE ipaddress USING hash AS - OPERATOR 1 = , - FUNCTION 1 ipaddresshash(ipaddress); - -CREATE OPERATOR CLASS hash_iprange_ops DEFAULT FOR TYPE iprange USING hash AS - OPERATOR 1 = , - FUNCTION 1 iprangehash(iprange); - --- ---------------------------------------------------------------------- --- GiST - -CREATE FUNCTION gip4r_consistent(internal,ip4r,int2,oid,internal) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE FUNCTION gip4r_compress(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE FUNCTION gip4r_decompress(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE FUNCTION gip4r_penalty(internal,internal,internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C STRICT; -CREATE FUNCTION gip4r_picksplit(internal, internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE FUNCTION gip4r_union(internal, internal) RETURNS ip4r AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE FUNCTION gip4r_same(ip4r, ip4r, internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE FUNCTION gip4r_fetch(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; - -CREATE FUNCTION gip6r_consistent(internal,ip6r,int2,oid,internal) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE FUNCTION gip6r_compress(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE FUNCTION gip6r_decompress(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE FUNCTION gip6r_penalty(internal,internal,internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C STRICT; -CREATE FUNCTION gip6r_picksplit(internal, internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE FUNCTION gip6r_union(internal, internal) RETURNS ip6r AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE FUNCTION gip6r_same(ip6r, ip6r, internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE FUNCTION gip6r_fetch(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; - -CREATE FUNCTION gipr_consistent(internal,iprange,int2,oid,internal) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE FUNCTION gipr_compress(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE FUNCTION gipr_decompress(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE FUNCTION gipr_penalty(internal,internal,internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C STRICT; -CREATE FUNCTION gipr_picksplit(internal, internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE FUNCTION gipr_union(internal, internal) RETURNS iprange AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE FUNCTION gipr_same(iprange, iprange, internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE FUNCTION gipr_fetch(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; - -CREATE OPERATOR CLASS gist_ip4r_ops DEFAULT FOR TYPE ip4r USING gist AS - OPERATOR 1 >>= , - OPERATOR 2 <<= , - OPERATOR 3 >> , - OPERATOR 4 << , - OPERATOR 5 && , - OPERATOR 6 = , - FUNCTION 1 gip4r_consistent (internal, ip4r, int2, oid, internal), - FUNCTION 2 gip4r_union (internal, internal), - FUNCTION 3 gip4r_compress (internal), - FUNCTION 4 gip4r_decompress (internal), - FUNCTION 5 gip4r_penalty (internal, internal, internal), - FUNCTION 6 gip4r_picksplit (internal, internal), - FUNCTION 7 gip4r_same (ip4r, ip4r, internal); - -CREATE OPERATOR CLASS gist_ip6r_ops DEFAULT FOR TYPE ip6r USING gist AS - OPERATOR 1 >>= , - OPERATOR 2 <<= , - OPERATOR 3 >> , - OPERATOR 4 << , - OPERATOR 5 && , - OPERATOR 6 = , - FUNCTION 1 gip6r_consistent (internal, ip6r, int2, oid, internal), - FUNCTION 2 gip6r_union (internal, internal), - FUNCTION 3 gip6r_compress (internal), - FUNCTION 4 gip6r_decompress (internal), - FUNCTION 5 gip6r_penalty (internal, internal, internal), - FUNCTION 6 gip6r_picksplit (internal, internal), - FUNCTION 7 gip6r_same (ip6r, ip6r, internal); - -CREATE OPERATOR CLASS gist_iprange_ops DEFAULT FOR TYPE iprange USING gist AS - OPERATOR 1 >>= , - OPERATOR 2 <<= , - OPERATOR 3 >> , - OPERATOR 4 << , - OPERATOR 5 && , - OPERATOR 6 = , - FUNCTION 1 gipr_consistent (internal, iprange, int2, oid, internal), - FUNCTION 2 gipr_union (internal, internal), - FUNCTION 3 gipr_compress (internal), - FUNCTION 4 gipr_decompress (internal), - FUNCTION 5 gipr_penalty (internal, internal, internal), - FUNCTION 6 gipr_picksplit (internal, internal), - FUNCTION 7 gipr_same (iprange, iprange, internal); - -DO $s$ - BEGIN - IF current_setting('server_version_num')::integer >= 90500 THEN - ALTER OPERATOR FAMILY gist_ip4r_ops USING gist ADD - FUNCTION 9 (ip4r,ip4r) gip4r_fetch (internal); - ALTER OPERATOR FAMILY gist_ip6r_ops USING gist ADD - FUNCTION 9 (ip6r,ip6r) gip6r_fetch (internal); - ALTER OPERATOR FAMILY gist_iprange_ops USING gist ADD - FUNCTION 9 (iprange,iprange) gipr_fetch (internal); - END IF; - IF current_setting('server_version_num')::integer >= 90600 THEN - DECLARE - r record; - BEGIN - FOR r IN SELECT oid::regprocedure as fsig - FROM pg_catalog.pg_proc - WHERE (probin = 'MODULE_PATHNAME' - AND prolang = (SELECT oid FROM pg_catalog.pg_language l WHERE l.lanname='c')) - OR (oid in ('family(ip4)'::regprocedure, - 'family(ip6)'::regprocedure, - 'family(ip4r)'::regprocedure, - 'family(ip6r)'::regprocedure)) - LOOP - EXECUTE format('ALTER FUNCTION %s PARALLEL SAFE', r.fsig); - END LOOP; - END; - END IF; - END; -$s$; - --- end diff -Nru ip4r-2.3/ip4r.c ip4r-2.4/ip4r.c --- ip4r-2.3/ip4r.c 2018-05-24 21:30:28.000000000 +0000 +++ ip4r-2.4/ip4r.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,1471 +0,0 @@ -/* $Id: ip4r.c,v 1.12 2011/08/22 14:05:19 andrewsn Exp $ */ - -#include "ipr.h" - -#include "ip4r_funcs.h" - - -/* extract an IP range from text. - */ -static -bool ip4r_from_str(char *str, IP4R *ipr) -{ - char buf[IP4_STRING_MAX]; - int pos = strcspn(str, "-/"); - IP4 ip; - - switch (str[pos]) - { - case 0: /* no separator, must be single ip4 addr */ - { - if (!ip4_raw_input(str, &ip)) - return FALSE; - ipr->lower = ip; - ipr->upper = ip; - return TRUE; - } - - case '-': /* lower-upper */ - { - char *rest = str + pos + 1; - - if (pos >= sizeof(buf)) - return FALSE; - memcpy(buf, str, pos); - buf[pos] = 0; - if (!ip4_raw_input(buf, &ip)) - return FALSE; - ipr->lower = ip; - if (!ip4_raw_input(rest, &ip)) - return FALSE; - if (!ip4_lessthan(ip, ipr->lower)) - ipr->upper = ip; - else - { - ipr->upper = ipr->lower; - ipr->lower = ip; - } - return TRUE; - } - - case '/': /* prefix/len */ - { - char *rest = str + pos + 1; - unsigned pfxlen; - char dummy; - - if (pos >= sizeof(buf)) - return FALSE; - memcpy(buf, str, pos); - buf[pos] = 0; - if (!ip4_raw_input(buf, &ip)) - return FALSE; - if (rest[strspn(rest,"0123456789")]) - return FALSE; - if (sscanf(rest, "%u%c", &pfxlen, &dummy) != 1) - return FALSE; - return ip4r_from_cidr(ip, pfxlen, ipr); - } - - default: - return FALSE; /* can't happen */ - } -} - - -/* Output an ip range in text form - */ -static inline -int ip4r_to_str(IP4R *ipr, char *str, int slen) -{ - char buf1[IP4_STRING_MAX]; - char buf2[IP4_STRING_MAX]; - unsigned msk; - - if (ip4_equal(ipr->lower, ipr->upper)) - return ip4_raw_output(ipr->lower, str, slen); - - if ((msk = masklen(ipr->lower,ipr->upper)) <= 32) - { - ip4_raw_output(ipr->lower, buf1, sizeof(buf1)); - return snprintf(str, slen, "%s/%u", buf1, msk); - } - - ip4_raw_output(ipr->lower, buf1, sizeof(buf1)); - ip4_raw_output(ipr->upper, buf2, sizeof(buf2)); - - return snprintf(str, slen, "%s-%s", buf1, buf2); -} - - -/**************************************************************************/ -/* This part handles all aspects of postgres interfacing. - */ - -static -text * -make_text(int len) -{ - text *ret = (text *) palloc0(len + VARHDRSZ); - SET_VARSIZE(ret, len + VARHDRSZ); - return ret; -} - -static inline -void -set_text_len(text *txt, int len) -{ - Assert(len + VARHDRSZ <= VARSIZE(txt)); - if (len + VARHDRSZ <= VARSIZE(txt)) - SET_VARSIZE(txt, len + VARHDRSZ); -} - -/* -** Input/Output routines -*/ - -PG_FUNCTION_INFO_V1(ip4_in); -Datum -ip4_in(PG_FUNCTION_ARGS) -{ - char *str = PG_GETARG_CSTRING(0); - IP4 ip; - if (ip4_raw_input(str, &ip)) - PG_RETURN_IP4(ip); - - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid IP4 value: '%s'", str))); - PG_RETURN_NULL(); -} - -PG_FUNCTION_INFO_V1(ip4_out); -Datum -ip4_out(PG_FUNCTION_ARGS) -{ - IP4 ip = PG_GETARG_IP4(0); - char *out = palloc(IP4_STRING_MAX); - ip4_raw_output(ip, out, IP4_STRING_MAX); - PG_RETURN_CSTRING(out); -} - -PG_FUNCTION_INFO_V1(ip4_recv); -Datum -ip4_recv(PG_FUNCTION_ARGS) -{ - StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); - PG_RETURN_IP4((IP4) pq_getmsgint(buf, sizeof(IP4))); -} - -PG_FUNCTION_INFO_V1(ip4_send); -Datum -ip4_send(PG_FUNCTION_ARGS) -{ - IP4 arg1 = PG_GETARG_IP4(0); - StringInfoData buf; - - pq_begintypsend(&buf); - pq_sendint(&buf, arg1, sizeof(IP4)); - PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); -} - -PG_FUNCTION_INFO_V1(ip4hash); -Datum -ip4hash(PG_FUNCTION_ARGS) -{ - IP4 arg1 = PG_GETARG_IP4(0); - - return hash_any((unsigned char *)&arg1, sizeof(IP4)); -} - -PG_FUNCTION_INFO_V1(ip4_cast_to_text); -Datum -ip4_cast_to_text(PG_FUNCTION_ARGS) -{ - IP4 ip = PG_GETARG_IP4(0); - text *out = make_text(IP4_STRING_MAX); - set_text_len(out, ip4_raw_output(ip, VARDATA(out), IP4_STRING_MAX)); - PG_RETURN_TEXT_P(out); -} - -PG_FUNCTION_INFO_V1(ip4_cast_from_text); -Datum -ip4_cast_from_text(PG_FUNCTION_ARGS) -{ - text *txt = PG_GETARG_TEXT_PP(0); - int tlen = VARSIZE_ANY_EXHDR(txt); - char buf[IP4_STRING_MAX]; - - if (tlen < sizeof(buf)) - { - IP4 ip; - - memcpy(buf, VARDATA_ANY(txt), tlen); - buf[tlen] = 0; - if (ip4_raw_input(buf, &ip)) - PG_RETURN_IP4(ip); - } - - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid IP4 value in text"))); - PG_RETURN_NULL(); -} - -PG_FUNCTION_INFO_V1(ip4_cast_from_inet); -Datum -ip4_cast_from_inet(PG_FUNCTION_ARGS) -{ - inet *inetptr = PG_GETARG_INET_P(0); - inet_struct *in = INET_STRUCT_DATA(inetptr); - - if (in->family == PGSQL_AF_INET) - { - unsigned char *p = in->ipaddr; - IP4 ip = (p[0] << 24)|(p[1] << 16)|(p[2] << 8)|p[3]; - PG_RETURN_IP4(ip); - } - - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid INET value for conversion to IP4"))); - PG_RETURN_NULL(); -} - -PG_FUNCTION_INFO_V1(ip4_cast_to_cidr); -Datum -ip4_cast_to_cidr(PG_FUNCTION_ARGS) -{ - IP4 ip = PG_GETARG_IP4(0); - inet *res = palloc0(VARHDRSZ + sizeof(inet_struct)); - inet_struct *in; - - SET_VARSIZE(res, VARHDRSZ + offsetof(inet_struct, ipaddr) + 4); - - in = ((inet_struct *)VARDATA(res)); - in->bits = 32; - in->family = PGSQL_AF_INET; - { - unsigned char *p = in->ipaddr; - p[0] = (ip >> 24) & 0xff; - p[1] = (ip >> 16) & 0xff; - p[2] = (ip >> 8) & 0xff; - p[3] = (ip ) & 0xff; - } - - PG_RETURN_INET_P(res); -} - -PG_FUNCTION_INFO_V1(ip4_cast_to_bigint); -Datum -ip4_cast_to_bigint(PG_FUNCTION_ARGS) -{ - IP4 ip = PG_GETARG_IP4(0); - PG_RETURN_INT64(ip); -} - -PG_FUNCTION_INFO_V1(ip4_cast_to_numeric); -Datum -ip4_cast_to_numeric(PG_FUNCTION_ARGS) -{ - IP4 ip = PG_GETARG_IP4(0); - int64 v = ip; - PG_RETURN_DATUM(DirectFunctionCall1(int8_numeric, Int64GetDatumFast(v))); -} - -PG_FUNCTION_INFO_V1(ip4_cast_from_bigint); -Datum -ip4_cast_from_bigint(PG_FUNCTION_ARGS) -{ - int64 val = PG_GETARG_INT64(0); - - if (val < -(int64)0x80000000UL || val > (int64)0xFFFFFFFFUL) - ereport(ERROR, - (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), - errmsg("ip address out of range"))); - - PG_RETURN_IP4(val); -} - -PG_FUNCTION_INFO_V1(ip4_cast_to_double); -Datum -ip4_cast_to_double(PG_FUNCTION_ARGS) -{ - IP4 ip = PG_GETARG_IP4(0); - PG_RETURN_FLOAT8(ip); -} - -PG_FUNCTION_INFO_V1(ip4_cast_from_double); -Datum -ip4_cast_from_double(PG_FUNCTION_ARGS) -{ - float8 val = PG_GETARG_FLOAT8(0); - float8 ival = 0; - - if (modf(val,&ival) != 0.0) - { - ereport(WARNING, - (errcode(ERRCODE_WARNING), - errmsg("double converted to IP4 is not integral"))); - } - - if (ival < -(float8)0x80000000UL || ival > (float8)0xFFFFFFFFUL) - ereport(ERROR, - (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), - errmsg("ip address out of range"))); - - /* - * casting directly to ulong evokes the nasal demons for negative values, - * casting to long first evokes them for large positive values if long is - * 32bit. - */ - if (ival < 0) - PG_RETURN_IP4((unsigned long) (long) ival); - else - PG_RETURN_IP4((unsigned long) ival); -} - -PG_FUNCTION_INFO_V1(ip4_cast_from_numeric); -Datum -ip4_cast_from_numeric(PG_FUNCTION_ARGS) -{ - Datum val_num = PG_GETARG_DATUM(0); - int64 val = DatumGetInt64(DirectFunctionCall1(numeric_int8,val_num)); - - if (val < -(int64)0x80000000UL || val > (int64)0xFFFFFFFFUL) - ereport(ERROR, - (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), - errmsg("ip address out of range"))); - - PG_RETURN_IP4((unsigned long) val); -} - -PG_FUNCTION_INFO_V1(ip4_netmask); -Datum -ip4_netmask(PG_FUNCTION_ARGS) -{ - int pfxlen = PG_GETARG_INT32(0); - - if (pfxlen < 0 || pfxlen > 32) - { - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("prefix length out of range"))); - } - - PG_RETURN_IP4( netmask(pfxlen) ); -} - -PG_FUNCTION_INFO_V1(ip4_net_lower); -Datum -ip4_net_lower(PG_FUNCTION_ARGS) -{ - IP4 ip = PG_GETARG_IP4(0); - int pfxlen = PG_GETARG_INT32(1); - - if (pfxlen < 0 || pfxlen > 32) - { - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("prefix length out of range"))); - } - - PG_RETURN_IP4( ip & netmask(pfxlen) ); -} - -PG_FUNCTION_INFO_V1(ip4_net_upper); -Datum -ip4_net_upper(PG_FUNCTION_ARGS) -{ - IP4 ip = PG_GETARG_IP4(0); - int pfxlen = PG_GETARG_INT32(1); - - if (pfxlen < 0 || pfxlen > 32) - { - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("prefix length out of range"))); - } - - PG_RETURN_IP4( ip | hostmask(pfxlen) ); -} - -PG_FUNCTION_INFO_V1(ip4_plus_int); -Datum -ip4_plus_int(PG_FUNCTION_ARGS) -{ - IP4 ip = PG_GETARG_IP4(0); - int addend = PG_GETARG_INT32(1); - IP4 result = ip + (IP4) addend; - - if ((addend < 0) != (result < ip)) - { - ereport(ERROR, - (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), - errmsg("ip address out of range"))); - } - - PG_RETURN_IP4(result); -} - -PG_FUNCTION_INFO_V1(ip4_plus_bigint); -Datum -ip4_plus_bigint(PG_FUNCTION_ARGS) -{ - IP4 ip = PG_GETARG_IP4(0); - int64 addend = PG_GETARG_INT64(1); - int64 result = (int64) ip + addend; - - if (((addend < 0) != (result < ip)) - || result != (int64)(IP4)result) - { - ereport(ERROR, - (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), - errmsg("ip address out of range"))); - } - - PG_RETURN_IP4( (IP4)(result) ); -} - -PG_FUNCTION_INFO_V1(ip4_plus_numeric); -Datum -ip4_plus_numeric(PG_FUNCTION_ARGS) -{ - IP4 ip = PG_GETARG_IP4(0); - Datum addend_num = PG_GETARG_DATUM(1); - int64 addend = DatumGetInt64(DirectFunctionCall1(numeric_int8,addend_num)); - int64 result = (int64) ip + addend; - - if (((addend < 0) != (result < ip)) - || result != (int64)(IP4)result) - { - ereport(ERROR, - (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), - errmsg("ip address out of range"))); - } - - PG_RETURN_IP4( (IP4)(result) ); -} - -PG_FUNCTION_INFO_V1(ip4_minus_int); -Datum -ip4_minus_int(PG_FUNCTION_ARGS) -{ - IP4 ip = PG_GETARG_IP4(0); - int subtrahend = PG_GETARG_INT32(1); - IP4 result = ip - (IP4) subtrahend; - - if ((subtrahend > 0) != (result < ip)) - { - ereport(ERROR, - (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), - errmsg("ip address out of range"))); - } - - PG_RETURN_IP4(result); -} - -PG_FUNCTION_INFO_V1(ip4_minus_bigint); -Datum -ip4_minus_bigint(PG_FUNCTION_ARGS) -{ - IP4 ip = PG_GETARG_IP4(0); - int64 subtrahend = PG_GETARG_INT64(1); - int64 result = (int64) ip - subtrahend; - - if (((subtrahend > 0) != (result < ip)) - || result != (int64)(IP4)result) - { - ereport(ERROR, - (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), - errmsg("ip address out of range"))); - } - - PG_RETURN_IP4( (IP4)(result) ); -} - -PG_FUNCTION_INFO_V1(ip4_minus_numeric); -Datum -ip4_minus_numeric(PG_FUNCTION_ARGS) -{ - IP4 ip = PG_GETARG_IP4(0); - Datum subtrahend_num = PG_GETARG_DATUM(1); - int64 subtrahend = DatumGetInt64(DirectFunctionCall1(numeric_int8,subtrahend_num)); - int64 result = (int64) ip - subtrahend; - - if (((subtrahend > 0) != (result < ip)) - || result != (int64)(IP4)result) - { - ereport(ERROR, - (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), - errmsg("ip address out of range"))); - } - - PG_RETURN_IP4( (IP4)(result) ); -} - -PG_FUNCTION_INFO_V1(ip4_minus_ip4); -Datum -ip4_minus_ip4(PG_FUNCTION_ARGS) -{ - IP4 minuend = PG_GETARG_IP4(0); - IP4 subtrahend = PG_GETARG_IP4(1); - int64 result = (int64) minuend - (int64) subtrahend; - - PG_RETURN_INT64(result); -} - -PG_FUNCTION_INFO_V1(ip4_and); -Datum -ip4_and(PG_FUNCTION_ARGS) -{ - IP4 a = PG_GETARG_IP4(0); - IP4 b = PG_GETARG_IP4(1); - - PG_RETURN_IP4(a & b); -} - -PG_FUNCTION_INFO_V1(ip4_or); -Datum -ip4_or(PG_FUNCTION_ARGS) -{ - IP4 a = PG_GETARG_IP4(0); - IP4 b = PG_GETARG_IP4(1); - - PG_RETURN_IP4(a | b); -} - -PG_FUNCTION_INFO_V1(ip4_xor); -Datum -ip4_xor(PG_FUNCTION_ARGS) -{ - IP4 a = PG_GETARG_IP4(0); - IP4 b = PG_GETARG_IP4(1); - - PG_RETURN_IP4(a ^ b); -} - -PG_FUNCTION_INFO_V1(ip4_not); -Datum -ip4_not(PG_FUNCTION_ARGS) -{ - IP4 a = PG_GETARG_IP4(0); - - PG_RETURN_IP4(~a); -} - - -/*---- ip4r ----*/ - -PG_FUNCTION_INFO_V1(ip4r_in); -Datum -ip4r_in(PG_FUNCTION_ARGS) -{ - char *str = PG_GETARG_CSTRING(0); - IP4R ipr; - if (ip4r_from_str(str, &ipr)) - { - IP4R *res = palloc(sizeof(IP4R)); - *res = ipr; - PG_RETURN_IP4R_P(res); - } - - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid IP4R value: \"%s\"", str))); - PG_RETURN_NULL(); -} - -PG_FUNCTION_INFO_V1(ip4r_out); -Datum -ip4r_out(PG_FUNCTION_ARGS) -{ - IP4R *ipr = PG_GETARG_IP4R_P(0); - char *out = palloc(IP4R_STRING_MAX); - ip4r_to_str(ipr, out, IP4R_STRING_MAX); - PG_RETURN_CSTRING(out); -} - -PG_FUNCTION_INFO_V1(ip4r_recv); -Datum -ip4r_recv(PG_FUNCTION_ARGS) -{ - StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); - IP4R *ipr = palloc(sizeof(IP4R)); - - ipr->lower = (IP4) pq_getmsgint(buf, sizeof(IP4)); - ipr->upper = (IP4) pq_getmsgint(buf, sizeof(IP4)); - - PG_RETURN_IP4R_P(ipr); -} - -PG_FUNCTION_INFO_V1(ip4r_send); -Datum -ip4r_send(PG_FUNCTION_ARGS) -{ - IP4R *ipr = PG_GETARG_IP4R_P(0); - StringInfoData buf; - - pq_begintypsend(&buf); - pq_sendint(&buf, ipr->lower, sizeof(IP4)); - pq_sendint(&buf, ipr->upper, sizeof(IP4)); - PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); -} - -PG_FUNCTION_INFO_V1(ip4rhash); -Datum -ip4rhash(PG_FUNCTION_ARGS) -{ - IP4R *arg1 = PG_GETARG_IP4R_P(0); - - return hash_any((unsigned char *)arg1, sizeof(IP4R)); -} - -PG_FUNCTION_INFO_V1(ip4r_cast_to_text); -Datum -ip4r_cast_to_text(PG_FUNCTION_ARGS) -{ - IP4R *ipr = PG_GETARG_IP4R_P(0); - text *out = make_text(IP4R_STRING_MAX); - set_text_len(out, ip4r_to_str(ipr, VARDATA(out), IP4R_STRING_MAX)); - PG_RETURN_TEXT_P(out); -} - -PG_FUNCTION_INFO_V1(ip4r_cast_from_text); -Datum -ip4r_cast_from_text(PG_FUNCTION_ARGS) -{ - text *txt = PG_GETARG_TEXT_PP(0); - int tlen = VARSIZE_ANY_EXHDR(txt); - char buf[IP4R_STRING_MAX]; - - if (tlen < sizeof(buf)) - { - IP4R ipr; - - memcpy(buf, VARDATA_ANY(txt), tlen); - buf[tlen] = 0; - if (ip4r_from_str(buf, &ipr)) - { - IP4R *res = palloc(sizeof(IP4R)); - *res = ipr; - PG_RETURN_IP4R_P(res); - } - } - - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid IP4R value in text"))); - PG_RETURN_NULL(); -} - -PG_FUNCTION_INFO_V1(ip4r_cast_from_cidr); -Datum -ip4r_cast_from_cidr(PG_FUNCTION_ARGS) -{ - inet *inetptr = PG_GETARG_INET_P(0); - inet_struct *in = INET_STRUCT_DATA(inetptr); - - if (in->family == PGSQL_AF_INET) - { - unsigned char *p = in->ipaddr; - IP4 ip = (p[0] << 24)|(p[1] << 16)|(p[2] << 8)|p[3]; - IP4R ipr; - if (ip4r_from_cidr(ip, in->bits, &ipr)) - { - IP4R *res = palloc(sizeof(IP4R)); - *res = ipr; - PG_RETURN_IP4R_P(res); - } - } - - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid CIDR value for conversion to IP4R"))); - PG_RETURN_NULL(); -} - -PG_FUNCTION_INFO_V1(ip4r_cast_to_cidr); -Datum -ip4r_cast_to_cidr(PG_FUNCTION_ARGS) -{ - IP4R *ipr = PG_GETARG_IP4R_P(0); - IP4 ip = ipr->lower; - inet *res; - inet_struct *in; - unsigned bits = masklen(ip, ipr->upper); - - if (bits > 32) - PG_RETURN_NULL(); - - res = palloc0(VARHDRSZ + sizeof(inet_struct)); - SET_VARSIZE(res, VARHDRSZ + offsetof(inet_struct, ipaddr) + 4); - - in = ((inet_struct *)VARDATA(res)); - in->bits = bits; - in->family = PGSQL_AF_INET; - { - unsigned char *p = in->ipaddr; - p[0] = (ip >> 24) & 0xff; - p[1] = (ip >> 16) & 0xff; - p[2] = (ip >> 8) & 0xff; - p[3] = (ip ) & 0xff; - } - - PG_RETURN_INET_P(res); -} - -PG_FUNCTION_INFO_V1(ip4r_cast_from_ip4); -Datum -ip4r_cast_from_ip4(PG_FUNCTION_ARGS) -{ - IP4 ip = PG_GETARG_IP4(0); - IP4R *res = palloc(sizeof(IP4R)); - if (ip4r_from_inet(ip, 32, res)) - { - PG_RETURN_IP4R_P(res); - } - - pfree(res); - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid IP4 value for conversion to IP4R (shouldn't be possible)"))); - PG_RETURN_NULL(); -} - -PG_FUNCTION_INFO_V1(ip4r_from_ip4s); -Datum -ip4r_from_ip4s(PG_FUNCTION_ARGS) -{ - IP4 a = PG_GETARG_IP4(0); - IP4 b = PG_GETARG_IP4(1); - IP4R *res = palloc(sizeof(IP4R)); - if (a < b) - res->lower = a, res->upper = b; - else - res->lower = b, res->upper = a; - PG_RETURN_IP4R_P( res ); -} - -PG_FUNCTION_INFO_V1(ip4r_net_prefix); -Datum -ip4r_net_prefix(PG_FUNCTION_ARGS) -{ - IP4 ip = PG_GETARG_IP4(0); - int pfxlen = PG_GETARG_INT32(1); - - if (pfxlen < 0 || pfxlen > 32) - { - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("prefix length out of range"))); - } - - { - IP4 mask = netmask(pfxlen); - IP4R *res = palloc(sizeof(IP4R)); - - res->lower = ip & mask; - res->upper = ip | ~mask; - - PG_RETURN_IP4R_P(res); - } -} - -PG_FUNCTION_INFO_V1(ip4r_net_mask); -Datum -ip4r_net_mask(PG_FUNCTION_ARGS) -{ - IP4 ip = PG_GETARG_IP4(0); - IP4 mask = PG_GETARG_IP4(1); - - if (!ip4_valid_netmask(mask)) - { - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid netmask"))); - } - - { - IP4R *res = palloc(sizeof(IP4R)); - - res->lower = ip & mask; - res->upper = ip | ~mask; - - PG_RETURN_IP4R_P(res); - } -} - - -PG_FUNCTION_INFO_V1(ip4r_lower); -Datum -ip4r_lower(PG_FUNCTION_ARGS) -{ - IP4R *ipr = PG_GETARG_IP4R_P(0); - PG_RETURN_IP4( ipr->lower ); -} - -PG_FUNCTION_INFO_V1(ip4r_upper); -Datum -ip4r_upper(PG_FUNCTION_ARGS) -{ - IP4R *ipr = PG_GETARG_IP4R_P(0); - PG_RETURN_IP4( ipr->upper ); -} - -PG_FUNCTION_INFO_V1(ip4r_is_cidr); -Datum -ip4r_is_cidr(PG_FUNCTION_ARGS) -{ - IP4R *ipr = PG_GETARG_IP4R_P(0); - PG_RETURN_BOOL( (masklen(ipr->lower,ipr->upper) <= 32U) ); -} - -PG_FUNCTION_INFO_V1(ip4_lt); -Datum -ip4_lt(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip4_lessthan(PG_GETARG_IP4(0), PG_GETARG_IP4(1)) ); -} - -PG_FUNCTION_INFO_V1(ip4_le); -Datum -ip4_le(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip4_less_eq(PG_GETARG_IP4(0), PG_GETARG_IP4(1)) ); -} - -PG_FUNCTION_INFO_V1(ip4_gt); -Datum -ip4_gt(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip4_lessthan(PG_GETARG_IP4(1), PG_GETARG_IP4(0)) ); -} - -PG_FUNCTION_INFO_V1(ip4_ge); -Datum -ip4_ge(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip4_less_eq(PG_GETARG_IP4(1), PG_GETARG_IP4(0)) ); -} - -PG_FUNCTION_INFO_V1(ip4_eq); -Datum -ip4_eq(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip4_equal(PG_GETARG_IP4(0), PG_GETARG_IP4(1)) ); -} - -PG_FUNCTION_INFO_V1(ip4_neq); -Datum -ip4_neq(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( !ip4_equal(PG_GETARG_IP4(0), PG_GETARG_IP4(1)) ); -} - -PG_FUNCTION_INFO_V1(ip4r_lt); -Datum -ip4r_lt(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip4r_lessthan(PG_GETARG_IP4R_P(0), PG_GETARG_IP4R_P(1)) ); -} - -PG_FUNCTION_INFO_V1(ip4r_le); -Datum -ip4r_le(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip4r_less_eq(PG_GETARG_IP4R_P(0), PG_GETARG_IP4R_P(1)) ); -} - -PG_FUNCTION_INFO_V1(ip4r_gt); -Datum -ip4r_gt(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip4r_lessthan(PG_GETARG_IP4R_P(1), PG_GETARG_IP4R_P(0)) ); -} - -PG_FUNCTION_INFO_V1(ip4r_ge); -Datum -ip4r_ge(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip4r_less_eq(PG_GETARG_IP4R_P(1), PG_GETARG_IP4R_P(0)) ); -} - -PG_FUNCTION_INFO_V1(ip4r_eq); -Datum -ip4r_eq(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip4r_equal(PG_GETARG_IP4R_P(0), PG_GETARG_IP4R_P(1)) ); -} - -PG_FUNCTION_INFO_V1(ip4r_neq); -Datum -ip4r_neq(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( !ip4r_equal(PG_GETARG_IP4R_P(0), PG_GETARG_IP4R_P(1)) ); -} - -PG_FUNCTION_INFO_V1(ip4r_overlaps); -Datum -ip4r_overlaps(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip4r_overlaps_internal(PG_GETARG_IP4R_P(0), - PG_GETARG_IP4R_P(1)) ); -} - -PG_FUNCTION_INFO_V1(ip4r_contains); -Datum -ip4r_contains(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip4r_contains_internal(PG_GETARG_IP4R_P(0), - PG_GETARG_IP4R_P(1), - TRUE) ); -} - -PG_FUNCTION_INFO_V1(ip4r_contains_strict); -Datum -ip4r_contains_strict(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip4r_contains_internal(PG_GETARG_IP4R_P(0), - PG_GETARG_IP4R_P(1), - FALSE) ); -} - -PG_FUNCTION_INFO_V1(ip4r_contained_by); -Datum -ip4r_contained_by(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip4r_contains_internal(PG_GETARG_IP4R_P(1), - PG_GETARG_IP4R_P(0), - TRUE) ); -} - -PG_FUNCTION_INFO_V1(ip4r_contained_by_strict); -Datum -ip4r_contained_by_strict(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip4r_contains_internal(PG_GETARG_IP4R_P(1), - PG_GETARG_IP4R_P(0), - FALSE) ); -} - -PG_FUNCTION_INFO_V1(ip4_contains); -Datum -ip4_contains(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip4_contains_internal(PG_GETARG_IP4R_P(0), PG_GETARG_IP4(1)) ); -} - -PG_FUNCTION_INFO_V1(ip4_contained_by); -Datum -ip4_contained_by(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip4_contains_internal(PG_GETARG_IP4R_P(1), PG_GETARG_IP4(0)) ); -} - -PG_FUNCTION_INFO_V1(ip4r_left_of); -Datum -ip4r_left_of(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip4r_left_internal(PG_GETARG_IP4R_P(0), PG_GETARG_IP4R_P(1)) ); -} - -PG_FUNCTION_INFO_V1(ip4r_right_of); -Datum -ip4r_right_of(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip4r_left_internal(PG_GETARG_IP4R_P(1), PG_GETARG_IP4R_P(0)) ); -} - - -PG_FUNCTION_INFO_V1(ip4r_union); -Datum -ip4r_union(PG_FUNCTION_ARGS) -{ - IP4R *res = (IP4R *) palloc(sizeof(IP4R)); - ip4r_union_internal(PG_GETARG_IP4R_P(0), PG_GETARG_IP4R_P(1), res); - PG_RETURN_IP4R_P(res); -} - -PG_FUNCTION_INFO_V1(ip4r_inter); -Datum -ip4r_inter(PG_FUNCTION_ARGS) -{ - IP4R *res = (IP4R *) palloc(sizeof(IP4R)); - if (ip4r_inter_internal(PG_GETARG_IP4R_P(0), PG_GETARG_IP4R_P(1), res)) - { - PG_RETURN_IP4R_P(res); - } - pfree(res); - PG_RETURN_NULL(); -} - -PG_FUNCTION_INFO_V1(ip4r_size); -Datum -ip4r_size(PG_FUNCTION_ARGS) -{ - double size = ip4r_metric(PG_GETARG_IP4R_P(0)); - PG_RETURN_FLOAT8(size); -} - -PG_FUNCTION_INFO_V1(ip4r_size_exact); -Datum -ip4r_size_exact(PG_FUNCTION_ARGS) -{ - int64 size = (int64) ip4r_metric(PG_GETARG_IP4R_P(0)); - PG_RETURN_DATUM(DirectFunctionCall1(int8_numeric, Int64GetDatumFast(size))); -} - -PG_FUNCTION_INFO_V1(ip4r_prefixlen); -Datum -ip4r_prefixlen(PG_FUNCTION_ARGS) -{ - IP4R *ipr = PG_GETARG_IP4R_P(0); - unsigned len = masklen(ipr->lower, ipr->upper); - if (len <= 32) - PG_RETURN_INT32((int32) len); - PG_RETURN_NULL(); -} - - -/***************************************************************************** - * Btree functions - *****************************************************************************/ - -PG_FUNCTION_INFO_V1(ip4r_cmp); -Datum -ip4r_cmp(PG_FUNCTION_ARGS) -{ - IP4R *a = PG_GETARG_IP4R_P(0); - IP4R *b = PG_GETARG_IP4R_P(1); - if (ip4r_lessthan(a,b)) - PG_RETURN_INT32(-1); - if (ip4r_equal(a,b)) - PG_RETURN_INT32(0); - PG_RETURN_INT32(1); -} - -PG_FUNCTION_INFO_V1(ip4_cmp); -Datum -ip4_cmp(PG_FUNCTION_ARGS) -{ - IP4 a = PG_GETARG_IP4(0); - IP4 b = PG_GETARG_IP4(1); - if (ip4_lessthan(a,b)) - PG_RETURN_INT32(-1); - if (ip4_equal(a,b)) - PG_RETURN_INT32(0); - PG_RETURN_INT32(1); -} - -/***************************************************************************** - * GiST functions - *****************************************************************************/ - -/* -** GiST support methods -*/ - -Datum gip4r_consistent(PG_FUNCTION_ARGS); -Datum gip4r_compress(PG_FUNCTION_ARGS); -Datum gip4r_decompress(PG_FUNCTION_ARGS); -Datum gip4r_penalty(PG_FUNCTION_ARGS); -Datum gip4r_picksplit(PG_FUNCTION_ARGS); -Datum gip4r_union(PG_FUNCTION_ARGS); -Datum gip4r_same(PG_FUNCTION_ARGS); -Datum gip4r_fetch(PG_FUNCTION_ARGS); - -static bool gip4r_leaf_consistent(IP4R * key, IP4R * query, StrategyNumber strategy); -static bool gip4r_internal_consistent(IP4R * key, IP4R * query, StrategyNumber strategy); - -/* -** The GiST Consistent method for IP ranges -** Should return false if for all data items x below entry, -** the predicate x op query == FALSE, where op is the oper -** corresponding to strategy in the pg_amop table. -*/ -PG_FUNCTION_INFO_V1(gip4r_consistent); -Datum -gip4r_consistent(PG_FUNCTION_ARGS) -{ - GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); - IP4R *query = (IP4R *) PG_GETARG_POINTER(1); - StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); - bool *recheck = (bool *) PG_GETARG_POINTER(4); - IP4R *key = (IP4R *) DatumGetPointer(entry->key); - bool retval; - - /* recheck is never needed with this type */ - if (recheck) - *recheck = false; - - /* - * * if entry is not leaf, use gip4r_internal_consistent, * else use - * gip4r_leaf_consistent - */ - if (GIST_LEAF(entry)) - retval = gip4r_leaf_consistent(key, query, strategy); - else - retval = gip4r_internal_consistent(key, query, strategy); - - PG_RETURN_BOOL(retval); -} - -/* -** The GiST Union method for IP ranges -** returns the minimal bounding IP4R that encloses all the entries in entryvec -*/ -PG_FUNCTION_INFO_V1(gip4r_union); -Datum -gip4r_union(PG_FUNCTION_ARGS) -{ - GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0); - int *sizep = (int *) PG_GETARG_POINTER(1); - GISTENTRY *ent = GISTENTRYVEC(entryvec); - - int numranges, i; - IP4R *out = (IP4R *) palloc(sizeof(IP4R)); - IP4R *tmp; - -#ifdef GIST_DEBUG - fprintf(stderr, "union\n"); -#endif - - numranges = GISTENTRYCOUNT(entryvec); - tmp = (IP4R *) DatumGetPointer(ent[0].key); - *sizep = sizeof(IP4R); - *out = *tmp; - - for (i = 1; i < numranges; i++) - { - tmp = (IP4R *) DatumGetPointer(ent[i].key); - if (tmp->lower < out->lower) - out->lower = tmp->lower; - if (tmp->upper > out->upper) - out->upper = tmp->upper; - } - - PG_RETURN_IP4R_P(out); -} - -/* -** GiST Compress and Decompress methods for IP ranges -** do not do anything. -*/ -PG_FUNCTION_INFO_V1(gip4r_compress); -Datum -gip4r_compress(PG_FUNCTION_ARGS) -{ - PG_RETURN_POINTER(PG_GETARG_POINTER(0)); -} - -PG_FUNCTION_INFO_V1(gip4r_decompress); -Datum -gip4r_decompress(PG_FUNCTION_ARGS) -{ - PG_RETURN_POINTER(PG_GETARG_POINTER(0)); -} - -PG_FUNCTION_INFO_V1(gip4r_fetch); -Datum -gip4r_fetch(PG_FUNCTION_ARGS) -{ - PG_RETURN_POINTER(PG_GETARG_POINTER(0)); -} - -/* -** The GiST Penalty method for IP ranges -** As in the R-tree paper, we use change in area as our penalty metric -*/ -PG_FUNCTION_INFO_V1(gip4r_penalty); -Datum -gip4r_penalty(PG_FUNCTION_ARGS) -{ - GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0); - GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1); - float *result = (float *) PG_GETARG_POINTER(2); - IP4R *key; - IP4R ud; - float tmp1, tmp2; - - key = (IP4R *) DatumGetPointer(origentry->key); - ud = *key; - tmp2 = ip4r_metric(&ud); - - key = (IP4R *) DatumGetPointer(newentry->key); - if (key->lower < ud.lower) - ud.lower = key->lower; - if (key->upper > ud.upper) - ud.upper = key->upper; - tmp1 = ip4r_metric(&ud); - - *result = tmp1 - tmp2; - -#ifdef GIST_DEBUG - fprintf(stderr, "penalty\n"); - fprintf(stderr, "\t%g\n", *result); -#endif - - PG_RETURN_POINTER(result); -} - - -/* Helper functions for picksplit. We might need to sort a list of - * ranges by size; these are for that. - */ - -struct gip4r_sort -{ - IP4R *key; - OffsetNumber pos; -}; - -static int -gip4r_sort_compare(const void *a, const void *b) -{ - double sa = ip4r_metric(((struct gip4r_sort *)a)->key); - double sb = ip4r_metric(((struct gip4r_sort *)b)->key); - return (sa > sb) ? 1 : ((sa == sb) ? 0 : -1); -} - -/* -** The GiST PickSplit method for IP ranges -** This is a linear-time algorithm based on a left/right split, -** based on the box functions in rtree_gist simplified to one -** dimension -*/ -PG_FUNCTION_INFO_V1(gip4r_picksplit); -Datum -gip4r_picksplit(PG_FUNCTION_ARGS) -{ - GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0); - GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1); - GISTENTRY *ent = GISTENTRYVEC(entryvec); - OffsetNumber i; - int nbytes; - OffsetNumber maxoff; - OffsetNumber *listL; - OffsetNumber *listR; - bool allisequal = true; - IP4R pageunion; - IP4R *cur; - IP4R *unionL; - IP4R *unionR; - int posL = 0; - int posR = 0; - - posL = posR = 0; - maxoff = GISTENTRYCOUNT(entryvec) - 1; - - cur = (IP4R *) DatumGetPointer(ent[FirstOffsetNumber].key); - pageunion = *cur; - - /* find MBR */ - for (i = OffsetNumberNext(FirstOffsetNumber); i <= maxoff; i = OffsetNumberNext(i)) - { - cur = (IP4R *) DatumGetPointer(ent[i].key); - if (allisequal == true - && (pageunion.lower != cur->lower || pageunion.upper != cur->upper)) - allisequal = false; - - if (cur->lower < pageunion.lower) - pageunion.lower = cur->lower; - if (cur->upper > pageunion.upper) - pageunion.upper = cur->upper; - } - - nbytes = (maxoff + 2) * sizeof(OffsetNumber); - listL = (OffsetNumber *) palloc(nbytes); - listR = (OffsetNumber *) palloc(nbytes); - unionL = (IP4R *) palloc(sizeof(IP4R)); - unionR = (IP4R *) palloc(sizeof(IP4R)); - v->spl_ldatum = PointerGetDatum(unionL); - v->spl_rdatum = PointerGetDatum(unionR); - v->spl_left = listL; - v->spl_right = listR; - - if (allisequal) - { - cur = (IP4R *) DatumGetPointer(ent[OffsetNumberNext(FirstOffsetNumber)].key); - if (ip4r_equal(cur, &pageunion)) - { - OffsetNumber split_at = FirstOffsetNumber + (maxoff - FirstOffsetNumber + 1)/2; - v->spl_nleft = v->spl_nright = 0; - *unionL = pageunion; - *unionR = pageunion; - - for (i = FirstOffsetNumber; i < split_at; i = OffsetNumberNext(i)) - v->spl_left[v->spl_nleft++] = i; - for (; i <= maxoff; i = OffsetNumberNext(i)) - v->spl_right[v->spl_nright++] = i; - - PG_RETURN_POINTER(v); - } - } - -#define ADDLIST( list_, u_, pos_, num_ ) do { \ - if ( pos_ ) { \ - if ( (u_)->upper < (cur)->upper ) (u_)->upper = (cur)->upper; \ - if ( (u_)->lower > (cur)->lower ) (u_)->lower = (cur)->lower; \ - } else { \ - *(u_) = *(cur); \ - } \ - (list_)[(pos_)++] = (num_); \ -} while(0) - - for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) - { - cur = (IP4R *) DatumGetPointer(ent[i].key); - if (cur->lower - pageunion.lower < pageunion.upper - cur->upper) - ADDLIST(listL, unionL, posL, i); - else - ADDLIST(listR, unionR, posR, i); - } - - /* bad disposition, sort by ascending size and resplit */ - if (posR == 0 || posL == 0) - { - struct gip4r_sort *arr = (struct gip4r_sort *) - palloc(sizeof(struct gip4r_sort) * (maxoff + FirstOffsetNumber)); - - for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) - { - arr[i].key = (IP4R *) DatumGetPointer(ent[i].key); - arr[i].pos = i; - } - - qsort(arr + FirstOffsetNumber, - maxoff - FirstOffsetNumber + 1, - sizeof(struct gip4r_sort), - gip4r_sort_compare); - - posL = posR = 0; - for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) - { - cur = arr[i].key; - if (cur->lower - pageunion.lower < pageunion.upper - cur->upper) - ADDLIST(listL, unionL, posL, arr[i].pos); - else if (cur->lower - pageunion.lower == pageunion.upper - cur->upper) - { - if (posL > posR) - ADDLIST(listR, unionR, posR, arr[i].pos); - else - ADDLIST(listL, unionL, posL, arr[i].pos); - } - else - ADDLIST(listR, unionR, posR, arr[i].pos); - } - pfree(arr); - } - - v->spl_nleft = posL; - v->spl_nright = posR; - - PG_RETURN_POINTER(v); -} - -#undef ADDLIST - -/* -** Equality methods -*/ -PG_FUNCTION_INFO_V1(gip4r_same); -Datum -gip4r_same(PG_FUNCTION_ARGS) -{ - IP4R *v1 = (IP4R *) PG_GETARG_POINTER(0); - IP4R *v2 = (IP4R *) PG_GETARG_POINTER(1); - bool *result = (bool *) PG_GETARG_POINTER(2); - - if (v1 && v2) - *result = ip4r_equal(v1,v2); - else - *result = (v1 == NULL && v2 == NULL); - -#ifdef GIST_DEBUG - fprintf(stderr, "same: %s\n", (*result ? "TRUE" : "FALSE")); -#endif - - PG_RETURN_POINTER(result); -} - - -/* - * Strategy numbers: - * OPERATOR 1 >>= , - * OPERATOR 2 <<= , - * OPERATOR 3 >> , - * OPERATOR 4 << , - * OPERATOR 5 && , - * OPERATOR 6 = , - */ - -/* -** SUPPORT ROUTINES -*/ -static bool -gip4r_leaf_consistent(IP4R * key, - IP4R * query, - StrategyNumber strategy) -{ -#ifdef GIST_QUERY_DEBUG - fprintf(stderr, "leaf_consistent, %d\n", strategy); -#endif - - switch (strategy) - { - case 1: /* left contains right nonstrict */ - return ip4r_contains_internal(key, query, TRUE); - case 2: /* left contained in right nonstrict */ - return ip4r_contains_internal(query, key, TRUE); - case 3: /* left contains right strict */ - return ip4r_contains_internal(key, query, FALSE); - case 4: /* left contained in right strict */ - return ip4r_contains_internal(query, key, FALSE); - case 5: /* left overlaps right */ - return ip4r_overlaps_internal(key, query); - case 6: /* left equal right */ - return ip4r_equal(key, query); - default: - return FALSE; - } -} - -/* logic notes: - * If the union value we're looking at overlaps with our query value - * at all, then any of the values underneath it might overlap with us - * or be contained by us, so all the "contained by" and "overlaps" - * cases degenerate to "overlap". - * If the union value is equal to the query value, then none of the - * values under it can strictly contain the query value, so for - * "contained" queries the strictness is preserved. - * If we're looking for an "equal" value, then we have to enter any - * subtree whose union contains (not strictly) our query value. - */ - -bool -gip4r_internal_consistent(IP4R * key, - IP4R * query, - StrategyNumber strategy) -{ -#ifdef GIST_QUERY_DEBUG - fprintf(stderr, "internal_consistent, %d\n", strategy); -#endif - - switch (strategy) - { - case 2: /* left contained in right nonstrict */ - case 4: /* left contained in right strict */ - case 5: /* left overlaps right */ - return ip4r_overlaps_internal(key, query); - case 3: /* left contains right strict */ - return ip4r_contains_internal(key, query, FALSE); - case 1: /* left contains right nonstrict */ - case 6: /* left equal right */ - return ip4r_contains_internal(key, query, TRUE); - default: - return FALSE; - } -} - -/* end */ diff -Nru ip4r-2.3/ip4r.control ip4r-2.4/ip4r.control --- ip4r-2.3/ip4r.control 2018-05-24 21:30:28.000000000 +0000 +++ ip4r-2.4/ip4r.control 2018-11-21 06:35:30.000000000 +0000 @@ -1,4 +1,4 @@ # ip4r -default_version = '2.2' +default_version = '2.4' relocatable = 'true' module_pathname = '$libdir/ip4r' diff -Nru ip4r-2.3/ip4r_funcs.h ip4r-2.4/ip4r_funcs.h --- ip4r-2.3/ip4r_funcs.h 2018-05-24 21:30:28.000000000 +0000 +++ ip4r-2.4/ip4r_funcs.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,221 +0,0 @@ -/* $Id: ip4r_funcs.h,v 1.1 2011/08/03 20:16:03 andrewsn Exp $ */ - - -static inline -uint32 hostmask(unsigned masklen) -{ - return (masklen) ? ( (((uint32)(1U)) << (32-masklen)) - 1U ) : 0xFFFFFFFFU; -} - -static inline -uint32 netmask(unsigned masklen) -{ - return ~hostmask(masklen); -} - -/* if LO and HI are ends of a CIDR prefix, return the mask length. - * If not, returns ~0. - */ - -static inline -unsigned masklen(uint32 lo, uint32 hi) -{ - uint32 d = (lo ^ hi) + 1; - /* at this point, d can be: - * 0 if A and B have all bits different - * 1 if A and B are equal - * 1 << (32-masklen) - * some other value if A and B are not ends of a CIDR range - * but in any case, after extracting the masklen, we have to - * recheck because some non-CIDR ranges will produce the same - * results. - */ - int fbit = ffs(d); - switch (fbit) - { - case 0: return (lo == 0 && hi == ~0) ? 0 : ~0; - case 1: return (lo == hi) ? 32 : ~0; - default: - if ( ((uint32)(1U) << (fbit-1)) == d ) - { - uint32 mask = hostmask(33-fbit); - if ((lo & mask) == 0 && (hi & mask) == mask) - return 33-fbit; - } - return ~0; - } -} - -static inline -bool ip4_valid_netmask(uint32 mask) -{ - uint32 d = ~mask + 1; - /* at this point, d can be: - * 0 if mask was 0x00000000 (valid) - * 1 << (32-masklen) (valid) - * some other value (invalid) - */ - int fbit = ffs(d); - switch (fbit) - { - case 0: - return true; - default: - return ( ((uint32)(1U) << (fbit-1)) == d ); - } -} - - -static inline -bool ip4r_from_cidr(IP4 prefix, unsigned masklen, IP4R *ipr) -{ - uint32 mask = hostmask(masklen); - if (masklen > 32) - return FALSE; - if (prefix & mask) - return FALSE; - ipr->lower = prefix; - ipr->upper = prefix | mask; - return TRUE; -} - -static inline -bool ip4r_from_inet(IP4 addr, unsigned masklen, IP4R *ipr) -{ - uint32 mask = hostmask(masklen); - if (masklen > 32) - return FALSE; - ipr->lower = addr & ~mask; - ipr->upper = addr | mask; - return TRUE; -} - - -/* comparisons */ - -static inline -bool ip4_equal(IP4 a, IP4 b) -{ - return (a == b); -} - -static inline -bool ip4_lessthan(IP4 a, IP4 b) -{ - return (a < b); -} - -static inline -bool ip4_less_eq(IP4 a, IP4 b) -{ - return (a <= b); -} - -/* helpers for union/intersection for indexing */ - -static inline -IP4R *ip4r_union_internal(IP4R *a, IP4R *b, IP4R *result) -{ - if (a->lower < b->lower) - result->lower = a->lower; - else - result->lower = b->lower; - - if (a->upper > b->upper) - result->upper = a->upper; - else - result->upper = b->upper; - - return result; -} - -static inline -IP4R *ip4r_inter_internal(IP4R *a, IP4R *b, IP4R *result) -{ - if (a->upper < b->lower || a->lower > b->upper) - { - /* disjoint */ - result->lower = 1; - result->upper = 0; /* INVALID VALUE */ - return NULL; - } - - if (a->upper < b->upper) - result->upper = a->upper; - else - result->upper = b->upper; - - if (a->lower > b->lower) - result->lower = a->lower; - else - result->lower = b->lower; - - return result; -} - -static inline -double ip4r_metric(IP4R *v) -{ - if (!v) - return 0.0; - return ((v->upper - v->lower) + 1.0); -} - -static inline -bool ip4r_equal(IP4R *a, IP4R *b) -{ - return (a->lower == b->lower && a->upper == b->upper); -} - -static inline -bool ip4r_lessthan(IP4R *a, IP4R *b) -{ - return (a->lower == b->lower) ? (a->upper < b->upper) : (a->lower < b->lower); -} - -static inline -bool ip4r_less_eq(IP4R *a, IP4R *b) -{ - return (a->lower == b->lower) ? (a->upper <= b->upper) : (a->lower < b->lower); -} - -static inline -bool ip4r_contains_internal(IP4R *left, IP4R *right, bool eqval) -{ - if (ip4r_equal(left,right)) - return eqval; - return ((left->lower <= right->lower) && (left->upper >= right->upper)); -} - -static inline -bool ip4r_overlaps_internal(IP4R *left, IP4R *right) -{ - return (left->upper >= right->lower && left->lower <= right->upper); -} - -static inline -bool ip4_contains_internal(IP4R *left, IP4 right) -{ - return (left->lower <= right && left->upper >= right); -} - -static inline -bool ip4r_left_internal(IP4R *left, IP4R *right) -{ - return (left->upper < right->lower); -} - -static inline -bool ip4r_extends_left_of_internal(IP4R *left, IP4R *right) -{ - return (left->lower < right->lower); -} - -static inline -bool ip4r_extends_right_of_internal(IP4R *left, IP4R *right) -{ - return (left->upper > right->upper); -} - - -/* end */ diff -Nru ip4r-2.3/ip4r_module.c ip4r-2.4/ip4r_module.c --- ip4r-2.3/ip4r_module.c 2018-05-24 21:30:28.000000000 +0000 +++ ip4r-2.4/ip4r_module.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,6 +0,0 @@ -/* $Id: ip4r_module.c,v 1.1 2011/08/22 14:06:31 andrewsn Exp $ */ - -#include "ipr.h" - -PG_MODULE_MAGIC; - diff -Nru ip4r-2.3/ip4r--unpackaged1--2.0.sql ip4r-2.4/ip4r--unpackaged1--2.0.sql --- ip4r-2.3/ip4r--unpackaged1--2.0.sql 2018-05-24 21:30:28.000000000 +0000 +++ ip4r-2.4/ip4r--unpackaged1--2.0.sql 1970-01-01 00:00:00.000000000 +0000 @@ -1,753 +0,0 @@ --- ip4r extension - --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "CREATE EXTENSION ip4r" to load this file. \quit - --- ---------------------------------------------------------------------- --- Type definitions - ---CREATE TYPE ip4; - -CREATE OR REPLACE FUNCTION ip4_in(cstring) RETURNS ip4 AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip4_out(ip4) RETURNS cstring AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip4_recv(internal) RETURNS ip4 AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip4_send(ip4) RETURNS bytea AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -/* -CREATE TYPE ip4 ( - INPUT = ip4_in, OUTPUT = ip4_out, - RECEIVE = ip4_recv, SEND = ip4_send, - INTERNALLENGTH = 4, ALIGNMENT = int4, PASSEDBYVALUE -); -*/ - -ALTER EXTENSION ip4r ADD TYPE ip4; - -COMMENT ON TYPE ip4 IS 'IPv4 address ''#.#.#.#'''; - ---CREATE TYPE ip4r; - -CREATE OR REPLACE FUNCTION ip4r_in(cstring) RETURNS ip4r AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip4r_out(ip4r) RETURNS cstring AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip4r_recv(internal) RETURNS ip4r AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip4r_send(ip4r) RETURNS bytea AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -/* -CREATE TYPE ip4r ( - INPUT = ip4r_in, OUTPUT = ip4r_out, - RECEIVE = ip4r_recv, SEND = ip4r_send, - INTERNALLENGTH = 8, ALIGNMENT = int4 -); -*/ - -ALTER EXTENSION ip4r ADD TYPE ip4r; - -COMMENT ON TYPE ip4r IS 'IPv4 range ''#.#.#.#-#.#.#.#'' or ''#.#.#.#/#'' or ''#.#.#.#'''; - -CREATE TYPE ip6; - -CREATE OR REPLACE FUNCTION ip6_in(cstring) RETURNS ip6 AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6_out(ip6) RETURNS cstring AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6_recv(internal) RETURNS ip6 AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6_send(ip6) RETURNS bytea AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -CREATE TYPE ip6 ( - INPUT = ip6_in, OUTPUT = ip6_out, - RECEIVE = ip6_recv, SEND = ip6_send, - INTERNALLENGTH = 16, ALIGNMENT = double -); - -COMMENT ON TYPE ip6 IS 'IPv6 address ''xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx'''; - -CREATE TYPE ip6r; - -CREATE OR REPLACE FUNCTION ip6r_in(cstring) RETURNS ip6r AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6r_out(ip6r) RETURNS cstring AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6r_recv(internal) RETURNS ip6r AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6r_send(ip6r) RETURNS bytea AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -CREATE TYPE ip6r ( - INPUT = ip6r_in, OUTPUT = ip6r_out, - RECEIVE = ip6r_recv, SEND = ip6r_send, - INTERNALLENGTH = 32, ALIGNMENT = double -); - -COMMENT ON TYPE ip6r IS 'IPv6 range ''#-#'' or ''#/#'' or ''#'''; - -CREATE TYPE ipaddress; - -CREATE OR REPLACE FUNCTION ipaddress_in(cstring) RETURNS ipaddress AS 'MODULE_PATHNAME','ipaddr_in' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ipaddress_out(ipaddress) RETURNS cstring AS 'MODULE_PATHNAME','ipaddr_out' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ipaddress_recv(internal) RETURNS ipaddress AS 'MODULE_PATHNAME','ipaddr_recv' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ipaddress_send(ipaddress) RETURNS bytea AS 'MODULE_PATHNAME','ipaddr_send' LANGUAGE C IMMUTABLE STRICT; - -CREATE TYPE ipaddress ( - INPUT = ipaddress_in, OUTPUT = ipaddress_out, - RECEIVE = ipaddress_recv, SEND = ipaddress_send, - INTERNALLENGTH = VARIABLE, ALIGNMENT = int4, STORAGE = main -); - -COMMENT ON TYPE ipaddress IS 'IPv4 or IPv6 address'; - -CREATE TYPE iprange; - -CREATE OR REPLACE FUNCTION iprange_in(cstring) RETURNS iprange AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange_out(iprange) RETURNS cstring AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange_recv(internal) RETURNS iprange AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange_send(iprange) RETURNS bytea AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -CREATE TYPE iprange ( - INPUT = iprange_in, OUTPUT = iprange_out, - RECEIVE = iprange_recv, SEND = iprange_send, - INTERNALLENGTH = VARIABLE, ALIGNMENT = int4, STORAGE = main -); - -COMMENT ON TYPE iprange IS 'IPv4 or IPv6 range'; - --- ---------------------------------------------------------------------- --- Cast functions (inward) - -CREATE OR REPLACE FUNCTION ip4(bigint) RETURNS ip4 AS 'MODULE_PATHNAME','ip4_cast_from_bigint' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip4(double precision) RETURNS ip4 AS 'MODULE_PATHNAME','ip4_cast_from_double' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip4(numeric) RETURNS ip4 AS 'MODULE_PATHNAME','ip4_cast_from_numeric' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip4(inet) RETURNS ip4 AS 'MODULE_PATHNAME','ip4_cast_from_inet' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip4(text) RETURNS ip4 AS 'MODULE_PATHNAME','ip4_cast_from_text' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip4(ipaddress) RETURNS ip4 AS 'MODULE_PATHNAME','ipaddr_cast_to_ip4' LANGUAGE C IMMUTABLE STRICT; - -CREATE OR REPLACE FUNCTION ip6(numeric) RETURNS ip6 AS 'MODULE_PATHNAME','ip6_cast_from_numeric' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6(inet) RETURNS ip6 AS 'MODULE_PATHNAME','ip6_cast_from_inet' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6(text) RETURNS ip6 AS 'MODULE_PATHNAME','ip6_cast_from_text' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6(ipaddress) RETURNS ip6 AS 'MODULE_PATHNAME','ipaddr_cast_to_ip6' LANGUAGE C IMMUTABLE STRICT; - -CREATE OR REPLACE FUNCTION ipaddress(inet) RETURNS ipaddress AS 'MODULE_PATHNAME','ipaddr_cast_from_inet' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ipaddress(ip4) RETURNS ipaddress AS 'MODULE_PATHNAME','ipaddr_cast_from_ip4' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ipaddress(ip6) RETURNS ipaddress AS 'MODULE_PATHNAME','ipaddr_cast_from_ip6' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ipaddress(text) RETURNS ipaddress AS 'MODULE_PATHNAME','ipaddr_cast_from_text' LANGUAGE C IMMUTABLE STRICT; - -CREATE OR REPLACE FUNCTION ip4r(cidr) RETURNS ip4r AS 'MODULE_PATHNAME','ip4r_cast_from_cidr' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip4r(ip4) RETURNS ip4r AS 'MODULE_PATHNAME','ip4r_cast_from_ip4' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip4r(text) RETURNS ip4r AS 'MODULE_PATHNAME','ip4r_cast_from_text' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip4r(iprange) RETURNS ip4r AS 'MODULE_PATHNAME','iprange_cast_to_ip4r' LANGUAGE C IMMUTABLE STRICT; - -CREATE OR REPLACE FUNCTION ip6r(cidr) RETURNS ip6r AS 'MODULE_PATHNAME','ip6r_cast_from_cidr' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6r(ip6) RETURNS ip6r AS 'MODULE_PATHNAME','ip6r_cast_from_ip6' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6r(text) RETURNS ip6r AS 'MODULE_PATHNAME','ip6r_cast_from_text' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6r(iprange) RETURNS ip6r AS 'MODULE_PATHNAME','iprange_cast_to_ip6r' LANGUAGE C IMMUTABLE STRICT; - -CREATE OR REPLACE FUNCTION iprange(cidr) RETURNS iprange AS 'MODULE_PATHNAME','iprange_cast_from_cidr' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange(ip4) RETURNS iprange AS 'MODULE_PATHNAME','iprange_cast_from_ip4' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange(ip6) RETURNS iprange AS 'MODULE_PATHNAME','iprange_cast_from_ip6' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange(ip4r) RETURNS iprange AS 'MODULE_PATHNAME','iprange_cast_from_ip4r' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange(ip6r) RETURNS iprange AS 'MODULE_PATHNAME','iprange_cast_from_ip6r' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange(ipaddress) RETURNS iprange AS 'MODULE_PATHNAME','iprange_cast_from_ipaddr' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange(text) RETURNS iprange AS 'MODULE_PATHNAME','iprange_cast_from_text' LANGUAGE C IMMUTABLE STRICT; - --- ---------------------------------------------------------------------- --- Cast functions (outward) - -CREATE OR REPLACE FUNCTION cidr(ip4) RETURNS cidr AS 'MODULE_PATHNAME','ip4_cast_to_cidr' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION cidr(ip4r) RETURNS cidr AS 'MODULE_PATHNAME','ip4r_cast_to_cidr' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION cidr(ip6) RETURNS cidr AS 'MODULE_PATHNAME','ip6_cast_to_cidr' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION cidr(ip6r) RETURNS cidr AS 'MODULE_PATHNAME','ip6r_cast_to_cidr' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION cidr(ipaddress) RETURNS cidr AS 'MODULE_PATHNAME','ipaddr_cast_to_cidr' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION cidr(iprange) RETURNS cidr AS 'MODULE_PATHNAME','iprange_cast_to_cidr' LANGUAGE C IMMUTABLE STRICT; - -CREATE OR REPLACE FUNCTION text(ip4) RETURNS text AS 'MODULE_PATHNAME','ip4_cast_to_text' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION text(ip4r) RETURNS text AS 'MODULE_PATHNAME','ip4r_cast_to_text' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION text(ip6) RETURNS text AS 'MODULE_PATHNAME','ip6_cast_to_text' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION text(ip6r) RETURNS text AS 'MODULE_PATHNAME','ip6r_cast_to_text' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION text(ipaddress) RETURNS text AS 'MODULE_PATHNAME','ipaddr_cast_to_text' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION text(iprange) RETURNS text AS 'MODULE_PATHNAME','iprange_cast_to_text' LANGUAGE C IMMUTABLE STRICT; - -CREATE OR REPLACE FUNCTION to_bigint(ip4) RETURNS bigint AS 'MODULE_PATHNAME','ip4_cast_to_bigint' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION to_double(ip4) RETURNS double precision AS 'MODULE_PATHNAME','ip4_cast_to_double' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION to_numeric(ip4) RETURNS numeric AS 'MODULE_PATHNAME','ip4_cast_to_numeric' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION to_numeric(ip6) RETURNS numeric AS 'MODULE_PATHNAME','ip6_cast_to_numeric' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION to_numeric(ipaddress) RETURNS numeric AS 'MODULE_PATHNAME','ipaddr_cast_to_numeric' LANGUAGE C IMMUTABLE STRICT; - --- ---------------------------------------------------------------------- --- Cast definitions (outward) - --- all these are explicit, with the exception of casts from single-address --- types to "cidr", which we make assignment casts since they are lossless --- and preserve general semantics. - -ALTER EXTENSION ip4r ADD CAST (ip4 as bigint); -ALTER EXTENSION ip4r ADD CAST (ip4 as double precision); -CREATE CAST (ip4 as numeric) WITH FUNCTION to_numeric(ip4); -ALTER EXTENSION ip4r ADD CAST (ip4 as text); - -ALTER EXTENSION ip4r ADD CAST (ip4 as cidr); - -ALTER EXTENSION ip4r ADD CAST (ip4r as cidr); -ALTER EXTENSION ip4r ADD CAST (ip4r as text); - -CREATE CAST (ip6 as numeric) WITH FUNCTION to_numeric(ip6); -CREATE CAST (ip6 as text) WITH FUNCTION text(ip6); - -CREATE CAST (ip6 as cidr) WITH FUNCTION cidr(ip6) AS ASSIGNMENT; - -CREATE CAST (ip6r as cidr) WITH FUNCTION cidr(ip6r); -CREATE CAST (ip6r as text) WITH FUNCTION text(ip6r); - -CREATE CAST (ipaddress as numeric) WITH FUNCTION to_numeric(ipaddress); -CREATE CAST (ipaddress as text) WITH FUNCTION text(ipaddress); - -CREATE CAST (ipaddress as cidr) WITH FUNCTION cidr(ipaddress) AS ASSIGNMENT; - -CREATE CAST (iprange as cidr) WITH FUNCTION cidr(iprange); -CREATE CAST (iprange as text) WITH FUNCTION text(iprange); - --- ---------------------------------------------------------------------- --- Cast definitions (inward) - --- these are explicit except for casts from inet/cidr types. Even though --- such casts are lossy for inet, since the masklen isn't preserved, the --- semantics and common usage are enough to justify an assignment cast. - -ALTER EXTENSION ip4r ADD CAST (text as ip4); -ALTER EXTENSION ip4r ADD CAST (text as ip4r); -CREATE CAST (text as ip6) WITH FUNCTION ip6(text); -CREATE CAST (text as ip6r) WITH FUNCTION ip6r(text); -CREATE CAST (text as ipaddress) WITH FUNCTION ipaddress(text); -CREATE CAST (text as iprange) WITH FUNCTION iprange(text); - -ALTER EXTENSION ip4r ADD CAST (bigint as ip4); -ALTER EXTENSION ip4r ADD CAST (double precision as ip4); - -CREATE CAST (numeric as ip4) WITH FUNCTION ip4(numeric); -CREATE CAST (numeric as ip6) WITH FUNCTION ip6(numeric); - -ALTER EXTENSION ip4r ADD CAST (cidr as ip4r); -CREATE CAST (cidr as ip6r) WITH FUNCTION ip6r(cidr) AS ASSIGNMENT; -CREATE CAST (cidr as iprange) WITH FUNCTION iprange(cidr) AS ASSIGNMENT; - -ALTER EXTENSION ip4r ADD CAST (inet as ip4); -CREATE CAST (inet as ip6) WITH FUNCTION ip6(inet) AS ASSIGNMENT; -CREATE CAST (inet as ipaddress) WITH FUNCTION ipaddress(inet) AS ASSIGNMENT; - --- ---------------------------------------------------------------------- --- Cast definitions (cross-type) - --- the lossless "upward" casts are made implict. - -ALTER EXTENSION ip4r ADD CAST (ip4 as ip4r); -CREATE CAST (ip4 as ipaddress) WITH FUNCTION ipaddress(ip4) AS IMPLICIT; -CREATE CAST (ip4 as iprange) WITH FUNCTION iprange(ip4) AS IMPLICIT; -CREATE CAST (ip4r as iprange) WITH FUNCTION iprange(ip4r) AS IMPLICIT; - -CREATE CAST (ip6 as ip6r) WITH FUNCTION ip6r(ip6) AS IMPLICIT; -CREATE CAST (ip6 as ipaddress) WITH FUNCTION ipaddress(ip6) AS IMPLICIT; -CREATE CAST (ip6 as iprange) WITH FUNCTION iprange(ip6) AS IMPLICIT; -CREATE CAST (ip6r as iprange) WITH FUNCTION iprange(ip6r) AS IMPLICIT; - -CREATE CAST (ipaddress as iprange) WITH FUNCTION iprange(ipaddress) AS IMPLICIT; - -CREATE CAST (ipaddress as ip4) WITH FUNCTION ip4(ipaddress); -CREATE CAST (ipaddress as ip6) WITH FUNCTION ip6(ipaddress); - -CREATE CAST (iprange as ip4r) WITH FUNCTION ip4r(iprange); -CREATE CAST (iprange as ip6r) WITH FUNCTION ip6r(iprange); - --- ---------------------------------------------------------------------- --- Constructor functions - -CREATE OR REPLACE FUNCTION ip4r(ip4,ip4) RETURNS ip4r AS 'MODULE_PATHNAME', 'ip4r_from_ip4s' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6r(ip6,ip6) RETURNS ip6r AS 'MODULE_PATHNAME', 'ip6r_from_ip6s' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange(ip4,ip4) RETURNS iprange AS 'MODULE_PATHNAME', 'iprange_from_ip4s' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange(ip6,ip6) RETURNS iprange AS 'MODULE_PATHNAME', 'iprange_from_ip6s' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange(ipaddress,ipaddress) RETURNS iprange AS 'MODULE_PATHNAME', 'iprange_from_ipaddrs' LANGUAGE C IMMUTABLE STRICT; - --- ---------------------------------------------------------------------- --- Utility functions (no operator equivalent) - -CREATE OR REPLACE FUNCTION family(ip4) RETURNS integer AS $f$ select 4; $f$ LANGUAGE SQL IMMUTABLE; -CREATE OR REPLACE FUNCTION family(ip4r) RETURNS integer AS $f$ select 4; $f$ LANGUAGE SQL IMMUTABLE; -CREATE OR REPLACE FUNCTION family(ip6) RETURNS integer AS $f$ select 6; $f$ LANGUAGE SQL IMMUTABLE; -CREATE OR REPLACE FUNCTION family(ip6r) RETURNS integer AS $f$ select 6; $f$ LANGUAGE SQL IMMUTABLE; -CREATE OR REPLACE FUNCTION family(ipaddress) RETURNS integer AS 'MODULE_PATHNAME', 'ipaddr_family' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION family(iprange) RETURNS integer AS 'MODULE_PATHNAME', 'iprange_family' LANGUAGE C IMMUTABLE STRICT; - -CREATE OR REPLACE FUNCTION ip4_netmask(integer) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_netmask' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6_netmask(integer) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_netmask' LANGUAGE C IMMUTABLE STRICT; - -CREATE OR REPLACE FUNCTION is_cidr(ip4r) RETURNS boolean AS 'MODULE_PATHNAME', 'ip4r_is_cidr' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION is_cidr(ip6r) RETURNS boolean AS 'MODULE_PATHNAME', 'ip6r_is_cidr' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION is_cidr(iprange) RETURNS boolean AS 'MODULE_PATHNAME', 'iprange_is_cidr' LANGUAGE C IMMUTABLE STRICT; - -CREATE OR REPLACE FUNCTION masklen(ip4r) RETURNS integer AS 'MODULE_PATHNAME','ip4r_prefixlen' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION masklen(ip6r) RETURNS integer AS 'MODULE_PATHNAME','ip6r_prefixlen' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION masklen(iprange) RETURNS integer AS 'MODULE_PATHNAME','iprange_prefixlen' LANGUAGE C IMMUTABLE STRICT; - -CREATE OR REPLACE FUNCTION lower(ip4r) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4r_lower' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION lower(ip6r) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6r_lower' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION lower(iprange) RETURNS ipaddress AS 'MODULE_PATHNAME', 'iprange_lower' LANGUAGE C IMMUTABLE STRICT; - -CREATE OR REPLACE FUNCTION upper(ip4r) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4r_upper' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION upper(ip6r) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6r_upper' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION upper(iprange) RETURNS ipaddress AS 'MODULE_PATHNAME', 'iprange_upper' LANGUAGE C IMMUTABLE STRICT; - -CREATE OR REPLACE FUNCTION ip4_net_lower(ip4,integer) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_net_lower' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6_net_lower(ip6,integer) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_net_lower' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ipaddress_net_lower(ipaddress,integer) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_net_lower' LANGUAGE C IMMUTABLE STRICT; - -CREATE OR REPLACE FUNCTION ip4_net_upper(ip4,integer) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_net_upper' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6_net_upper(ip6,integer) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_net_upper' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ipaddress_net_upper(ipaddress,integer) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_net_upper' LANGUAGE C IMMUTABLE STRICT; - -CREATE OR REPLACE FUNCTION ip4r_union(ip4r, ip4r) RETURNS ip4r AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6r_union(ip6r, ip6r) RETURNS ip6r AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange_union(iprange, iprange) RETURNS iprange AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -CREATE OR REPLACE FUNCTION ip4r_inter(ip4r,ip4r) RETURNS ip4r AS 'MODULE_PATHNAME','ip4r_inter' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6r_inter(ip6r,ip6r) RETURNS ip6r AS 'MODULE_PATHNAME','ip6r_inter' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange_inter(iprange,iprange) RETURNS iprange AS 'MODULE_PATHNAME','iprange_inter' LANGUAGE C IMMUTABLE STRICT; - --- ---------------------------------------------------------------------- --- Functions with operator equivalents - --- it's intended that either the function form or the operator form be used, --- as desired. - --- (ip / len) or (ip / mask) - -CREATE OR REPLACE FUNCTION ip4r_net_mask(ip4,ip4) RETURNS ip4r AS 'MODULE_PATHNAME','ip4r_net_mask' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6r_net_mask(ip6,ip6) RETURNS ip6r AS 'MODULE_PATHNAME','ip6r_net_mask' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange_net_mask(ip4,ip4) RETURNS iprange AS 'MODULE_PATHNAME','iprange_net_mask_ip4' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange_net_mask(ip6,ip6) RETURNS iprange AS 'MODULE_PATHNAME','iprange_net_mask_ip6' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange_net_mask(ipaddress,ipaddress) RETURNS iprange AS 'MODULE_PATHNAME','iprange_net_mask' LANGUAGE C IMMUTABLE STRICT; - -CREATE OR REPLACE FUNCTION ip4r_net_prefix(ip4,integer) RETURNS ip4r AS 'MODULE_PATHNAME','ip4r_net_prefix' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6r_net_prefix(ip6,integer) RETURNS ip6r AS 'MODULE_PATHNAME','ip6r_net_prefix' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange_net_prefix(ip4,integer) RETURNS iprange AS 'MODULE_PATHNAME','iprange_net_prefix_ip4' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange_net_prefix(ip6,integer) RETURNS iprange AS 'MODULE_PATHNAME','iprange_net_prefix_ip6' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange_net_prefix(ipaddress,integer) RETURNS iprange AS 'MODULE_PATHNAME','iprange_net_prefix' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR / ( LEFTARG = ip4, RIGHTARG = ip4, PROCEDURE = ip4r_net_mask ); -CREATE OPERATOR / ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6r_net_mask ); -CREATE OPERATOR / ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = iprange_net_mask ); -CREATE OPERATOR / ( LEFTARG = ip4, RIGHTARG = integer, PROCEDURE = ip4r_net_prefix ); -CREATE OPERATOR / ( LEFTARG = ip6, RIGHTARG = integer, PROCEDURE = ip6r_net_prefix ); -CREATE OPERATOR / ( LEFTARG = ipaddress, RIGHTARG = integer, PROCEDURE = iprange_net_prefix ); - --- @ ipr (approximate size) or @@ ipr (exact size) - -CREATE OR REPLACE FUNCTION ip4r_size(ip4r) RETURNS double precision AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6r_size(ip6r) RETURNS double precision AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange_size(iprange) RETURNS double precision AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -CREATE OR REPLACE FUNCTION ip4r_size_exact(ip4r) RETURNS numeric AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6r_size_exact(ip6r) RETURNS numeric AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange_size_exact(iprange) RETURNS numeric AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR @ ( RIGHTARG = ip4r, PROCEDURE = ip4r_size ); -CREATE OPERATOR @ ( RIGHTARG = ip6r, PROCEDURE = ip6r_size ); -CREATE OPERATOR @ ( RIGHTARG = iprange, PROCEDURE = iprange_size ); - -CREATE OPERATOR @@ ( RIGHTARG = ip4r, PROCEDURE = ip4r_size_exact ); -CREATE OPERATOR @@ ( RIGHTARG = ip6r, PROCEDURE = ip6r_size_exact ); -CREATE OPERATOR @@ ( RIGHTARG = iprange, PROCEDURE = iprange_size_exact ); - --- ---------------------------------------------------------------------- --- Operators - --- the function forms of these aren't intended for general use - --- bitwise ops: and (a & b), or (a | b), xor (a # b), not (~a) - -CREATE OR REPLACE FUNCTION ip4_and(ip4,ip4) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_and' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6_and(ip6,ip6) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_and' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ipaddress_and(ipaddress,ipaddress) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_and' LANGUAGE C IMMUTABLE STRICT; - -ALTER EXTENSION ip4r ADD OPERATOR &(ip4,ip4); -CREATE OPERATOR & ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_and ); -CREATE OPERATOR & ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_and ); - -CREATE OR REPLACE FUNCTION ip4_or(ip4,ip4) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_or' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6_or(ip6,ip6) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_or' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ipaddress_or(ipaddress,ipaddress) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_or' LANGUAGE C IMMUTABLE STRICT; - -ALTER EXTENSION ip4r ADD OPERATOR |(ip4,ip4); -CREATE OPERATOR | ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_or ); -CREATE OPERATOR | ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_or ); - -CREATE OR REPLACE FUNCTION ip4_not(ip4) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_not' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6_not(ip6) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_not' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ipaddress_not(ipaddress) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_not' LANGUAGE C IMMUTABLE STRICT; - -ALTER EXTENSION ip4r ADD OPERATOR ~(NONE,ip4); -CREATE OPERATOR ~ ( RIGHTARG = ip6, PROCEDURE = ip6_not ); -CREATE OPERATOR ~ ( RIGHTARG = ipaddress, PROCEDURE = ipaddress_not ); - -CREATE OR REPLACE FUNCTION ip4_xor(ip4,ip4) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_xor' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6_xor(ip6,ip6) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_xor' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ipaddress_xor(ipaddress,ipaddress) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_xor' LANGUAGE C IMMUTABLE STRICT; - -ALTER EXTENSION ip4r ADD OPERATOR #(ip4,ip4); -CREATE OPERATOR # ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_xor ); -CREATE OPERATOR # ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_xor ); - --- arithmetic ops: (ip + n), (ip - n), (ip - ip) where n is a numeric or integer type - -CREATE OR REPLACE FUNCTION ip4_plus_bigint(ip4,bigint) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_plus_bigint' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip4_plus_int(ip4,integer) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_plus_int' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip4_plus_numeric(ip4,numeric) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_plus_numeric' LANGUAGE C IMMUTABLE STRICT; - -ALTER EXTENSION ip4r ADD OPERATOR +(ip4,bigint); -ALTER EXTENSION ip4r ADD OPERATOR +(ip4,integer); -CREATE OPERATOR + ( LEFTARG = ip4, RIGHTARG = numeric, PROCEDURE = ip4_plus_numeric ); - -CREATE OR REPLACE FUNCTION ip6_plus_bigint(ip6,bigint) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_plus_bigint' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6_plus_int(ip6,integer) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_plus_int' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6_plus_numeric(ip6,numeric) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_plus_numeric' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR + ( LEFTARG = ip6, RIGHTARG = bigint, PROCEDURE = ip6_plus_bigint ); -CREATE OPERATOR + ( LEFTARG = ip6, RIGHTARG = integer, PROCEDURE = ip6_plus_int ); -CREATE OPERATOR + ( LEFTARG = ip6, RIGHTARG = numeric, PROCEDURE = ip6_plus_numeric ); - -CREATE OR REPLACE FUNCTION ipaddress_plus_bigint(ipaddress,bigint) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_plus_bigint' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ipaddress_plus_int(ipaddress,integer) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_plus_int' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ipaddress_plus_numeric(ipaddress,numeric) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_plus_numeric' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR + ( LEFTARG = ipaddress, RIGHTARG = bigint, PROCEDURE = ipaddress_plus_bigint ); -CREATE OPERATOR + ( LEFTARG = ipaddress, RIGHTARG = integer, PROCEDURE = ipaddress_plus_int ); -CREATE OPERATOR + ( LEFTARG = ipaddress, RIGHTARG = numeric, PROCEDURE = ipaddress_plus_numeric ); - -CREATE OR REPLACE FUNCTION ip4_minus_bigint(ip4,bigint) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_minus_bigint' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip4_minus_int(ip4,integer) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_minus_int' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip4_minus_numeric(ip4,numeric) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_minus_numeric' LANGUAGE C IMMUTABLE STRICT; - -ALTER EXTENSION ip4r ADD OPERATOR -(ip4,bigint); -ALTER EXTENSION ip4r ADD OPERATOR -(ip4,integer); -CREATE OPERATOR - ( LEFTARG = ip4, RIGHTARG = numeric, PROCEDURE = ip4_minus_numeric ); - -CREATE OR REPLACE FUNCTION ip6_minus_bigint(ip6,bigint) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_minus_bigint' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6_minus_int(ip6,integer) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_minus_int' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6_minus_numeric(ip6,numeric) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_minus_numeric' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR - ( LEFTARG = ip6, RIGHTARG = bigint, PROCEDURE = ip6_minus_bigint ); -CREATE OPERATOR - ( LEFTARG = ip6, RIGHTARG = integer, PROCEDURE = ip6_minus_int ); -CREATE OPERATOR - ( LEFTARG = ip6, RIGHTARG = numeric, PROCEDURE = ip6_minus_numeric ); - -CREATE OR REPLACE FUNCTION ipaddress_minus_bigint(ipaddress,bigint) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_minus_bigint' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ipaddress_minus_int(ipaddress,integer) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_minus_int' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ipaddress_minus_numeric(ipaddress,numeric) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_minus_numeric' LANGUAGE C IMMUTABLE STRICT; - -CREATE OPERATOR - ( LEFTARG = ipaddress, RIGHTARG = bigint, PROCEDURE = ipaddress_minus_bigint ); -CREATE OPERATOR - ( LEFTARG = ipaddress, RIGHTARG = integer, PROCEDURE = ipaddress_minus_int ); -CREATE OPERATOR - ( LEFTARG = ipaddress, RIGHTARG = numeric, PROCEDURE = ipaddress_minus_numeric ); - -CREATE OR REPLACE FUNCTION ip4_minus_ip4(ip4,ip4) RETURNS bigint AS 'MODULE_PATHNAME', 'ip4_minus_ip4' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6_minus_ip6(ip6,ip6) RETURNS numeric AS 'MODULE_PATHNAME', 'ip6_minus_ip6' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ipaddress_minus_ipaddress(ipaddress,ipaddress) RETURNS numeric AS 'MODULE_PATHNAME', 'ipaddr_minus_ipaddr' LANGUAGE C IMMUTABLE STRICT; - -ALTER EXTENSION ip4r ADD OPERATOR -(ip4,ip4); -CREATE OPERATOR - ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_minus_ip6 ); -CREATE OPERATOR - ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_minus_ipaddress ); - --- containment predicates: (a >>= b), (a >> b), (a <<= b), (a << b), (a && b) - -CREATE OR REPLACE FUNCTION ip4r_contained_by(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6r_contained_by(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange_contained_by(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -ALTER EXTENSION ip4r ADD OPERATOR <<=(ip4r,ip4r); -CREATE OPERATOR <<= ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_contained_by, COMMUTATOR = '>>=', RESTRICT = contsel, JOIN = contjoinsel ); -CREATE OPERATOR <<= ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_contained_by, COMMUTATOR = '>>=', RESTRICT = contsel, JOIN = contjoinsel ); - -CREATE OR REPLACE FUNCTION ip4r_contained_by_strict(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6r_contained_by_strict(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange_contained_by_strict(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -ALTER EXTENSION ip4r ADD OPERATOR <<(ip4r,ip4r); -CREATE OPERATOR << ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_contained_by_strict, COMMUTATOR = '>>', RESTRICT = contsel, JOIN = contjoinsel ); -CREATE OPERATOR << ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_contained_by_strict, COMMUTATOR = '>>', RESTRICT = contsel, JOIN = contjoinsel ); - -CREATE OR REPLACE FUNCTION ip4r_contains(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6r_contains(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange_contains(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -ALTER EXTENSION ip4r ADD OPERATOR >>=(ip4r,ip4r); -CREATE OPERATOR >>= ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_contains, COMMUTATOR = '<<=', RESTRICT = contsel, JOIN = contjoinsel ); -CREATE OPERATOR >>= ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_contains, COMMUTATOR = '<<=', RESTRICT = contsel, JOIN = contjoinsel ); - -CREATE OR REPLACE FUNCTION ip4r_contains_strict(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6r_contains_strict(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange_contains_strict(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -ALTER EXTENSION ip4r ADD OPERATOR >>(ip4r,ip4r); -CREATE OPERATOR >> ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_contains_strict, COMMUTATOR = '<<', RESTRICT = contsel, JOIN = contjoinsel ); -CREATE OPERATOR >> ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_contains_strict, COMMUTATOR = '<<', RESTRICT = contsel, JOIN = contjoinsel ); - -CREATE OR REPLACE FUNCTION ip4r_overlaps(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6r_overlaps(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange_overlaps(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -ALTER EXTENSION ip4r ADD OPERATOR &&(ip4r,ip4r); -CREATE OPERATOR && ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_overlaps, COMMUTATOR = '&&', RESTRICT = areasel, JOIN = areajoinsel ); -CREATE OPERATOR && ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_overlaps, COMMUTATOR = '&&', RESTRICT = areasel, JOIN = areajoinsel ); - --- cross-type containment --- no operators for these since they seem to do more harm than good. These cases --- are handled by implicit casts instead. - -CREATE OR REPLACE FUNCTION ip4_contained_by(ip4,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip4_contained_by(ip4,iprange) RETURNS bool AS 'MODULE_PATHNAME','iprange_ip4_contained_by' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6_contained_by(ip6,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6_contained_by(ip6,iprange) RETURNS bool AS 'MODULE_PATHNAME','iprange_ip6_contained_by' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ipaddress_contained_by(ipaddress,iprange) RETURNS bool AS 'MODULE_PATHNAME','iprange_ip_contained_by' LANGUAGE C IMMUTABLE STRICT; - -CREATE OR REPLACE FUNCTION ip4_contains(ip4r,ip4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6_contains(ip6r,ip6) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip4_contains(iprange,ip4) RETURNS bool AS 'MODULE_PATHNAME','iprange_contains_ip4' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6_contains(iprange,ip6) RETURNS bool AS 'MODULE_PATHNAME','iprange_contains_ip6' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ipaddress_contains(iprange,ipaddress) RETURNS bool AS 'MODULE_PATHNAME','iprange_contains_ip' LANGUAGE C IMMUTABLE STRICT; - --- btree (strict weak) ordering operators --- meaning of < > for ip4 and ip6 is obvious. --- for ipaddress, all ip4 addresses are less than all ip6 addresses --- for ip4r/ip6r, the order is lexicographic on (lower,upper) --- for iprange, the universal range is lowest, then all ip4 ranges, then ip6 - -CREATE OR REPLACE FUNCTION ip4_eq(ip4,ip4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip4r_eq(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6_eq(ip6,ip6) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6r_eq(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ipaddress_eq(ipaddress,ipaddress) RETURNS bool AS 'MODULE_PATHNAME','ipaddr_eq' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange_eq(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -ALTER EXTENSION ip4r ADD OPERATOR =(ip4,ip4); -ALTER EXTENSION ip4r ADD OPERATOR =(ip4r,ip4r); -CREATE OPERATOR = ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_eq, COMMUTATOR = '=', NEGATOR = '<>', RESTRICT = eqsel, JOIN = eqjoinsel, SORT1 = '<', SORT2 = '<', HASHES ); -CREATE OPERATOR = ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_eq, COMMUTATOR = '=', NEGATOR = '<>', RESTRICT = eqsel, JOIN = eqjoinsel, SORT1 = '<', SORT2 = '<', HASHES ); -CREATE OPERATOR = ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_eq, COMMUTATOR = '=', NEGATOR = '<>', RESTRICT = eqsel, JOIN = eqjoinsel, SORT1 = '<', SORT2 = '<', HASHES ); -CREATE OPERATOR = ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_eq, COMMUTATOR = '=', NEGATOR = '<>', RESTRICT = eqsel, JOIN = eqjoinsel, SORT1 = '<', SORT2 = '<', HASHES ); - -CREATE OR REPLACE FUNCTION ip4_ge(ip4,ip4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip4r_ge(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6_ge(ip6,ip6) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6r_ge(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ipaddress_ge(ipaddress,ipaddress) RETURNS bool AS 'MODULE_PATHNAME','ipaddr_ge' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange_ge(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -ALTER EXTENSION ip4r ADD OPERATOR >=(ip4,ip4); -ALTER EXTENSION ip4r ADD OPERATOR >=(ip4r,ip4r); -CREATE OPERATOR >= ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_ge, COMMUTATOR = '<=', NEGATOR = '<', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); -CREATE OPERATOR >= ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_ge, COMMUTATOR = '<=', NEGATOR = '<', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); -CREATE OPERATOR >= ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_ge, COMMUTATOR = '<=', NEGATOR = '<', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); -CREATE OPERATOR >= ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_ge, COMMUTATOR = '<=', NEGATOR = '<', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); - -CREATE OR REPLACE FUNCTION ip4_gt(ip4,ip4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip4r_gt(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6_gt(ip6,ip6) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6r_gt(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ipaddress_gt(ipaddress,ipaddress) RETURNS bool AS 'MODULE_PATHNAME','ipaddr_gt' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange_gt(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -ALTER EXTENSION ip4r ADD OPERATOR >(ip4,ip4); -ALTER EXTENSION ip4r ADD OPERATOR >(ip4r,ip4r); -CREATE OPERATOR > ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_gt, COMMUTATOR = '<', NEGATOR = '<=', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); -CREATE OPERATOR > ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_gt, COMMUTATOR = '<', NEGATOR = '<=', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); -CREATE OPERATOR > ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_gt, COMMUTATOR = '<', NEGATOR = '<=', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); -CREATE OPERATOR > ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_gt, COMMUTATOR = '<', NEGATOR = '<=', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); - -CREATE OR REPLACE FUNCTION ip4_le(ip4,ip4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip4r_le(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6_le(ip6,ip6) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6r_le(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ipaddress_le(ipaddress,ipaddress) RETURNS bool AS 'MODULE_PATHNAME','ipaddr_le' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange_le(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -ALTER EXTENSION ip4r ADD OPERATOR <=(ip4,ip4); -ALTER EXTENSION ip4r ADD OPERATOR <=(ip4r,ip4r); -CREATE OPERATOR <= ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_le, COMMUTATOR = '>=', NEGATOR = '>', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); -CREATE OPERATOR <= ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_le, COMMUTATOR = '>=', NEGATOR = '>', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); -CREATE OPERATOR <= ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_le, COMMUTATOR = '>=', NEGATOR = '>', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); -CREATE OPERATOR <= ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_le, COMMUTATOR = '>=', NEGATOR = '>', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); - -CREATE OR REPLACE FUNCTION ip4_lt(ip4,ip4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip4r_lt(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6_lt(ip6,ip6) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6r_lt(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ipaddress_lt(ipaddress,ipaddress) RETURNS bool AS 'MODULE_PATHNAME','ipaddr_lt' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange_lt(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -ALTER EXTENSION ip4r ADD OPERATOR <(ip4,ip4); -ALTER EXTENSION ip4r ADD OPERATOR <(ip4r,ip4r); -CREATE OPERATOR < ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_lt, COMMUTATOR = '>', NEGATOR = '>=', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); -CREATE OPERATOR < ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_lt, COMMUTATOR = '>', NEGATOR = '>=', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); -CREATE OPERATOR < ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_lt, COMMUTATOR = '>', NEGATOR = '>=', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); -CREATE OPERATOR < ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_lt, COMMUTATOR = '>', NEGATOR = '>=', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); - -CREATE OR REPLACE FUNCTION ip4_neq(ip4,ip4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip4r_neq(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6_neq(ip6,ip6) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6r_neq(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ipaddress_neq(ipaddress,ipaddress) RETURNS bool AS 'MODULE_PATHNAME','ipaddr_neq' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange_neq(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -ALTER EXTENSION ip4r ADD OPERATOR <>(ip4,ip4); -ALTER EXTENSION ip4r ADD OPERATOR <>(ip4r,ip4r); -CREATE OPERATOR <> ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_neq, COMMUTATOR = '<>', NEGATOR = '=', RESTRICT = neqsel, JOIN = neqjoinsel ); -CREATE OPERATOR <> ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_neq, COMMUTATOR = '<>', NEGATOR = '=', RESTRICT = neqsel, JOIN = neqjoinsel ); -CREATE OPERATOR <> ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_neq, COMMUTATOR = '<>', NEGATOR = '=', RESTRICT = neqsel, JOIN = neqjoinsel ); -CREATE OPERATOR <> ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_neq, COMMUTATOR = '<>', NEGATOR = '=', RESTRICT = neqsel, JOIN = neqjoinsel ); - --- ---------------------------------------------------------------------- --- Btree index - -CREATE OR REPLACE FUNCTION ip4_cmp(ip4,ip4) RETURNS integer AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip4r_cmp(ip4r,ip4r) RETURNS integer AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6_cmp(ip6,ip6) RETURNS integer AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6r_cmp(ip6r,ip6r) RETURNS integer AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ipaddress_cmp(ipaddress,ipaddress) RETURNS integer AS 'MODULE_PATHNAME','ipaddr_cmp' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprange_cmp(iprange,iprange) RETURNS integer AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; - -ALTER EXTENSION ip4r ADD OPERATOR CLASS btree_ip4_ops USING btree; -ALTER EXTENSION ip4r ADD OPERATOR CLASS btree_ip4r_ops USING btree; - -CREATE OPERATOR CLASS btree_ip6_ops DEFAULT FOR TYPE ip6 USING btree AS - OPERATOR 1 < , - OPERATOR 2 <= , - OPERATOR 3 = , - OPERATOR 4 >= , - OPERATOR 5 > , - FUNCTION 1 ip6_cmp(ip6, ip6); - -CREATE OPERATOR CLASS btree_ip6r_ops DEFAULT FOR TYPE ip6r USING btree AS - OPERATOR 1 < , - OPERATOR 2 <= , - OPERATOR 3 = , - OPERATOR 4 >= , - OPERATOR 5 > , - FUNCTION 1 ip6r_cmp(ip6r, ip6r); - -CREATE OPERATOR CLASS btree_ipaddress_ops DEFAULT FOR TYPE ipaddress USING btree AS - OPERATOR 1 < , - OPERATOR 2 <= , - OPERATOR 3 = , - OPERATOR 4 >= , - OPERATOR 5 > , - FUNCTION 1 ipaddress_cmp(ipaddress, ipaddress); - -CREATE OPERATOR CLASS btree_iprange_ops DEFAULT FOR TYPE iprange USING btree AS - OPERATOR 1 < , - OPERATOR 2 <= , - OPERATOR 3 = , - OPERATOR 4 >= , - OPERATOR 5 > , - FUNCTION 1 iprange_cmp(iprange, iprange); - --- ---------------------------------------------------------------------- --- Hash index - --- the hash index definitions are needed for hashagg, hashjoin, hash-distinct, hashsetop --- etc. even if no actual hash indexes are used. - -CREATE OR REPLACE FUNCTION ip4hash(ip4) RETURNS integer AS 'MODULE_PATHNAME', 'ip4hash' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6hash(ip6) RETURNS integer AS 'MODULE_PATHNAME', 'ip6hash' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ipaddresshash(ipaddress) RETURNS integer AS 'MODULE_PATHNAME', 'ipaddr_hash' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip4rhash(ip4r) RETURNS integer AS 'MODULE_PATHNAME', 'ip4rhash' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION ip6rhash(ip6r) RETURNS integer AS 'MODULE_PATHNAME', 'ip6rhash' LANGUAGE C IMMUTABLE STRICT; -CREATE OR REPLACE FUNCTION iprangehash(iprange) RETURNS integer AS 'MODULE_PATHNAME', 'iprange_hash' LANGUAGE C IMMUTABLE STRICT; - -ALTER EXTENSION ip4r ADD OPERATOR CLASS hash_ip4_ops USING hash; -ALTER EXTENSION ip4r ADD OPERATOR CLASS hash_ip4r_ops USING hash; - -CREATE OPERATOR CLASS hash_ip6_ops DEFAULT FOR TYPE ip6 USING hash AS - OPERATOR 1 = , - FUNCTION 1 ip6hash(ip6); - -CREATE OPERATOR CLASS hash_ip6r_ops DEFAULT FOR TYPE ip6r USING hash AS - OPERATOR 1 = , - FUNCTION 1 ip6rhash(ip6r); - -CREATE OPERATOR CLASS hash_ipaddress_ops DEFAULT FOR TYPE ipaddress USING hash AS - OPERATOR 1 = , - FUNCTION 1 ipaddresshash(ipaddress); - -CREATE OPERATOR CLASS hash_iprange_ops DEFAULT FOR TYPE iprange USING hash AS - OPERATOR 1 = , - FUNCTION 1 iprangehash(iprange); - --- ---------------------------------------------------------------------- --- GiST - --- these type declarations are actually wrong for 8.4+ (which added --- more args to consistent) but we ignore that because the access --- method code doesn't actually look at the function declaration, and --- the differences are handled in the C code. Having the SQL --- definition changing is just too much of a pain. - -CREATE OR REPLACE FUNCTION gip4r_consistent(internal,ip4r,int4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE OR REPLACE FUNCTION gip4r_compress(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE OR REPLACE FUNCTION gip4r_decompress(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE OR REPLACE FUNCTION gip4r_penalty(internal,internal,internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C STRICT; -CREATE OR REPLACE FUNCTION gip4r_picksplit(internal, internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE OR REPLACE FUNCTION gip4r_union(internal, internal) RETURNS ip4r AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE OR REPLACE FUNCTION gip4r_same(ip4r, ip4r, internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; - -CREATE OR REPLACE FUNCTION gip6r_consistent(internal,ip6r,int4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE OR REPLACE FUNCTION gip6r_compress(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE OR REPLACE FUNCTION gip6r_decompress(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE OR REPLACE FUNCTION gip6r_penalty(internal,internal,internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C STRICT; -CREATE OR REPLACE FUNCTION gip6r_picksplit(internal, internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE OR REPLACE FUNCTION gip6r_union(internal, internal) RETURNS ip6r AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE OR REPLACE FUNCTION gip6r_same(ip6r, ip6r, internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; - -CREATE OR REPLACE FUNCTION gipr_consistent(internal,iprange,int4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE OR REPLACE FUNCTION gipr_compress(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE OR REPLACE FUNCTION gipr_decompress(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE OR REPLACE FUNCTION gipr_penalty(internal,internal,internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C STRICT; -CREATE OR REPLACE FUNCTION gipr_picksplit(internal, internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE OR REPLACE FUNCTION gipr_union(internal, internal) RETURNS iprange AS 'MODULE_PATHNAME' LANGUAGE C; -CREATE OR REPLACE FUNCTION gipr_same(iprange, iprange, internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; - -ALTER EXTENSION ip4r ADD OPERATOR CLASS gist_ip4r_ops USING gist; - -CREATE OPERATOR CLASS gist_ip6r_ops DEFAULT FOR TYPE ip6r USING gist AS - OPERATOR 1 >>= , - OPERATOR 2 <<= , - OPERATOR 3 >> , - OPERATOR 4 << , - OPERATOR 5 && , - OPERATOR 6 = , - FUNCTION 1 gip6r_consistent (internal, ip6r, int4), - FUNCTION 2 gip6r_union (internal, internal), - FUNCTION 3 gip6r_compress (internal), - FUNCTION 4 gip6r_decompress (internal), - FUNCTION 5 gip6r_penalty (internal, internal, internal), - FUNCTION 6 gip6r_picksplit (internal, internal), - FUNCTION 7 gip6r_same (ip6r, ip6r, internal); - -CREATE OPERATOR CLASS gist_iprange_ops DEFAULT FOR TYPE iprange USING gist AS - OPERATOR 1 >>= , - OPERATOR 2 <<= , - OPERATOR 3 >> , - OPERATOR 4 << , - OPERATOR 5 && , - OPERATOR 6 = , - FUNCTION 1 gipr_consistent (internal, iprange, int4), - FUNCTION 2 gipr_union (internal, internal), - FUNCTION 3 gipr_compress (internal), - FUNCTION 4 gipr_decompress (internal), - FUNCTION 5 gipr_penalty (internal, internal, internal), - FUNCTION 6 gipr_picksplit (internal, internal), - FUNCTION 7 gipr_same (iprange, iprange, internal); - --- cleanup old cruft - -DROP OPERATOR IF EXISTS @(ip4r,ip4r); -DROP OPERATOR IF EXISTS ~(ip4r,ip4r); - -DROP OPERATOR IF EXISTS &<<(ip4r,ip4r); -DROP OPERATOR IF EXISTS &>>(ip4r,ip4r); -DROP OPERATOR IF EXISTS <<<(ip4r,ip4r); -DROP OPERATOR IF EXISTS >>>(ip4r,ip4r); - -DROP FUNCTION IF EXISTS ip4r_left_of(ip4r,ip4r); -DROP FUNCTION IF EXISTS ip4r_left_overlap(ip4r,ip4r); -DROP FUNCTION IF EXISTS ip4r_right_of(ip4r,ip4r); -DROP FUNCTION IF EXISTS ip4r_right_overlap(ip4r,ip4r); - --- end diff -Nru ip4r-2.3/ip4r--unpackaged2.0--2.0.sql ip4r-2.4/ip4r--unpackaged2.0--2.0.sql --- ip4r-2.3/ip4r--unpackaged2.0--2.0.sql 2018-05-24 21:30:28.000000000 +0000 +++ ip4r-2.4/ip4r--unpackaged2.0--2.0.sql 1970-01-01 00:00:00.000000000 +0000 @@ -1,420 +0,0 @@ --- ip4r extension - --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "CREATE EXTENSION ip4r" to load this file. \quit - -ALTER EXTENSION ip4r ADD FUNCTION ip4_in(cstring); -ALTER EXTENSION ip4r ADD FUNCTION ip4_out(ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip4_recv(internal); -ALTER EXTENSION ip4r ADD FUNCTION ip4_send(ip4); -ALTER EXTENSION ip4r ADD TYPE ip4; -ALTER EXTENSION ip4r ADD FUNCTION ip4r_in(cstring); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_out(ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_recv(internal); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_send(ip4r); -ALTER EXTENSION ip4r ADD TYPE ip4r; -ALTER EXTENSION ip4r ADD FUNCTION ip6_in(cstring); -ALTER EXTENSION ip4r ADD FUNCTION ip6_out(ip6); -ALTER EXTENSION ip4r ADD FUNCTION ip6_recv(internal); -ALTER EXTENSION ip4r ADD FUNCTION ip6_send(ip6); -ALTER EXTENSION ip4r ADD TYPE ip6; -ALTER EXTENSION ip4r ADD FUNCTION ip6r_in(cstring); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_out(ip6r); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_recv(internal); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_send(ip6r); -ALTER EXTENSION ip4r ADD TYPE ip6r; -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_in(cstring); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_out(ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_recv(internal); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_send(ipaddress); -ALTER EXTENSION ip4r ADD TYPE ipaddress; -ALTER EXTENSION ip4r ADD FUNCTION iprange_in(cstring); -ALTER EXTENSION ip4r ADD FUNCTION iprange_out(iprange); -ALTER EXTENSION ip4r ADD FUNCTION iprange_recv(internal); -ALTER EXTENSION ip4r ADD FUNCTION iprange_send(iprange); -ALTER EXTENSION ip4r ADD TYPE iprange; -ALTER EXTENSION ip4r ADD FUNCTION ip4(bigint); -ALTER EXTENSION ip4r ADD FUNCTION ip4(double precision); -ALTER EXTENSION ip4r ADD FUNCTION ip4(numeric); -ALTER EXTENSION ip4r ADD FUNCTION ip4(inet); -ALTER EXTENSION ip4r ADD FUNCTION ip4(text); -ALTER EXTENSION ip4r ADD FUNCTION ip4(ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION ip6(numeric); -ALTER EXTENSION ip4r ADD FUNCTION ip6(inet); -ALTER EXTENSION ip4r ADD FUNCTION ip6(text); -ALTER EXTENSION ip4r ADD FUNCTION ip6(ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress(inet); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress(ip4); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress(ip6); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress(text); -ALTER EXTENSION ip4r ADD FUNCTION ip4r(cidr); -ALTER EXTENSION ip4r ADD FUNCTION ip4r(ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip4r(text); -ALTER EXTENSION ip4r ADD FUNCTION ip4r(iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip6r(cidr); -ALTER EXTENSION ip4r ADD FUNCTION ip6r(ip6); -ALTER EXTENSION ip4r ADD FUNCTION ip6r(text); -ALTER EXTENSION ip4r ADD FUNCTION ip6r(iprange); -ALTER EXTENSION ip4r ADD FUNCTION iprange(cidr); -ALTER EXTENSION ip4r ADD FUNCTION iprange(ip4); -ALTER EXTENSION ip4r ADD FUNCTION iprange(ip6); -ALTER EXTENSION ip4r ADD FUNCTION iprange(ip4r); -ALTER EXTENSION ip4r ADD FUNCTION iprange(ip6r); -ALTER EXTENSION ip4r ADD FUNCTION iprange(ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION iprange(text); -ALTER EXTENSION ip4r ADD FUNCTION cidr(ip4); -ALTER EXTENSION ip4r ADD FUNCTION cidr(ip4r); -ALTER EXTENSION ip4r ADD FUNCTION cidr(ip6); -ALTER EXTENSION ip4r ADD FUNCTION cidr(ip6r); -ALTER EXTENSION ip4r ADD FUNCTION cidr(ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION cidr(iprange); -ALTER EXTENSION ip4r ADD FUNCTION text(ip4); -ALTER EXTENSION ip4r ADD FUNCTION text(ip4r); -ALTER EXTENSION ip4r ADD FUNCTION text(ip6); -ALTER EXTENSION ip4r ADD FUNCTION text(ip6r); -ALTER EXTENSION ip4r ADD FUNCTION text(ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION text(iprange); -ALTER EXTENSION ip4r ADD FUNCTION to_bigint(ip4); -ALTER EXTENSION ip4r ADD FUNCTION to_double(ip4); -ALTER EXTENSION ip4r ADD FUNCTION to_numeric(ip4); -ALTER EXTENSION ip4r ADD FUNCTION to_numeric(ip6); -ALTER EXTENSION ip4r ADD FUNCTION to_numeric(ipaddress); -ALTER EXTENSION ip4r ADD CAST (ip4 as bigint); -ALTER EXTENSION ip4r ADD CAST (ip4 as double precision); -ALTER EXTENSION ip4r ADD CAST (ip4 as numeric); -ALTER EXTENSION ip4r ADD CAST (ip4 as text); -ALTER EXTENSION ip4r ADD CAST (ip4 as cidr); -ALTER EXTENSION ip4r ADD CAST (ip4r as cidr); -ALTER EXTENSION ip4r ADD CAST (ip4r as text); -ALTER EXTENSION ip4r ADD CAST (ip6 as numeric); -ALTER EXTENSION ip4r ADD CAST (ip6 as text); -ALTER EXTENSION ip4r ADD CAST (ip6 as cidr); -ALTER EXTENSION ip4r ADD CAST (ip6r as cidr); -ALTER EXTENSION ip4r ADD CAST (ip6r as text); -ALTER EXTENSION ip4r ADD CAST (ipaddress as numeric); -ALTER EXTENSION ip4r ADD CAST (ipaddress as text); -ALTER EXTENSION ip4r ADD CAST (ipaddress as cidr); -ALTER EXTENSION ip4r ADD CAST (iprange as cidr); -ALTER EXTENSION ip4r ADD CAST (iprange as text); -ALTER EXTENSION ip4r ADD CAST (text as ip4); -ALTER EXTENSION ip4r ADD CAST (text as ip4r); -ALTER EXTENSION ip4r ADD CAST (text as ip6); -ALTER EXTENSION ip4r ADD CAST (text as ip6r); -ALTER EXTENSION ip4r ADD CAST (text as ipaddress); -ALTER EXTENSION ip4r ADD CAST (text as iprange); -ALTER EXTENSION ip4r ADD CAST (bigint as ip4); -ALTER EXTENSION ip4r ADD CAST (double precision as ip4); -ALTER EXTENSION ip4r ADD CAST (numeric as ip4); -ALTER EXTENSION ip4r ADD CAST (numeric as ip6); -ALTER EXTENSION ip4r ADD CAST (cidr as ip4r); -ALTER EXTENSION ip4r ADD CAST (cidr as ip6r); -ALTER EXTENSION ip4r ADD CAST (cidr as iprange); -ALTER EXTENSION ip4r ADD CAST (inet as ip4); -ALTER EXTENSION ip4r ADD CAST (inet as ip6); -ALTER EXTENSION ip4r ADD CAST (inet as ipaddress); -ALTER EXTENSION ip4r ADD CAST (ip4 as ip4r); -ALTER EXTENSION ip4r ADD CAST (ip4 as ipaddress); -ALTER EXTENSION ip4r ADD CAST (ip4 as iprange); -ALTER EXTENSION ip4r ADD CAST (ip4r as iprange); -ALTER EXTENSION ip4r ADD CAST (ip6 as ip6r); -ALTER EXTENSION ip4r ADD CAST (ip6 as ipaddress); -ALTER EXTENSION ip4r ADD CAST (ip6 as iprange); -ALTER EXTENSION ip4r ADD CAST (ip6r as iprange); -ALTER EXTENSION ip4r ADD CAST (ipaddress as iprange); -ALTER EXTENSION ip4r ADD CAST (ipaddress as ip4); -ALTER EXTENSION ip4r ADD CAST (ipaddress as ip6); -ALTER EXTENSION ip4r ADD CAST (iprange as ip4r); -ALTER EXTENSION ip4r ADD CAST (iprange as ip6r); -ALTER EXTENSION ip4r ADD FUNCTION ip4r(ip4,ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip6r(ip6,ip6); -ALTER EXTENSION ip4r ADD FUNCTION iprange(ip4,ip4); -ALTER EXTENSION ip4r ADD FUNCTION iprange(ip6,ip6); -ALTER EXTENSION ip4r ADD FUNCTION iprange(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION family(ip4); -ALTER EXTENSION ip4r ADD FUNCTION family(ip4r); -ALTER EXTENSION ip4r ADD FUNCTION family(ip6); -ALTER EXTENSION ip4r ADD FUNCTION family(ip6r); -ALTER EXTENSION ip4r ADD FUNCTION family(ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION family(iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4_netmask(integer); -ALTER EXTENSION ip4r ADD FUNCTION ip6_netmask(integer); -ALTER EXTENSION ip4r ADD FUNCTION is_cidr(ip4r); -ALTER EXTENSION ip4r ADD FUNCTION is_cidr(ip6r); -ALTER EXTENSION ip4r ADD FUNCTION is_cidr(iprange); -ALTER EXTENSION ip4r ADD FUNCTION masklen(ip4r); -ALTER EXTENSION ip4r ADD FUNCTION masklen(ip6r); -ALTER EXTENSION ip4r ADD FUNCTION masklen(iprange); -ALTER EXTENSION ip4r ADD FUNCTION lower(ip4r); -ALTER EXTENSION ip4r ADD FUNCTION lower(ip6r); -ALTER EXTENSION ip4r ADD FUNCTION lower(iprange); -ALTER EXTENSION ip4r ADD FUNCTION upper(ip4r); -ALTER EXTENSION ip4r ADD FUNCTION upper(ip6r); -ALTER EXTENSION ip4r ADD FUNCTION upper(iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4_net_lower(ip4,integer); -ALTER EXTENSION ip4r ADD FUNCTION ip6_net_lower(ip6,integer); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_net_lower(ipaddress,integer); -ALTER EXTENSION ip4r ADD FUNCTION ip4_net_upper(ip4,integer); -ALTER EXTENSION ip4r ADD FUNCTION ip6_net_upper(ip6,integer); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_net_upper(ipaddress,integer); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_union(ip4r, ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_union(ip6r, ip6r); -ALTER EXTENSION ip4r ADD FUNCTION iprange_union(iprange, iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_inter(ip4r,ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_inter(ip6r,ip6r); -ALTER EXTENSION ip4r ADD FUNCTION iprange_inter(iprange,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_net_mask(ip4,ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_net_mask(ip6,ip6); -ALTER EXTENSION ip4r ADD FUNCTION iprange_net_mask(ip4,ip4); -ALTER EXTENSION ip4r ADD FUNCTION iprange_net_mask(ip6,ip6); -ALTER EXTENSION ip4r ADD FUNCTION iprange_net_mask(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_net_prefix(ip4,integer); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_net_prefix(ip6,integer); -ALTER EXTENSION ip4r ADD FUNCTION iprange_net_prefix(ip4,integer); -ALTER EXTENSION ip4r ADD FUNCTION iprange_net_prefix(ip6,integer); -ALTER EXTENSION ip4r ADD FUNCTION iprange_net_prefix(ipaddress,integer); -ALTER EXTENSION ip4r ADD OPERATOR /(ip4,ip4); -ALTER EXTENSION ip4r ADD OPERATOR /(ip6,ip6); -ALTER EXTENSION ip4r ADD OPERATOR /(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD OPERATOR /(ip4,integer); -ALTER EXTENSION ip4r ADD OPERATOR /(ip6,integer); -ALTER EXTENSION ip4r ADD OPERATOR /(ipaddress,integer); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_size(ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_size(ip6r); -ALTER EXTENSION ip4r ADD FUNCTION iprange_size(iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_size_exact(ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_size_exact(ip6r); -ALTER EXTENSION ip4r ADD FUNCTION iprange_size_exact(iprange); -ALTER EXTENSION ip4r ADD OPERATOR @(NONE,ip4r); -ALTER EXTENSION ip4r ADD OPERATOR @(NONE,ip6r); -ALTER EXTENSION ip4r ADD OPERATOR @(NONE,iprange); -ALTER EXTENSION ip4r ADD OPERATOR @@(NONE,ip4r); -ALTER EXTENSION ip4r ADD OPERATOR @@(NONE,ip6r); -ALTER EXTENSION ip4r ADD OPERATOR @@(NONE,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4_and(ip4,ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip6_and(ip6,ip6); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_and(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD OPERATOR &(ip4,ip4); -ALTER EXTENSION ip4r ADD OPERATOR &(ip6,ip6); -ALTER EXTENSION ip4r ADD OPERATOR &(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION ip4_or(ip4,ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip6_or(ip6,ip6); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_or(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD OPERATOR |(ip4,ip4); -ALTER EXTENSION ip4r ADD OPERATOR |(ip6,ip6); -ALTER EXTENSION ip4r ADD OPERATOR |(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION ip4_not(ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip6_not(ip6); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_not(ipaddress); -ALTER EXTENSION ip4r ADD OPERATOR ~(NONE,ip4); -ALTER EXTENSION ip4r ADD OPERATOR ~(NONE,ip6); -ALTER EXTENSION ip4r ADD OPERATOR ~(NONE,ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION ip4_xor(ip4,ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip6_xor(ip6,ip6); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_xor(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD OPERATOR #(ip4,ip4); -ALTER EXTENSION ip4r ADD OPERATOR #(ip6,ip6); -ALTER EXTENSION ip4r ADD OPERATOR #(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION ip4_plus_bigint(ip4,bigint); -ALTER EXTENSION ip4r ADD FUNCTION ip4_plus_int(ip4,integer); -ALTER EXTENSION ip4r ADD FUNCTION ip4_plus_numeric(ip4,numeric); -ALTER EXTENSION ip4r ADD OPERATOR +(ip4,bigint); -ALTER EXTENSION ip4r ADD OPERATOR +(ip4,integer); -ALTER EXTENSION ip4r ADD OPERATOR +(ip4,numeric); -ALTER EXTENSION ip4r ADD FUNCTION ip6_plus_bigint(ip6,bigint); -ALTER EXTENSION ip4r ADD FUNCTION ip6_plus_int(ip6,integer); -ALTER EXTENSION ip4r ADD FUNCTION ip6_plus_numeric(ip6,numeric); -ALTER EXTENSION ip4r ADD OPERATOR +(ip6,bigint); -ALTER EXTENSION ip4r ADD OPERATOR +(ip6,integer); -ALTER EXTENSION ip4r ADD OPERATOR +(ip6,numeric); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_plus_bigint(ipaddress,bigint); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_plus_int(ipaddress,integer); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_plus_numeric(ipaddress,numeric); -ALTER EXTENSION ip4r ADD OPERATOR +(ipaddress,bigint); -ALTER EXTENSION ip4r ADD OPERATOR +(ipaddress,integer); -ALTER EXTENSION ip4r ADD OPERATOR +(ipaddress,numeric); -ALTER EXTENSION ip4r ADD FUNCTION ip4_minus_bigint(ip4,bigint); -ALTER EXTENSION ip4r ADD FUNCTION ip4_minus_int(ip4,integer); -ALTER EXTENSION ip4r ADD FUNCTION ip4_minus_numeric(ip4,numeric); -ALTER EXTENSION ip4r ADD OPERATOR -(ip4,bigint); -ALTER EXTENSION ip4r ADD OPERATOR -(ip4,integer); -ALTER EXTENSION ip4r ADD OPERATOR -(ip4,numeric); -ALTER EXTENSION ip4r ADD FUNCTION ip6_minus_bigint(ip6,bigint); -ALTER EXTENSION ip4r ADD FUNCTION ip6_minus_int(ip6,integer); -ALTER EXTENSION ip4r ADD FUNCTION ip6_minus_numeric(ip6,numeric); -ALTER EXTENSION ip4r ADD OPERATOR -(ip6,bigint); -ALTER EXTENSION ip4r ADD OPERATOR -(ip6,integer); -ALTER EXTENSION ip4r ADD OPERATOR -(ip6,numeric); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_minus_bigint(ipaddress,bigint); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_minus_int(ipaddress,integer); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_minus_numeric(ipaddress,numeric); -ALTER EXTENSION ip4r ADD OPERATOR -(ipaddress,bigint); -ALTER EXTENSION ip4r ADD OPERATOR -(ipaddress,integer); -ALTER EXTENSION ip4r ADD OPERATOR -(ipaddress,numeric); -ALTER EXTENSION ip4r ADD FUNCTION ip4_minus_ip4(ip4,ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip6_minus_ip6(ip6,ip6); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_minus_ipaddress(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD OPERATOR -(ip4,ip4); -ALTER EXTENSION ip4r ADD OPERATOR -(ip6,ip6); -ALTER EXTENSION ip4r ADD OPERATOR -(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_contained_by(ip4r,ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_contained_by(ip6r,ip6r); -ALTER EXTENSION ip4r ADD FUNCTION iprange_contained_by(iprange,iprange); -ALTER EXTENSION ip4r ADD OPERATOR <<=(ip4r,ip4r); -ALTER EXTENSION ip4r ADD OPERATOR <<=(ip6r,ip6r); -ALTER EXTENSION ip4r ADD OPERATOR <<=(iprange,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_contained_by_strict(ip4r,ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_contained_by_strict(ip6r,ip6r); -ALTER EXTENSION ip4r ADD FUNCTION iprange_contained_by_strict(iprange,iprange); -ALTER EXTENSION ip4r ADD OPERATOR <<(ip4r,ip4r); -ALTER EXTENSION ip4r ADD OPERATOR <<(ip6r,ip6r); -ALTER EXTENSION ip4r ADD OPERATOR <<(iprange,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_contains(ip4r,ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_contains(ip6r,ip6r); -ALTER EXTENSION ip4r ADD FUNCTION iprange_contains(iprange,iprange); -ALTER EXTENSION ip4r ADD OPERATOR >>=(ip4r,ip4r); -ALTER EXTENSION ip4r ADD OPERATOR >>=(ip6r,ip6r); -ALTER EXTENSION ip4r ADD OPERATOR >>=(iprange,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_contains_strict(ip4r,ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_contains_strict(ip6r,ip6r); -ALTER EXTENSION ip4r ADD FUNCTION iprange_contains_strict(iprange,iprange); -ALTER EXTENSION ip4r ADD OPERATOR >>(ip4r,ip4r); -ALTER EXTENSION ip4r ADD OPERATOR >>(ip6r,ip6r); -ALTER EXTENSION ip4r ADD OPERATOR >>(iprange,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_overlaps(ip4r,ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_overlaps(ip6r,ip6r); -ALTER EXTENSION ip4r ADD FUNCTION iprange_overlaps(iprange,iprange); -ALTER EXTENSION ip4r ADD OPERATOR &&(ip4r,ip4r); -ALTER EXTENSION ip4r ADD OPERATOR &&(ip6r,ip6r); -ALTER EXTENSION ip4r ADD OPERATOR &&(iprange,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4_contained_by(ip4,ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip4_contained_by(ip4,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip6_contained_by(ip6,ip6r); -ALTER EXTENSION ip4r ADD FUNCTION ip6_contained_by(ip6,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_contained_by(ipaddress,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4_contains(ip4r,ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip6_contains(ip6r,ip6); -ALTER EXTENSION ip4r ADD FUNCTION ip4_contains(iprange,ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip6_contains(iprange,ip6); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_contains(iprange,ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION ip4_eq(ip4,ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_eq(ip4r,ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6_eq(ip6,ip6); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_eq(ip6r,ip6r); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_eq(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION iprange_eq(iprange,iprange); -ALTER EXTENSION ip4r ADD OPERATOR =(ip4,ip4); -ALTER EXTENSION ip4r ADD OPERATOR =(ip4r,ip4r); -ALTER EXTENSION ip4r ADD OPERATOR =(ip6,ip6); -ALTER EXTENSION ip4r ADD OPERATOR =(ip6r,ip6r); -ALTER EXTENSION ip4r ADD OPERATOR =(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD OPERATOR =(iprange,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4_ge(ip4,ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_ge(ip4r,ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6_ge(ip6,ip6); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_ge(ip6r,ip6r); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_ge(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION iprange_ge(iprange,iprange); -ALTER EXTENSION ip4r ADD OPERATOR >=(ip4,ip4); -ALTER EXTENSION ip4r ADD OPERATOR >=(ip4r,ip4r); -ALTER EXTENSION ip4r ADD OPERATOR >=(ip6,ip6); -ALTER EXTENSION ip4r ADD OPERATOR >=(ip6r,ip6r); -ALTER EXTENSION ip4r ADD OPERATOR >=(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD OPERATOR >=(iprange,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4_gt(ip4,ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_gt(ip4r,ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6_gt(ip6,ip6); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_gt(ip6r,ip6r); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_gt(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION iprange_gt(iprange,iprange); -ALTER EXTENSION ip4r ADD OPERATOR >(ip4,ip4); -ALTER EXTENSION ip4r ADD OPERATOR >(ip4r,ip4r); -ALTER EXTENSION ip4r ADD OPERATOR >(ip6,ip6); -ALTER EXTENSION ip4r ADD OPERATOR >(ip6r,ip6r); -ALTER EXTENSION ip4r ADD OPERATOR >(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD OPERATOR >(iprange,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4_le(ip4,ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_le(ip4r,ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6_le(ip6,ip6); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_le(ip6r,ip6r); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_le(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION iprange_le(iprange,iprange); -ALTER EXTENSION ip4r ADD OPERATOR <=(ip4,ip4); -ALTER EXTENSION ip4r ADD OPERATOR <=(ip4r,ip4r); -ALTER EXTENSION ip4r ADD OPERATOR <=(ip6,ip6); -ALTER EXTENSION ip4r ADD OPERATOR <=(ip6r,ip6r); -ALTER EXTENSION ip4r ADD OPERATOR <=(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD OPERATOR <=(iprange,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4_lt(ip4,ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_lt(ip4r,ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6_lt(ip6,ip6); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_lt(ip6r,ip6r); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_lt(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION iprange_lt(iprange,iprange); -ALTER EXTENSION ip4r ADD OPERATOR <(ip4,ip4); -ALTER EXTENSION ip4r ADD OPERATOR <(ip4r,ip4r); -ALTER EXTENSION ip4r ADD OPERATOR <(ip6,ip6); -ALTER EXTENSION ip4r ADD OPERATOR <(ip6r,ip6r); -ALTER EXTENSION ip4r ADD OPERATOR <(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD OPERATOR <(iprange,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4_neq(ip4,ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_neq(ip4r,ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6_neq(ip6,ip6); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_neq(ip6r,ip6r); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_neq(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION iprange_neq(iprange,iprange); -ALTER EXTENSION ip4r ADD OPERATOR <>(ip4,ip4); -ALTER EXTENSION ip4r ADD OPERATOR <>(ip4r,ip4r); -ALTER EXTENSION ip4r ADD OPERATOR <>(ip6,ip6); -ALTER EXTENSION ip4r ADD OPERATOR <>(ip6r,ip6r); -ALTER EXTENSION ip4r ADD OPERATOR <>(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD OPERATOR <>(iprange,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4_cmp(ip4,ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_cmp(ip4r,ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6_cmp(ip6,ip6); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_cmp(ip6r,ip6r); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_cmp(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION iprange_cmp(iprange,iprange); -ALTER EXTENSION ip4r ADD OPERATOR CLASS btree_ip4_ops USING btree; -ALTER EXTENSION ip4r ADD OPERATOR CLASS btree_ip4r_ops USING btree; -ALTER EXTENSION ip4r ADD OPERATOR CLASS btree_ip6_ops USING btree; -ALTER EXTENSION ip4r ADD OPERATOR CLASS btree_ip6r_ops USING btree; -ALTER EXTENSION ip4r ADD OPERATOR CLASS btree_ipaddress_ops USING btree; -ALTER EXTENSION ip4r ADD OPERATOR CLASS btree_iprange_ops USING btree; -ALTER EXTENSION ip4r ADD FUNCTION ip4hash(ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip6hash(ip6); -ALTER EXTENSION ip4r ADD FUNCTION ipaddresshash(ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION ip4rhash(ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6rhash(ip6r); -ALTER EXTENSION ip4r ADD FUNCTION iprangehash(iprange); -ALTER EXTENSION ip4r ADD OPERATOR CLASS hash_ip4_ops USING hash; -ALTER EXTENSION ip4r ADD OPERATOR CLASS hash_ip4r_ops USING hash; -ALTER EXTENSION ip4r ADD OPERATOR CLASS hash_ip6_ops USING hash; -ALTER EXTENSION ip4r ADD OPERATOR CLASS hash_ip6r_ops USING hash; -ALTER EXTENSION ip4r ADD OPERATOR CLASS hash_ipaddress_ops USING hash; -ALTER EXTENSION ip4r ADD OPERATOR CLASS hash_iprange_ops USING hash; -ALTER EXTENSION ip4r ADD FUNCTION gip4r_consistent(internal,ip4r,int4); -ALTER EXTENSION ip4r ADD FUNCTION gip4r_compress(internal); -ALTER EXTENSION ip4r ADD FUNCTION gip4r_decompress(internal); -ALTER EXTENSION ip4r ADD FUNCTION gip4r_penalty(internal,internal,internal); -ALTER EXTENSION ip4r ADD FUNCTION gip4r_picksplit(internal, internal); -ALTER EXTENSION ip4r ADD FUNCTION gip4r_union(internal, internal); -ALTER EXTENSION ip4r ADD FUNCTION gip4r_same(ip4r, ip4r, internal); -ALTER EXTENSION ip4r ADD FUNCTION gip6r_consistent(internal,ip6r,int4); -ALTER EXTENSION ip4r ADD FUNCTION gip6r_compress(internal); -ALTER EXTENSION ip4r ADD FUNCTION gip6r_decompress(internal); -ALTER EXTENSION ip4r ADD FUNCTION gip6r_penalty(internal,internal,internal); -ALTER EXTENSION ip4r ADD FUNCTION gip6r_picksplit(internal, internal); -ALTER EXTENSION ip4r ADD FUNCTION gip6r_union(internal, internal); -ALTER EXTENSION ip4r ADD FUNCTION gip6r_same(ip6r, ip6r, internal); -ALTER EXTENSION ip4r ADD FUNCTION gipr_consistent(internal,iprange,int4); -ALTER EXTENSION ip4r ADD FUNCTION gipr_compress(internal); -ALTER EXTENSION ip4r ADD FUNCTION gipr_decompress(internal); -ALTER EXTENSION ip4r ADD FUNCTION gipr_penalty(internal,internal,internal); -ALTER EXTENSION ip4r ADD FUNCTION gipr_picksplit(internal, internal); -ALTER EXTENSION ip4r ADD FUNCTION gipr_union(internal, internal); -ALTER EXTENSION ip4r ADD FUNCTION gipr_same(iprange, iprange, internal); -ALTER EXTENSION ip4r ADD OPERATOR CLASS gist_ip4r_ops USING gist; -ALTER EXTENSION ip4r ADD OPERATOR CLASS gist_ip6r_ops USING gist; -ALTER EXTENSION ip4r ADD OPERATOR CLASS gist_iprange_ops USING gist; - --- end diff -Nru ip4r-2.3/ip4r--unpackaged2.1--2.1.sql ip4r-2.4/ip4r--unpackaged2.1--2.1.sql --- ip4r-2.3/ip4r--unpackaged2.1--2.1.sql 2018-05-24 21:30:28.000000000 +0000 +++ ip4r-2.4/ip4r--unpackaged2.1--2.1.sql 1970-01-01 00:00:00.000000000 +0000 @@ -1,423 +0,0 @@ --- ip4r extension - --- complain if script is sourced in psql, rather than via CREATE EXTENSION -\echo Use "CREATE EXTENSION ip4r" to load this file. \quit - -ALTER EXTENSION ip4r ADD FUNCTION ip4_in(cstring); -ALTER EXTENSION ip4r ADD FUNCTION ip4_out(ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip4_recv(internal); -ALTER EXTENSION ip4r ADD FUNCTION ip4_send(ip4); -ALTER EXTENSION ip4r ADD TYPE ip4; -ALTER EXTENSION ip4r ADD FUNCTION ip4r_in(cstring); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_out(ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_recv(internal); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_send(ip4r); -ALTER EXTENSION ip4r ADD TYPE ip4r; -ALTER EXTENSION ip4r ADD FUNCTION ip6_in(cstring); -ALTER EXTENSION ip4r ADD FUNCTION ip6_out(ip6); -ALTER EXTENSION ip4r ADD FUNCTION ip6_recv(internal); -ALTER EXTENSION ip4r ADD FUNCTION ip6_send(ip6); -ALTER EXTENSION ip4r ADD TYPE ip6; -ALTER EXTENSION ip4r ADD FUNCTION ip6r_in(cstring); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_out(ip6r); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_recv(internal); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_send(ip6r); -ALTER EXTENSION ip4r ADD TYPE ip6r; -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_in(cstring); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_out(ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_recv(internal); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_send(ipaddress); -ALTER EXTENSION ip4r ADD TYPE ipaddress; -ALTER EXTENSION ip4r ADD FUNCTION iprange_in(cstring); -ALTER EXTENSION ip4r ADD FUNCTION iprange_out(iprange); -ALTER EXTENSION ip4r ADD FUNCTION iprange_recv(internal); -ALTER EXTENSION ip4r ADD FUNCTION iprange_send(iprange); -ALTER EXTENSION ip4r ADD TYPE iprange; -ALTER EXTENSION ip4r ADD FUNCTION ip4(bigint); -ALTER EXTENSION ip4r ADD FUNCTION ip4(double precision); -ALTER EXTENSION ip4r ADD FUNCTION ip4(numeric); -ALTER EXTENSION ip4r ADD FUNCTION ip4(inet); -ALTER EXTENSION ip4r ADD FUNCTION ip4(text); -ALTER EXTENSION ip4r ADD FUNCTION ip4(ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION ip6(numeric); -ALTER EXTENSION ip4r ADD FUNCTION ip6(inet); -ALTER EXTENSION ip4r ADD FUNCTION ip6(text); -ALTER EXTENSION ip4r ADD FUNCTION ip6(ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress(inet); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress(ip4); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress(ip6); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress(text); -ALTER EXTENSION ip4r ADD FUNCTION ip4r(cidr); -ALTER EXTENSION ip4r ADD FUNCTION ip4r(ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip4r(text); -ALTER EXTENSION ip4r ADD FUNCTION ip4r(iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip6r(cidr); -ALTER EXTENSION ip4r ADD FUNCTION ip6r(ip6); -ALTER EXTENSION ip4r ADD FUNCTION ip6r(text); -ALTER EXTENSION ip4r ADD FUNCTION ip6r(iprange); -ALTER EXTENSION ip4r ADD FUNCTION iprange(cidr); -ALTER EXTENSION ip4r ADD FUNCTION iprange(ip4); -ALTER EXTENSION ip4r ADD FUNCTION iprange(ip6); -ALTER EXTENSION ip4r ADD FUNCTION iprange(ip4r); -ALTER EXTENSION ip4r ADD FUNCTION iprange(ip6r); -ALTER EXTENSION ip4r ADD FUNCTION iprange(ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION iprange(text); -ALTER EXTENSION ip4r ADD FUNCTION cidr(ip4); -ALTER EXTENSION ip4r ADD FUNCTION cidr(ip4r); -ALTER EXTENSION ip4r ADD FUNCTION cidr(ip6); -ALTER EXTENSION ip4r ADD FUNCTION cidr(ip6r); -ALTER EXTENSION ip4r ADD FUNCTION cidr(ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION cidr(iprange); -ALTER EXTENSION ip4r ADD FUNCTION text(ip4); -ALTER EXTENSION ip4r ADD FUNCTION text(ip4r); -ALTER EXTENSION ip4r ADD FUNCTION text(ip6); -ALTER EXTENSION ip4r ADD FUNCTION text(ip6r); -ALTER EXTENSION ip4r ADD FUNCTION text(ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION text(iprange); -ALTER EXTENSION ip4r ADD FUNCTION to_bigint(ip4); -ALTER EXTENSION ip4r ADD FUNCTION to_double(ip4); -ALTER EXTENSION ip4r ADD FUNCTION to_numeric(ip4); -ALTER EXTENSION ip4r ADD FUNCTION to_numeric(ip6); -ALTER EXTENSION ip4r ADD FUNCTION to_numeric(ipaddress); -ALTER EXTENSION ip4r ADD CAST (ip4 as bigint); -ALTER EXTENSION ip4r ADD CAST (ip4 as double precision); -ALTER EXTENSION ip4r ADD CAST (ip4 as numeric); -ALTER EXTENSION ip4r ADD CAST (ip4 as text); -ALTER EXTENSION ip4r ADD CAST (ip4 as cidr); -ALTER EXTENSION ip4r ADD CAST (ip4r as cidr); -ALTER EXTENSION ip4r ADD CAST (ip4r as text); -ALTER EXTENSION ip4r ADD CAST (ip6 as numeric); -ALTER EXTENSION ip4r ADD CAST (ip6 as text); -ALTER EXTENSION ip4r ADD CAST (ip6 as cidr); -ALTER EXTENSION ip4r ADD CAST (ip6r as cidr); -ALTER EXTENSION ip4r ADD CAST (ip6r as text); -ALTER EXTENSION ip4r ADD CAST (ipaddress as numeric); -ALTER EXTENSION ip4r ADD CAST (ipaddress as text); -ALTER EXTENSION ip4r ADD CAST (ipaddress as cidr); -ALTER EXTENSION ip4r ADD CAST (iprange as cidr); -ALTER EXTENSION ip4r ADD CAST (iprange as text); -ALTER EXTENSION ip4r ADD CAST (text as ip4); -ALTER EXTENSION ip4r ADD CAST (text as ip4r); -ALTER EXTENSION ip4r ADD CAST (text as ip6); -ALTER EXTENSION ip4r ADD CAST (text as ip6r); -ALTER EXTENSION ip4r ADD CAST (text as ipaddress); -ALTER EXTENSION ip4r ADD CAST (text as iprange); -ALTER EXTENSION ip4r ADD CAST (bigint as ip4); -ALTER EXTENSION ip4r ADD CAST (double precision as ip4); -ALTER EXTENSION ip4r ADD CAST (numeric as ip4); -ALTER EXTENSION ip4r ADD CAST (numeric as ip6); -ALTER EXTENSION ip4r ADD CAST (cidr as ip4r); -ALTER EXTENSION ip4r ADD CAST (cidr as ip6r); -ALTER EXTENSION ip4r ADD CAST (cidr as iprange); -ALTER EXTENSION ip4r ADD CAST (inet as ip4); -ALTER EXTENSION ip4r ADD CAST (inet as ip6); -ALTER EXTENSION ip4r ADD CAST (inet as ipaddress); -ALTER EXTENSION ip4r ADD CAST (ip4 as ip4r); -ALTER EXTENSION ip4r ADD CAST (ip4 as ipaddress); -ALTER EXTENSION ip4r ADD CAST (ip4 as iprange); -ALTER EXTENSION ip4r ADD CAST (ip4r as iprange); -ALTER EXTENSION ip4r ADD CAST (ip6 as ip6r); -ALTER EXTENSION ip4r ADD CAST (ip6 as ipaddress); -ALTER EXTENSION ip4r ADD CAST (ip6 as iprange); -ALTER EXTENSION ip4r ADD CAST (ip6r as iprange); -ALTER EXTENSION ip4r ADD CAST (ipaddress as iprange); -ALTER EXTENSION ip4r ADD CAST (ipaddress as ip4); -ALTER EXTENSION ip4r ADD CAST (ipaddress as ip6); -ALTER EXTENSION ip4r ADD CAST (iprange as ip4r); -ALTER EXTENSION ip4r ADD CAST (iprange as ip6r); -ALTER EXTENSION ip4r ADD FUNCTION ip4r(ip4,ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip6r(ip6,ip6); -ALTER EXTENSION ip4r ADD FUNCTION iprange(ip4,ip4); -ALTER EXTENSION ip4r ADD FUNCTION iprange(ip6,ip6); -ALTER EXTENSION ip4r ADD FUNCTION iprange(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION family(ip4); -ALTER EXTENSION ip4r ADD FUNCTION family(ip4r); -ALTER EXTENSION ip4r ADD FUNCTION family(ip6); -ALTER EXTENSION ip4r ADD FUNCTION family(ip6r); -ALTER EXTENSION ip4r ADD FUNCTION family(ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION family(iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4_netmask(integer); -ALTER EXTENSION ip4r ADD FUNCTION ip6_netmask(integer); -ALTER EXTENSION ip4r ADD FUNCTION is_cidr(ip4r); -ALTER EXTENSION ip4r ADD FUNCTION is_cidr(ip6r); -ALTER EXTENSION ip4r ADD FUNCTION is_cidr(iprange); -ALTER EXTENSION ip4r ADD FUNCTION masklen(ip4r); -ALTER EXTENSION ip4r ADD FUNCTION masklen(ip6r); -ALTER EXTENSION ip4r ADD FUNCTION masklen(iprange); -ALTER EXTENSION ip4r ADD FUNCTION lower(ip4r); -ALTER EXTENSION ip4r ADD FUNCTION lower(ip6r); -ALTER EXTENSION ip4r ADD FUNCTION lower(iprange); -ALTER EXTENSION ip4r ADD FUNCTION upper(ip4r); -ALTER EXTENSION ip4r ADD FUNCTION upper(ip6r); -ALTER EXTENSION ip4r ADD FUNCTION upper(iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4_net_lower(ip4,integer); -ALTER EXTENSION ip4r ADD FUNCTION ip6_net_lower(ip6,integer); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_net_lower(ipaddress,integer); -ALTER EXTENSION ip4r ADD FUNCTION ip4_net_upper(ip4,integer); -ALTER EXTENSION ip4r ADD FUNCTION ip6_net_upper(ip6,integer); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_net_upper(ipaddress,integer); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_union(ip4r, ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_union(ip6r, ip6r); -ALTER EXTENSION ip4r ADD FUNCTION iprange_union(iprange, iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_inter(ip4r,ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_inter(ip6r,ip6r); -ALTER EXTENSION ip4r ADD FUNCTION iprange_inter(iprange,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_net_mask(ip4,ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_net_mask(ip6,ip6); -ALTER EXTENSION ip4r ADD FUNCTION iprange_net_mask(ip4,ip4); -ALTER EXTENSION ip4r ADD FUNCTION iprange_net_mask(ip6,ip6); -ALTER EXTENSION ip4r ADD FUNCTION iprange_net_mask(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_net_prefix(ip4,integer); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_net_prefix(ip6,integer); -ALTER EXTENSION ip4r ADD FUNCTION iprange_net_prefix(ip4,integer); -ALTER EXTENSION ip4r ADD FUNCTION iprange_net_prefix(ip6,integer); -ALTER EXTENSION ip4r ADD FUNCTION iprange_net_prefix(ipaddress,integer); -ALTER EXTENSION ip4r ADD OPERATOR /(ip4,ip4); -ALTER EXTENSION ip4r ADD OPERATOR /(ip6,ip6); -ALTER EXTENSION ip4r ADD OPERATOR /(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD OPERATOR /(ip4,integer); -ALTER EXTENSION ip4r ADD OPERATOR /(ip6,integer); -ALTER EXTENSION ip4r ADD OPERATOR /(ipaddress,integer); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_size(ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_size(ip6r); -ALTER EXTENSION ip4r ADD FUNCTION iprange_size(iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_size_exact(ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_size_exact(ip6r); -ALTER EXTENSION ip4r ADD FUNCTION iprange_size_exact(iprange); -ALTER EXTENSION ip4r ADD OPERATOR @(NONE,ip4r); -ALTER EXTENSION ip4r ADD OPERATOR @(NONE,ip6r); -ALTER EXTENSION ip4r ADD OPERATOR @(NONE,iprange); -ALTER EXTENSION ip4r ADD OPERATOR @@(NONE,ip4r); -ALTER EXTENSION ip4r ADD OPERATOR @@(NONE,ip6r); -ALTER EXTENSION ip4r ADD OPERATOR @@(NONE,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4_and(ip4,ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip6_and(ip6,ip6); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_and(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD OPERATOR &(ip4,ip4); -ALTER EXTENSION ip4r ADD OPERATOR &(ip6,ip6); -ALTER EXTENSION ip4r ADD OPERATOR &(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION ip4_or(ip4,ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip6_or(ip6,ip6); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_or(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD OPERATOR |(ip4,ip4); -ALTER EXTENSION ip4r ADD OPERATOR |(ip6,ip6); -ALTER EXTENSION ip4r ADD OPERATOR |(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION ip4_not(ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip6_not(ip6); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_not(ipaddress); -ALTER EXTENSION ip4r ADD OPERATOR ~(NONE,ip4); -ALTER EXTENSION ip4r ADD OPERATOR ~(NONE,ip6); -ALTER EXTENSION ip4r ADD OPERATOR ~(NONE,ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION ip4_xor(ip4,ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip6_xor(ip6,ip6); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_xor(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD OPERATOR #(ip4,ip4); -ALTER EXTENSION ip4r ADD OPERATOR #(ip6,ip6); -ALTER EXTENSION ip4r ADD OPERATOR #(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION ip4_plus_bigint(ip4,bigint); -ALTER EXTENSION ip4r ADD FUNCTION ip4_plus_int(ip4,integer); -ALTER EXTENSION ip4r ADD FUNCTION ip4_plus_numeric(ip4,numeric); -ALTER EXTENSION ip4r ADD OPERATOR +(ip4,bigint); -ALTER EXTENSION ip4r ADD OPERATOR +(ip4,integer); -ALTER EXTENSION ip4r ADD OPERATOR +(ip4,numeric); -ALTER EXTENSION ip4r ADD FUNCTION ip6_plus_bigint(ip6,bigint); -ALTER EXTENSION ip4r ADD FUNCTION ip6_plus_int(ip6,integer); -ALTER EXTENSION ip4r ADD FUNCTION ip6_plus_numeric(ip6,numeric); -ALTER EXTENSION ip4r ADD OPERATOR +(ip6,bigint); -ALTER EXTENSION ip4r ADD OPERATOR +(ip6,integer); -ALTER EXTENSION ip4r ADD OPERATOR +(ip6,numeric); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_plus_bigint(ipaddress,bigint); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_plus_int(ipaddress,integer); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_plus_numeric(ipaddress,numeric); -ALTER EXTENSION ip4r ADD OPERATOR +(ipaddress,bigint); -ALTER EXTENSION ip4r ADD OPERATOR +(ipaddress,integer); -ALTER EXTENSION ip4r ADD OPERATOR +(ipaddress,numeric); -ALTER EXTENSION ip4r ADD FUNCTION ip4_minus_bigint(ip4,bigint); -ALTER EXTENSION ip4r ADD FUNCTION ip4_minus_int(ip4,integer); -ALTER EXTENSION ip4r ADD FUNCTION ip4_minus_numeric(ip4,numeric); -ALTER EXTENSION ip4r ADD OPERATOR -(ip4,bigint); -ALTER EXTENSION ip4r ADD OPERATOR -(ip4,integer); -ALTER EXTENSION ip4r ADD OPERATOR -(ip4,numeric); -ALTER EXTENSION ip4r ADD FUNCTION ip6_minus_bigint(ip6,bigint); -ALTER EXTENSION ip4r ADD FUNCTION ip6_minus_int(ip6,integer); -ALTER EXTENSION ip4r ADD FUNCTION ip6_minus_numeric(ip6,numeric); -ALTER EXTENSION ip4r ADD OPERATOR -(ip6,bigint); -ALTER EXTENSION ip4r ADD OPERATOR -(ip6,integer); -ALTER EXTENSION ip4r ADD OPERATOR -(ip6,numeric); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_minus_bigint(ipaddress,bigint); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_minus_int(ipaddress,integer); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_minus_numeric(ipaddress,numeric); -ALTER EXTENSION ip4r ADD OPERATOR -(ipaddress,bigint); -ALTER EXTENSION ip4r ADD OPERATOR -(ipaddress,integer); -ALTER EXTENSION ip4r ADD OPERATOR -(ipaddress,numeric); -ALTER EXTENSION ip4r ADD FUNCTION ip4_minus_ip4(ip4,ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip6_minus_ip6(ip6,ip6); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_minus_ipaddress(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD OPERATOR -(ip4,ip4); -ALTER EXTENSION ip4r ADD OPERATOR -(ip6,ip6); -ALTER EXTENSION ip4r ADD OPERATOR -(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_contained_by(ip4r,ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_contained_by(ip6r,ip6r); -ALTER EXTENSION ip4r ADD FUNCTION iprange_contained_by(iprange,iprange); -ALTER EXTENSION ip4r ADD OPERATOR <<=(ip4r,ip4r); -ALTER EXTENSION ip4r ADD OPERATOR <<=(ip6r,ip6r); -ALTER EXTENSION ip4r ADD OPERATOR <<=(iprange,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_contained_by_strict(ip4r,ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_contained_by_strict(ip6r,ip6r); -ALTER EXTENSION ip4r ADD FUNCTION iprange_contained_by_strict(iprange,iprange); -ALTER EXTENSION ip4r ADD OPERATOR <<(ip4r,ip4r); -ALTER EXTENSION ip4r ADD OPERATOR <<(ip6r,ip6r); -ALTER EXTENSION ip4r ADD OPERATOR <<(iprange,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_contains(ip4r,ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_contains(ip6r,ip6r); -ALTER EXTENSION ip4r ADD FUNCTION iprange_contains(iprange,iprange); -ALTER EXTENSION ip4r ADD OPERATOR >>=(ip4r,ip4r); -ALTER EXTENSION ip4r ADD OPERATOR >>=(ip6r,ip6r); -ALTER EXTENSION ip4r ADD OPERATOR >>=(iprange,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_contains_strict(ip4r,ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_contains_strict(ip6r,ip6r); -ALTER EXTENSION ip4r ADD FUNCTION iprange_contains_strict(iprange,iprange); -ALTER EXTENSION ip4r ADD OPERATOR >>(ip4r,ip4r); -ALTER EXTENSION ip4r ADD OPERATOR >>(ip6r,ip6r); -ALTER EXTENSION ip4r ADD OPERATOR >>(iprange,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_overlaps(ip4r,ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_overlaps(ip6r,ip6r); -ALTER EXTENSION ip4r ADD FUNCTION iprange_overlaps(iprange,iprange); -ALTER EXTENSION ip4r ADD OPERATOR &&(ip4r,ip4r); -ALTER EXTENSION ip4r ADD OPERATOR &&(ip6r,ip6r); -ALTER EXTENSION ip4r ADD OPERATOR &&(iprange,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4_contained_by(ip4,ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip4_contained_by(ip4,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip6_contained_by(ip6,ip6r); -ALTER EXTENSION ip4r ADD FUNCTION ip6_contained_by(ip6,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_contained_by(ipaddress,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4_contains(ip4r,ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip6_contains(ip6r,ip6); -ALTER EXTENSION ip4r ADD FUNCTION ip4_contains(iprange,ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip6_contains(iprange,ip6); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_contains(iprange,ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION ip4_eq(ip4,ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_eq(ip4r,ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6_eq(ip6,ip6); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_eq(ip6r,ip6r); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_eq(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION iprange_eq(iprange,iprange); -ALTER EXTENSION ip4r ADD OPERATOR =(ip4,ip4); -ALTER EXTENSION ip4r ADD OPERATOR =(ip4r,ip4r); -ALTER EXTENSION ip4r ADD OPERATOR =(ip6,ip6); -ALTER EXTENSION ip4r ADD OPERATOR =(ip6r,ip6r); -ALTER EXTENSION ip4r ADD OPERATOR =(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD OPERATOR =(iprange,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4_ge(ip4,ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_ge(ip4r,ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6_ge(ip6,ip6); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_ge(ip6r,ip6r); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_ge(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION iprange_ge(iprange,iprange); -ALTER EXTENSION ip4r ADD OPERATOR >=(ip4,ip4); -ALTER EXTENSION ip4r ADD OPERATOR >=(ip4r,ip4r); -ALTER EXTENSION ip4r ADD OPERATOR >=(ip6,ip6); -ALTER EXTENSION ip4r ADD OPERATOR >=(ip6r,ip6r); -ALTER EXTENSION ip4r ADD OPERATOR >=(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD OPERATOR >=(iprange,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4_gt(ip4,ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_gt(ip4r,ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6_gt(ip6,ip6); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_gt(ip6r,ip6r); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_gt(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION iprange_gt(iprange,iprange); -ALTER EXTENSION ip4r ADD OPERATOR >(ip4,ip4); -ALTER EXTENSION ip4r ADD OPERATOR >(ip4r,ip4r); -ALTER EXTENSION ip4r ADD OPERATOR >(ip6,ip6); -ALTER EXTENSION ip4r ADD OPERATOR >(ip6r,ip6r); -ALTER EXTENSION ip4r ADD OPERATOR >(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD OPERATOR >(iprange,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4_le(ip4,ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_le(ip4r,ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6_le(ip6,ip6); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_le(ip6r,ip6r); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_le(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION iprange_le(iprange,iprange); -ALTER EXTENSION ip4r ADD OPERATOR <=(ip4,ip4); -ALTER EXTENSION ip4r ADD OPERATOR <=(ip4r,ip4r); -ALTER EXTENSION ip4r ADD OPERATOR <=(ip6,ip6); -ALTER EXTENSION ip4r ADD OPERATOR <=(ip6r,ip6r); -ALTER EXTENSION ip4r ADD OPERATOR <=(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD OPERATOR <=(iprange,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4_lt(ip4,ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_lt(ip4r,ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6_lt(ip6,ip6); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_lt(ip6r,ip6r); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_lt(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION iprange_lt(iprange,iprange); -ALTER EXTENSION ip4r ADD OPERATOR <(ip4,ip4); -ALTER EXTENSION ip4r ADD OPERATOR <(ip4r,ip4r); -ALTER EXTENSION ip4r ADD OPERATOR <(ip6,ip6); -ALTER EXTENSION ip4r ADD OPERATOR <(ip6r,ip6r); -ALTER EXTENSION ip4r ADD OPERATOR <(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD OPERATOR <(iprange,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4_neq(ip4,ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_neq(ip4r,ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6_neq(ip6,ip6); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_neq(ip6r,ip6r); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_neq(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION iprange_neq(iprange,iprange); -ALTER EXTENSION ip4r ADD OPERATOR <>(ip4,ip4); -ALTER EXTENSION ip4r ADD OPERATOR <>(ip4r,ip4r); -ALTER EXTENSION ip4r ADD OPERATOR <>(ip6,ip6); -ALTER EXTENSION ip4r ADD OPERATOR <>(ip6r,ip6r); -ALTER EXTENSION ip4r ADD OPERATOR <>(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD OPERATOR <>(iprange,iprange); -ALTER EXTENSION ip4r ADD FUNCTION ip4_cmp(ip4,ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip4r_cmp(ip4r,ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6_cmp(ip6,ip6); -ALTER EXTENSION ip4r ADD FUNCTION ip6r_cmp(ip6r,ip6r); -ALTER EXTENSION ip4r ADD FUNCTION ipaddress_cmp(ipaddress,ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION iprange_cmp(iprange,iprange); -ALTER EXTENSION ip4r ADD OPERATOR CLASS btree_ip4_ops USING btree; -ALTER EXTENSION ip4r ADD OPERATOR CLASS btree_ip4r_ops USING btree; -ALTER EXTENSION ip4r ADD OPERATOR CLASS btree_ip6_ops USING btree; -ALTER EXTENSION ip4r ADD OPERATOR CLASS btree_ip6r_ops USING btree; -ALTER EXTENSION ip4r ADD OPERATOR CLASS btree_ipaddress_ops USING btree; -ALTER EXTENSION ip4r ADD OPERATOR CLASS btree_iprange_ops USING btree; -ALTER EXTENSION ip4r ADD FUNCTION ip4hash(ip4); -ALTER EXTENSION ip4r ADD FUNCTION ip6hash(ip6); -ALTER EXTENSION ip4r ADD FUNCTION ipaddresshash(ipaddress); -ALTER EXTENSION ip4r ADD FUNCTION ip4rhash(ip4r); -ALTER EXTENSION ip4r ADD FUNCTION ip6rhash(ip6r); -ALTER EXTENSION ip4r ADD FUNCTION iprangehash(iprange); -ALTER EXTENSION ip4r ADD OPERATOR CLASS hash_ip4_ops USING hash; -ALTER EXTENSION ip4r ADD OPERATOR CLASS hash_ip4r_ops USING hash; -ALTER EXTENSION ip4r ADD OPERATOR CLASS hash_ip6_ops USING hash; -ALTER EXTENSION ip4r ADD OPERATOR CLASS hash_ip6r_ops USING hash; -ALTER EXTENSION ip4r ADD OPERATOR CLASS hash_ipaddress_ops USING hash; -ALTER EXTENSION ip4r ADD OPERATOR CLASS hash_iprange_ops USING hash; -ALTER EXTENSION ip4r ADD FUNCTION gip4r_consistent(internal,ip4r,int2,oid,internal); -ALTER EXTENSION ip4r ADD FUNCTION gip4r_compress(internal); -ALTER EXTENSION ip4r ADD FUNCTION gip4r_decompress(internal); -ALTER EXTENSION ip4r ADD FUNCTION gip4r_penalty(internal,internal,internal); -ALTER EXTENSION ip4r ADD FUNCTION gip4r_picksplit(internal, internal); -ALTER EXTENSION ip4r ADD FUNCTION gip4r_union(internal, internal); -ALTER EXTENSION ip4r ADD FUNCTION gip4r_same(ip4r, ip4r, internal); -ALTER EXTENSION ip4r ADD FUNCTION gip4r_fetch(internal); -ALTER EXTENSION ip4r ADD FUNCTION gip6r_consistent(internal,ip6r,int2,oid,internal); -ALTER EXTENSION ip4r ADD FUNCTION gip6r_compress(internal); -ALTER EXTENSION ip4r ADD FUNCTION gip6r_decompress(internal); -ALTER EXTENSION ip4r ADD FUNCTION gip6r_penalty(internal,internal,internal); -ALTER EXTENSION ip4r ADD FUNCTION gip6r_picksplit(internal, internal); -ALTER EXTENSION ip4r ADD FUNCTION gip6r_union(internal, internal); -ALTER EXTENSION ip4r ADD FUNCTION gip6r_same(ip6r, ip6r, internal); -ALTER EXTENSION ip4r ADD FUNCTION gip6r_fetch(internal); -ALTER EXTENSION ip4r ADD FUNCTION gipr_consistent(internal,iprange,int2,oid,internal); -ALTER EXTENSION ip4r ADD FUNCTION gipr_compress(internal); -ALTER EXTENSION ip4r ADD FUNCTION gipr_decompress(internal); -ALTER EXTENSION ip4r ADD FUNCTION gipr_penalty(internal,internal,internal); -ALTER EXTENSION ip4r ADD FUNCTION gipr_picksplit(internal, internal); -ALTER EXTENSION ip4r ADD FUNCTION gipr_union(internal, internal); -ALTER EXTENSION ip4r ADD FUNCTION gipr_same(iprange, iprange, internal); -ALTER EXTENSION ip4r ADD FUNCTION gipr_fetch(internal); -ALTER EXTENSION ip4r ADD OPERATOR CLASS gist_ip4r_ops USING gist; -ALTER EXTENSION ip4r ADD OPERATOR CLASS gist_ip6r_ops USING gist; -ALTER EXTENSION ip4r ADD OPERATOR CLASS gist_iprange_ops USING gist; - --- end diff -Nru ip4r-2.3/ip6r.c ip4r-2.4/ip6r.c --- ip4r-2.3/ip6r.c 2018-05-24 21:30:28.000000000 +0000 +++ ip4r-2.4/ip6r.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,1636 +0,0 @@ -/* $Id: ip6r.c,v 1.2 2011/08/22 14:05:19 andrewsn Exp $ */ - -#include "ipr.h" - -#include "ip6r_funcs.h" - - -/* extract an IP range from text. - */ -static -bool ip6r_from_str(char *str, IP6R *ipr) -{ - char buf[IP6_STRING_MAX]; - int pos = strcspn(str, "-/"); - IP6 ip; - - switch (str[pos]) - { - case 0: /* no separator, must be single ip6 addr */ - { - if (!ip6_raw_input(str, ip.bits)) - return FALSE; - ipr->lower = ip; - ipr->upper = ip; - return TRUE; - } - - case '-': /* lower-upper */ - { - char *rest = str + pos + 1; - - if (pos > sizeof(buf)-2) - return FALSE; - memcpy(buf, str, pos); - buf[pos] = 0; - if (!ip6_raw_input(buf, ip.bits)) - return FALSE; - ipr->lower = ip; - if (!ip6_raw_input(rest, ip.bits)) - return FALSE; - if (!ip6_lessthan(&ip, &ipr->lower)) - ipr->upper = ip; - else - { - ipr->upper = ipr->lower; - ipr->lower = ip; - } - return TRUE; - } - - case '/': /* prefix/len */ - { - char *rest = str + pos + 1; - unsigned pfxlen; - char dummy; - - if (pos > sizeof(buf)-2) - return FALSE; - memcpy(buf, str, pos); - buf[pos] = 0; - if (!ip6_raw_input(buf, ip.bits)) - return FALSE; - if (rest[strspn(rest,"0123456789")]) - return FALSE; - if (sscanf(rest, "%u%c", &pfxlen, &dummy) != 1) - return FALSE; - return ip6r_from_cidr(&ip, pfxlen, ipr); - } - - default: - return FALSE; /* can't happen */ - } -} - - -/* Output an ip range in text form - */ -static -int ip6r_to_str(IP6R *ipr, char *str, int slen) -{ - char buf1[IP6_STRING_MAX]; - char buf2[IP6_STRING_MAX]; - unsigned msk; - - if (ip6_equal(&ipr->lower, &ipr->upper)) - return ip6_raw_output(ipr->lower.bits, str, slen); - - if ((msk = masklen6(&ipr->lower,&ipr->upper)) <= 128) - { - ip6_raw_output(ipr->lower.bits, buf1, sizeof(buf1)); - return snprintf(str, slen, "%s/%u", buf1, msk); - } - - ip6_raw_output(ipr->lower.bits, buf1, sizeof(buf1)); - ip6_raw_output(ipr->upper.bits, buf2, sizeof(buf2)); - - return snprintf(str, slen, "%s-%s", buf1, buf2); -} - - -/**************************************************************************/ -/* This part handles all aspects of postgres interfacing. - */ - - -/* end of version dependencies */ - - -/* -#define GIST_DEBUG -#define GIST_QUERY_DEBUG -*/ - -static -text * -make_text(int len) -{ - text *ret = (text *) palloc0(len + VARHDRSZ); - SET_VARSIZE(ret, len + VARHDRSZ); - return ret; -} - -static inline -void -set_text_len(text *txt, int len) -{ - Assert(len >= 0 && len + VARHDRSZ <= VARSIZE(txt)); - if (len + VARHDRSZ <= VARSIZE(txt)) - SET_VARSIZE(txt, len + VARHDRSZ); -} - -/* -** Input/Output routines -*/ - -PG_FUNCTION_INFO_V1(ip6_in); -Datum -ip6_in(PG_FUNCTION_ARGS) -{ - char *str = PG_GETARG_CSTRING(0); - IP6 *ip = palloc(sizeof(IP6)); - if (ip6_raw_input(str, ip->bits)) - PG_RETURN_IP6_P(ip); - - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid IP6 value: '%s'", str))); - PG_RETURN_NULL(); -} - -PG_FUNCTION_INFO_V1(ip6_out); -Datum -ip6_out(PG_FUNCTION_ARGS) -{ - IP6 *ip = PG_GETARG_IP6_P(0); - char *out = palloc(IP6_STRING_MAX); - ip6_raw_output(ip->bits, out, IP6_STRING_MAX); - PG_RETURN_CSTRING(out); -} - -PG_FUNCTION_INFO_V1(ip6_recv); -Datum -ip6_recv(PG_FUNCTION_ARGS) -{ - StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); - IP6 *ip = palloc(sizeof(IP6)); - - ip->bits[0] = pq_getmsgint64(buf); - ip->bits[1] = pq_getmsgint64(buf); - - PG_RETURN_IP6_P(ip); -} - -PG_FUNCTION_INFO_V1(ip6_send); -Datum -ip6_send(PG_FUNCTION_ARGS) -{ - IP6 *arg1 = PG_GETARG_IP6_P(0); - StringInfoData buf; - - pq_begintypsend(&buf); - pq_sendint64(&buf, arg1->bits[0]); - pq_sendint64(&buf, arg1->bits[1]); - PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); -} - -PG_FUNCTION_INFO_V1(ip6hash); -Datum -ip6hash(PG_FUNCTION_ARGS) -{ - IP6 *arg1 = PG_GETARG_IP6_P(0); - - return hash_any((unsigned char *)arg1, sizeof(IP6)); -} - -PG_FUNCTION_INFO_V1(ip6_cast_to_text); -Datum -ip6_cast_to_text(PG_FUNCTION_ARGS) -{ - IP6 *ip = PG_GETARG_IP6_P(0); - text *out = make_text(IP6_STRING_MAX); - set_text_len(out, ip6_raw_output(ip->bits, VARDATA(out), IP6_STRING_MAX)); - PG_RETURN_TEXT_P(out); -} - -PG_FUNCTION_INFO_V1(ip6_cast_from_text); -Datum -ip6_cast_from_text(PG_FUNCTION_ARGS) -{ - text *txt = PG_GETARG_TEXT_PP(0); - int tlen = VARSIZE_ANY_EXHDR(txt); - char buf[IP6_STRING_MAX]; - - if (tlen < sizeof(buf)) - { - IP6 *ip = palloc(sizeof(IP6)); - - memcpy(buf, VARDATA_ANY(txt), tlen); - buf[tlen] = 0; - if (ip6_raw_input(buf, ip->bits)) - PG_RETURN_IP6_P(ip); - } - - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid IP6 value in text"))); - PG_RETURN_NULL(); -} - -PG_FUNCTION_INFO_V1(ip6_cast_from_inet); -Datum -ip6_cast_from_inet(PG_FUNCTION_ARGS) -{ - inet *inetptr = PG_GETARG_INET_P(0); - inet_struct *in = INET_STRUCT_DATA(inetptr); - - if (in->family == PGSQL_AF_INET6) - { - unsigned char *p = in->ipaddr; - IP6 *ip = palloc(sizeof(IP6)); - ip->bits[0] = (((uint64)p[0] << 56) - | ((uint64)p[1] << 48) - | ((uint64)p[2] << 40) - | ((uint64)p[3] << 32) - | ((uint64)p[4] << 24) - | ((uint64)p[5] << 16) - | ((uint64)p[6] << 8) - | p[7]); - ip->bits[1] = (((uint64)p[8] << 56) - | ((uint64)p[9] << 48) - | ((uint64)p[10] << 40) - | ((uint64)p[11] << 32) - | ((uint64)p[12] << 24) - | ((uint64)p[13] << 16) - | ((uint64)p[14] << 8) - | p[15]); - PG_RETURN_IP6_P(ip); - } - - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid INET value for conversion to IP6"))); - PG_RETURN_NULL(); -} - -PG_FUNCTION_INFO_V1(ip6_cast_to_cidr); -Datum -ip6_cast_to_cidr(PG_FUNCTION_ARGS) -{ - IP6 *ip = PG_GETARG_IP6_P(0); - inet *res = palloc0(VARHDRSZ + sizeof(inet_struct)); - inet_struct *in; - - SET_VARSIZE(res, VARHDRSZ + offsetof(inet_struct, ipaddr) + 16); - - in = ((inet_struct *)VARDATA(res)); - in->bits = 128; - in->family = PGSQL_AF_INET6; - { - unsigned char *p = in->ipaddr; - p[0] = (ip->bits[0] >> 56); - p[1] = (ip->bits[0] >> 48); - p[2] = (ip->bits[0] >> 40); - p[3] = (ip->bits[0] >> 32); - p[4] = (ip->bits[0] >> 24); - p[5] = (ip->bits[0] >> 16); - p[6] = (ip->bits[0] >> 8); - p[7] = (ip->bits[0]); - p[8] = (ip->bits[1] >> 56); - p[9] = (ip->bits[1] >> 48); - p[10] = (ip->bits[1] >> 40); - p[11] = (ip->bits[1] >> 32); - p[12] = (ip->bits[1] >> 24); - p[13] = (ip->bits[1] >> 16); - p[14] = (ip->bits[1] >> 8); - p[15] = (ip->bits[1]); - } - - PG_RETURN_INET_P(res); -} - - -PG_FUNCTION_INFO_V1(ip6_cast_to_numeric); -Datum -ip6_cast_to_numeric(PG_FUNCTION_ARGS) -{ - IP6 *ip = PG_GETARG_IP6_P(0); - Datum res,tmp,mul; - static int64 mul_val = ((int64)1 << 56); - int64 tmp_val; - - mul = DirectFunctionCall1(int8_numeric,Int64GetDatumFast(mul_val)); - tmp_val = (ip->bits[0] >> 48); - res = DirectFunctionCall1(int8_numeric,Int64GetDatumFast(tmp_val)); - tmp_val = ((ip->bits[0] & (uint64)(0xFFFFFFFFFFFFULL)) << 8) | (ip->bits[1] >> 56); - tmp = DirectFunctionCall1(int8_numeric,Int64GetDatumFast(tmp_val)); - res = DirectFunctionCall2(numeric_mul,res,mul); - res = DirectFunctionCall2(numeric_add,res,tmp); - tmp_val = (ip->bits[1] & (uint64)(0xFFFFFFFFFFFFFFULL)); - tmp = DirectFunctionCall1(int8_numeric,Int64GetDatumFast(tmp_val)); - res = DirectFunctionCall2(numeric_mul,res,mul); - res = DirectFunctionCall2(numeric_add,res,tmp); - - PG_RETURN_DATUM(res); -} - -PG_FUNCTION_INFO_V1(ip6_cast_from_numeric); -Datum -ip6_cast_from_numeric(PG_FUNCTION_ARGS) -{ - Datum val = NumericGetDatum(PG_GETARG_NUMERIC(0)); - Datum rem,tmp,div,mul; - static int64 mul_val = ((int64)1 << 56); - uint64 tmp_val; - IP6 *res; - - tmp = DirectFunctionCall1(numeric_floor,DirectFunctionCall1(numeric_abs,val)); - - if (!DatumGetBool(DirectFunctionCall2(numeric_eq,tmp,val))) - { - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid numeric value for conversion to IP6"))); - } - - res = palloc(sizeof(IP6)); - - /* we use div/mul here rather than mod because numeric_mod is implemented as - * a div/mul/subtract in any case, so we save a division step by doing the - * mul/subtract ourselves - */ - - mul = DirectFunctionCall1(int8_numeric,Int64GetDatumFast(mul_val)); - div = DirectFunctionCall2(numeric_div_trunc,val,mul); - tmp = DirectFunctionCall2(numeric_mul,div,mul); - rem = DirectFunctionCall2(numeric_sub,val,tmp); - res->bits[1] = (uint64)DatumGetInt64(DirectFunctionCall1(numeric_int8,rem)); - val = div; - div = DirectFunctionCall2(numeric_div_trunc,val,mul); - tmp = DirectFunctionCall2(numeric_mul,div,mul); - rem = DirectFunctionCall2(numeric_sub,val,tmp); - tmp_val = (uint64)DatumGetInt64(DirectFunctionCall1(numeric_int8,rem)); - res->bits[1] |= ((tmp_val & 0xFF) << 56); - res->bits[0] = (tmp_val >> 8); - if (!DatumGetBool(DirectFunctionCall2(numeric_gt,div,mul))) - { - tmp_val = (uint64)DatumGetInt64(DirectFunctionCall1(numeric_int8,div)); - if (tmp_val <= (uint64)0xFFFFU) - { - res->bits[0] |= (tmp_val << 48); - PG_RETURN_IP6_P(res); - } - } - - ereport(ERROR, - (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), - errmsg("numeric value too large for conversion to IP6"))); - PG_RETURN_NULL(); -} - - -PG_FUNCTION_INFO_V1(ip6_netmask); -Datum -ip6_netmask(PG_FUNCTION_ARGS) -{ - int pfxlen = PG_GETARG_INT32(0); - IP6 *mask; - - if (pfxlen < 0 || pfxlen > 128) - { - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("prefix length out of range"))); - } - - mask = palloc(sizeof(IP6)); - mask->bits[0] = netmask6_hi(pfxlen); - mask->bits[1] = netmask6_lo(pfxlen); - PG_RETURN_IP6_P(mask); -} - -PG_FUNCTION_INFO_V1(ip6_net_lower); -Datum -ip6_net_lower(PG_FUNCTION_ARGS) -{ - IP6 *ip = PG_GETARG_IP6_P(0); - int pfxlen = PG_GETARG_INT32(1); - IP6 *res; - - if (pfxlen < 0 || pfxlen > 128) - { - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("prefix length out of range"))); - } - - res = palloc(sizeof(IP6)); - res->bits[0] = ip->bits[0] & netmask6_hi(pfxlen); - res->bits[1] = ip->bits[1] & netmask6_lo(pfxlen); - - PG_RETURN_IP6_P(res); -} - -PG_FUNCTION_INFO_V1(ip6_net_upper); -Datum -ip6_net_upper(PG_FUNCTION_ARGS) -{ - IP6 *ip = PG_GETARG_IP6_P(0); - int pfxlen = PG_GETARG_INT32(1); - IP6 *res; - - if (pfxlen < 0 || pfxlen > 128) - { - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("prefix length out of range"))); - } - - res = palloc(sizeof(IP6)); - res->bits[0] = ip->bits[0] | hostmask6_hi(pfxlen); - res->bits[1] = ip->bits[1] | hostmask6_lo(pfxlen); - - PG_RETURN_IP6_P(res); -} - -PG_FUNCTION_INFO_V1(ip6_plus_int); -Datum -ip6_plus_int(PG_FUNCTION_ARGS) -{ - IP6 *ip = PG_GETARG_IP6_P(0); - int addend = PG_GETARG_INT32(1); - IP6 *result = palloc(sizeof(IP6)); - - if (addend >= 0) - { - result->bits[1] = ip->bits[1] + addend; - result->bits[0] = ip->bits[0] + (result->bits[1] < ip->bits[1]); - } - else - { - result->bits[1] = ip->bits[1] - (uint64)(-addend); - result->bits[0] = ip->bits[0] - (result->bits[1] > ip->bits[1]); - } - - if ((addend < 0) != ip6_lessthan(result,ip)) - { - ereport(ERROR, - (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), - errmsg("ip address out of range"))); - } - - PG_RETURN_IP6_P(result); -} - -PG_FUNCTION_INFO_V1(ip6_plus_bigint); -Datum -ip6_plus_bigint(PG_FUNCTION_ARGS) -{ - IP6 *ip = PG_GETARG_IP6_P(0); - int64 addend = PG_GETARG_INT64(1); - IP6 *result = palloc(sizeof(IP6)); - - if (addend >= 0) - { - result->bits[1] = ip->bits[1] + addend; - result->bits[0] = ip->bits[0] + (result->bits[1] < ip->bits[1]); - } - else - { - result->bits[1] = ip->bits[1] - (uint64)(-addend); - result->bits[0] = ip->bits[0] - (result->bits[1] > ip->bits[1]); - } - - if ((addend < 0) != ip6_lessthan(result,ip)) - { - ereport(ERROR, - (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), - errmsg("ip address out of range"))); - } - - PG_RETURN_IP6_P(result); -} - -PG_FUNCTION_INFO_V1(ip6_plus_numeric); -Datum -ip6_plus_numeric(PG_FUNCTION_ARGS) -{ - IP6 *ip = PG_GETARG_IP6_P(0); - Datum addend_num = NumericGetDatum(PG_GETARG_NUMERIC(1)); - Datum addend_abs; - IP6 *addend; - IP6 *result = palloc(sizeof(IP6)); - bool is_negative; - - addend_abs = DirectFunctionCall1(numeric_abs,addend_num); - addend = DatumGetIP6P(DirectFunctionCall1(ip6_cast_from_numeric,addend_abs)); - - if (DatumGetBool(DirectFunctionCall2(numeric_eq,addend_num,addend_abs))) - { - is_negative = false; - result->bits[1] = ip->bits[1] + addend->bits[1]; - result->bits[0] = ip->bits[0] + addend->bits[0] + (result->bits[1] < ip->bits[1]); - } - else - { - is_negative = true; - result->bits[1] = ip->bits[1] - addend->bits[1]; - result->bits[0] = ip->bits[0] - addend->bits[0] - (result->bits[1] > ip->bits[1]); - } - - if (is_negative != ip6_lessthan(result,ip)) - { - ereport(ERROR, - (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), - errmsg("ip address out of range"))); - } - - PG_RETURN_IP6_P(result); -} - -PG_FUNCTION_INFO_V1(ip6_minus_int); -Datum -ip6_minus_int(PG_FUNCTION_ARGS) -{ - IP6 *ip = PG_GETARG_IP6_P(0); - int subtrahend = PG_GETARG_INT32(1); - IP6 *result = palloc(sizeof(IP6)); - - ip6_sub_int(ip, subtrahend, result); - - if ((subtrahend > 0) != ip6_lessthan(result,ip)) - { - ereport(ERROR, - (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), - errmsg("ip address out of range"))); - } - - PG_RETURN_IP6_P(result); -} - -PG_FUNCTION_INFO_V1(ip6_minus_bigint); -Datum -ip6_minus_bigint(PG_FUNCTION_ARGS) -{ - IP6 *ip = PG_GETARG_IP6_P(0); - int64 subtrahend = PG_GETARG_INT64(1); - IP6 *result = palloc(sizeof(IP6)); - - if (subtrahend >= 0) - { - result->bits[1] = ip->bits[1] - (uint64)subtrahend; - result->bits[0] = ip->bits[0] - (result->bits[1] > ip->bits[1]); - } - else - { - result->bits[1] = ip->bits[1] + (uint64)(-subtrahend); - result->bits[0] = ip->bits[0] + (result->bits[1] < ip->bits[1]); - } - - if ((subtrahend > 0) != ip6_lessthan(result,ip)) - { - ereport(ERROR, - (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), - errmsg("ip address out of range"))); - } - - PG_RETURN_IP6_P(result); -} - -PG_FUNCTION_INFO_V1(ip6_minus_numeric); -Datum -ip6_minus_numeric(PG_FUNCTION_ARGS) -{ - Datum ip = PG_GETARG_DATUM(0); - Datum subtrahend = PG_GETARG_DATUM(1); - - subtrahend = DirectFunctionCall1(numeric_uminus,subtrahend); - return DirectFunctionCall2(ip6_plus_numeric,ip,subtrahend); -} - -PG_FUNCTION_INFO_V1(ip6_minus_ip6); -Datum -ip6_minus_ip6(PG_FUNCTION_ARGS) -{ - Datum minuend = PG_GETARG_DATUM(0); - Datum subtrahend = PG_GETARG_DATUM(1); - Datum res; - - res = DirectFunctionCall2(numeric_sub, - DirectFunctionCall1(ip6_cast_to_numeric,minuend), - DirectFunctionCall1(ip6_cast_to_numeric,subtrahend)); - - PG_RETURN_DATUM(res); -} - -PG_FUNCTION_INFO_V1(ip6_and); -Datum -ip6_and(PG_FUNCTION_ARGS) -{ - IP6 *a = PG_GETARG_IP6_P(0); - IP6 *b = PG_GETARG_IP6_P(1); - IP6 *res = palloc(sizeof(IP6)); - - res->bits[0] = a->bits[0] & b->bits[0]; - res->bits[1] = a->bits[1] & b->bits[1]; - - PG_RETURN_IP6_P(res); -} - -PG_FUNCTION_INFO_V1(ip6_or); -Datum -ip6_or(PG_FUNCTION_ARGS) -{ - IP6 *a = PG_GETARG_IP6_P(0); - IP6 *b = PG_GETARG_IP6_P(1); - IP6 *res = palloc(sizeof(IP6)); - - res->bits[0] = a->bits[0] | b->bits[0]; - res->bits[1] = a->bits[1] | b->bits[1]; - - PG_RETURN_IP6_P(res); -} - -PG_FUNCTION_INFO_V1(ip6_xor); -Datum -ip6_xor(PG_FUNCTION_ARGS) -{ - IP6 *a = PG_GETARG_IP6_P(0); - IP6 *b = PG_GETARG_IP6_P(1); - IP6 *res = palloc(sizeof(IP6)); - - res->bits[0] = a->bits[0] ^ b->bits[0]; - res->bits[1] = a->bits[1] ^ b->bits[1]; - - PG_RETURN_IP6_P(res); -} - -PG_FUNCTION_INFO_V1(ip6_not); -Datum -ip6_not(PG_FUNCTION_ARGS) -{ - IP6 *a = PG_GETARG_IP6_P(0); - IP6 *res = palloc(sizeof(IP6)); - - res->bits[0] = ~a->bits[0]; - res->bits[1] = ~a->bits[1]; - - PG_RETURN_IP6_P(res); -} - - -/*---- ip6r ----*/ - -PG_FUNCTION_INFO_V1(ip6r_in); -Datum -ip6r_in(PG_FUNCTION_ARGS) -{ - char *str = PG_GETARG_CSTRING(0); - IP6R ipr; - - if (ip6r_from_str(str, &ipr)) - { - IP6R *res = palloc(sizeof(IP6R)); - *res = ipr; - PG_RETURN_IP6R_P(res); - } - - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid IP6R value: \"%s\"", str))); - PG_RETURN_NULL(); -} - -PG_FUNCTION_INFO_V1(ip6r_out); -Datum -ip6r_out(PG_FUNCTION_ARGS) -{ - IP6R *ipr = PG_GETARG_IP6R_P(0); - char *out = palloc(IP6R_STRING_MAX); - ip6r_to_str(ipr, out, IP6R_STRING_MAX); - PG_RETURN_CSTRING(out); -} - -PG_FUNCTION_INFO_V1(ip6r_recv); -Datum -ip6r_recv(PG_FUNCTION_ARGS) -{ - StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); - IP6R *ipr = palloc(sizeof(IP6R)); - - ipr->lower.bits[0] = pq_getmsgint64(buf); - ipr->lower.bits[1] = pq_getmsgint64(buf); - ipr->upper.bits[0] = pq_getmsgint64(buf); - ipr->upper.bits[1] = pq_getmsgint64(buf); - - PG_RETURN_IP6R_P(ipr); -} - -PG_FUNCTION_INFO_V1(ip6r_send); -Datum -ip6r_send(PG_FUNCTION_ARGS) -{ - IP6R *ipr = PG_GETARG_IP6R_P(0); - StringInfoData buf; - - pq_begintypsend(&buf); - pq_sendint64(&buf, ipr->lower.bits[0]); - pq_sendint64(&buf, ipr->lower.bits[1]); - pq_sendint64(&buf, ipr->upper.bits[0]); - pq_sendint64(&buf, ipr->upper.bits[1]); - PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); -} - -PG_FUNCTION_INFO_V1(ip6rhash); -Datum -ip6rhash(PG_FUNCTION_ARGS) -{ - IP6R *arg1 = PG_GETARG_IP6R_P(0); - - return hash_any((unsigned char *)arg1, sizeof(IP6R)); -} - -PG_FUNCTION_INFO_V1(ip6r_cast_to_text); -Datum -ip6r_cast_to_text(PG_FUNCTION_ARGS) -{ - IP6R *ipr = PG_GETARG_IP6R_P(0); - text *out = make_text(IP6R_STRING_MAX); - set_text_len(out, ip6r_to_str(ipr, VARDATA(out), IP6R_STRING_MAX)); - PG_RETURN_TEXT_P(out); -} - -PG_FUNCTION_INFO_V1(ip6r_cast_from_text); -Datum -ip6r_cast_from_text(PG_FUNCTION_ARGS) -{ - text *txt = PG_GETARG_TEXT_PP(0); - int tlen = VARSIZE_ANY_EXHDR(txt); - char buf[IP6R_STRING_MAX]; - - if (tlen < sizeof(buf)) - { - IP6R ipr; - - memcpy(buf, VARDATA_ANY(txt), tlen); - buf[tlen] = 0; - if (ip6r_from_str(buf, &ipr)) - { - IP6R *res = palloc(sizeof(IP6R)); - *res = ipr; - PG_RETURN_IP6R_P(res); - } - } - - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid IP6R value in text"))); - PG_RETURN_NULL(); -} - -PG_FUNCTION_INFO_V1(ip6r_cast_from_cidr); -Datum -ip6r_cast_from_cidr(PG_FUNCTION_ARGS) -{ - inet *inetptr = PG_GETARG_INET_P(0); - inet_struct *in = INET_STRUCT_DATA(inetptr); - - if (in->family == PGSQL_AF_INET6) - { - unsigned char *p = in->ipaddr; - IP6 ip; - IP6R ipr; - ip.bits[0] = (((uint64)p[0] << 56) - | ((uint64)p[1] << 48) - | ((uint64)p[2] << 40) - | ((uint64)p[3] << 32) - | ((uint64)p[4] << 24) - | ((uint64)p[5] << 16) - | ((uint64)p[6] << 8) - | p[7]); - ip.bits[1] = (((uint64)p[8] << 56) - | ((uint64)p[9] << 48) - | ((uint64)p[10] << 40) - | ((uint64)p[11] << 32) - | ((uint64)p[12] << 24) - | ((uint64)p[13] << 16) - | ((uint64)p[14] << 8) - | p[15]); - if (ip6r_from_cidr(&ip, in->bits, &ipr)) - { - IP6R *res = palloc(sizeof(IP6R)); - *res = ipr; - PG_RETURN_IP6R_P(res); - } - } - - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid CIDR value for conversion to IP6R"))); - PG_RETURN_NULL(); -} - -PG_FUNCTION_INFO_V1(ip6r_cast_to_cidr); -Datum -ip6r_cast_to_cidr(PG_FUNCTION_ARGS) -{ - IP6R *ipr = PG_GETARG_IP6R_P(0); - IP6 *ip = &ipr->lower; - inet *res; - inet_struct *in; - unsigned bits = masklen6(ip, &ipr->upper); - - if (bits > 128) - PG_RETURN_NULL(); - - res = palloc0(VARHDRSZ + sizeof(inet_struct)); - SET_VARSIZE(res, VARHDRSZ + offsetof(inet_struct, ipaddr) + 16); - - in = ((inet_struct *)VARDATA(res)); - in->bits = bits; - in->family = PGSQL_AF_INET6; - { - unsigned char *p = in->ipaddr; - p[0] = (ip->bits[0] >> 56); - p[1] = (ip->bits[0] >> 48); - p[2] = (ip->bits[0] >> 40); - p[3] = (ip->bits[0] >> 32); - p[4] = (ip->bits[0] >> 24); - p[5] = (ip->bits[0] >> 16); - p[6] = (ip->bits[0] >> 8); - p[7] = (ip->bits[0]); - p[8] = (ip->bits[1] >> 56); - p[9] = (ip->bits[1] >> 48); - p[10] = (ip->bits[1] >> 40); - p[11] = (ip->bits[1] >> 32); - p[12] = (ip->bits[1] >> 24); - p[13] = (ip->bits[1] >> 16); - p[14] = (ip->bits[1] >> 8); - p[15] = (ip->bits[1]); - } - - PG_RETURN_INET_P(res); -} - -PG_FUNCTION_INFO_V1(ip6r_cast_from_ip6); -Datum -ip6r_cast_from_ip6(PG_FUNCTION_ARGS) -{ - IP6 *ip = PG_GETARG_IP6_P(0); - IP6R *res = palloc(sizeof(IP6R)); - if (ip6r_from_inet(ip, 128, res)) - { - PG_RETURN_IP6R_P(res); - } - - pfree(res); - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid IP6 value for conversion to IP6R (shouldn't be possible)"))); - PG_RETURN_NULL(); -} - -PG_FUNCTION_INFO_V1(ip6r_from_ip6s); -Datum -ip6r_from_ip6s(PG_FUNCTION_ARGS) -{ - IP6 *a = PG_GETARG_IP6_P(0); - IP6 *b = PG_GETARG_IP6_P(1); - IP6R *res = palloc(sizeof(IP6R)); - if (ip6_lessthan(a,b)) - res->lower = *a, res->upper = *b; - else - res->lower = *b, res->upper = *a; - PG_RETURN_IP6R_P(res); -} - -PG_FUNCTION_INFO_V1(ip6r_net_prefix); -Datum -ip6r_net_prefix(PG_FUNCTION_ARGS) -{ - IP6 *ip = PG_GETARG_IP6_P(0); - int pfxlen = PG_GETARG_INT32(1); - - if (pfxlen < 0 || pfxlen > 128) - { - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("prefix length out of range"))); - } - - { - IP6R *res = palloc(sizeof(IP6R)); - ip6r_from_inet(ip, (unsigned)pfxlen, res); - PG_RETURN_IP6R_P(res); - } -} - -PG_FUNCTION_INFO_V1(ip6r_net_mask); -Datum -ip6r_net_mask(PG_FUNCTION_ARGS) -{ - IP6 *ip = PG_GETARG_IP6_P(0); - IP6 *mask = PG_GETARG_IP6_P(1); - - if (!ip6_valid_netmask(mask->bits[0], mask->bits[1])) - { - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid netmask"))); - } - - { - IP6R *res = palloc(sizeof(IP6R)); - - res->lower.bits[0] = ip->bits[0] & mask->bits[0]; - res->lower.bits[1] = ip->bits[1] & mask->bits[1]; - res->upper.bits[0] = ip->bits[0] | ~(mask->bits[0]); - res->upper.bits[1] = ip->bits[1] | ~(mask->bits[1]); - - PG_RETURN_IP6R_P(res); - } -} - - -PG_FUNCTION_INFO_V1(ip6r_lower); -Datum -ip6r_lower(PG_FUNCTION_ARGS) -{ - IP6R *ipr = PG_GETARG_IP6R_P(0); - IP6 *res = palloc(sizeof(IP6)); - *res = ipr->lower; - PG_RETURN_IP6_P(res); -} - -PG_FUNCTION_INFO_V1(ip6r_upper); -Datum -ip6r_upper(PG_FUNCTION_ARGS) -{ - IP6R *ipr = PG_GETARG_IP6R_P(0); - IP6 *res = palloc(sizeof(IP6)); - *res = ipr->upper; - PG_RETURN_IP6_P(res); -} - -PG_FUNCTION_INFO_V1(ip6r_is_cidr); -Datum -ip6r_is_cidr(PG_FUNCTION_ARGS) -{ - IP6R *ipr = PG_GETARG_IP6R_P(0); - PG_RETURN_BOOL( (masklen6(&ipr->lower,&ipr->upper) <= 128U) ); -} - -PG_FUNCTION_INFO_V1(ip6_lt); -Datum -ip6_lt(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip6_lessthan(PG_GETARG_IP6_P(0), PG_GETARG_IP6_P(1)) ); -} - -PG_FUNCTION_INFO_V1(ip6_le); -Datum -ip6_le(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip6_less_eq(PG_GETARG_IP6_P(0), PG_GETARG_IP6_P(1)) ); -} - -PG_FUNCTION_INFO_V1(ip6_gt); -Datum -ip6_gt(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip6_lessthan(PG_GETARG_IP6_P(1), PG_GETARG_IP6_P(0)) ); -} - -PG_FUNCTION_INFO_V1(ip6_ge); -Datum -ip6_ge(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip6_less_eq(PG_GETARG_IP6_P(1), PG_GETARG_IP6_P(0)) ); -} - -PG_FUNCTION_INFO_V1(ip6_eq); -Datum -ip6_eq(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip6_equal(PG_GETARG_IP6_P(0), PG_GETARG_IP6_P(1)) ); -} - -PG_FUNCTION_INFO_V1(ip6_neq); -Datum -ip6_neq(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( !ip6_equal(PG_GETARG_IP6_P(0), PG_GETARG_IP6_P(1)) ); -} - -PG_FUNCTION_INFO_V1(ip6r_lt); -Datum -ip6r_lt(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip6r_lessthan(PG_GETARG_IP6R_P(0), PG_GETARG_IP6R_P(1)) ); -} - -PG_FUNCTION_INFO_V1(ip6r_le); -Datum -ip6r_le(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip6r_less_eq(PG_GETARG_IP6R_P(0), PG_GETARG_IP6R_P(1)) ); -} - -PG_FUNCTION_INFO_V1(ip6r_gt); -Datum -ip6r_gt(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip6r_lessthan(PG_GETARG_IP6R_P(1), PG_GETARG_IP6R_P(0)) ); -} - -PG_FUNCTION_INFO_V1(ip6r_ge); -Datum -ip6r_ge(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip6r_less_eq(PG_GETARG_IP6R_P(1), PG_GETARG_IP6R_P(0)) ); -} - -PG_FUNCTION_INFO_V1(ip6r_eq); -Datum -ip6r_eq(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip6r_equal(PG_GETARG_IP6R_P(0), PG_GETARG_IP6R_P(1)) ); -} - -PG_FUNCTION_INFO_V1(ip6r_neq); -Datum -ip6r_neq(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( !ip6r_equal(PG_GETARG_IP6R_P(0), PG_GETARG_IP6R_P(1)) ); -} - -PG_FUNCTION_INFO_V1(ip6r_overlaps); -Datum -ip6r_overlaps(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip6r_overlaps_internal(PG_GETARG_IP6R_P(0), - PG_GETARG_IP6R_P(1)) ); -} - -PG_FUNCTION_INFO_V1(ip6r_contains); -Datum -ip6r_contains(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip6r_contains_internal(PG_GETARG_IP6R_P(0), - PG_GETARG_IP6R_P(1), - TRUE) ); -} - -PG_FUNCTION_INFO_V1(ip6r_contains_strict); -Datum -ip6r_contains_strict(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip6r_contains_internal(PG_GETARG_IP6R_P(0), - PG_GETARG_IP6R_P(1), - FALSE) ); -} - -PG_FUNCTION_INFO_V1(ip6r_contained_by); -Datum -ip6r_contained_by(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip6r_contains_internal(PG_GETARG_IP6R_P(1), - PG_GETARG_IP6R_P(0), - TRUE) ); -} - -PG_FUNCTION_INFO_V1(ip6r_contained_by_strict); -Datum -ip6r_contained_by_strict(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip6r_contains_internal(PG_GETARG_IP6R_P(1), - PG_GETARG_IP6R_P(0), - FALSE) ); -} - -PG_FUNCTION_INFO_V1(ip6_contains); -Datum -ip6_contains(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip6_contains_internal(PG_GETARG_IP6R_P(0), PG_GETARG_IP6_P(1)) ); -} - -PG_FUNCTION_INFO_V1(ip6_contained_by); -Datum -ip6_contained_by(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( ip6_contains_internal(PG_GETARG_IP6R_P(1), PG_GETARG_IP6_P(0)) ); -} - -PG_FUNCTION_INFO_V1(ip6r_union); -Datum -ip6r_union(PG_FUNCTION_ARGS) -{ - IP6R *res = palloc(sizeof(IP6R)); - ip6r_union_internal(PG_GETARG_IP6R_P(0), PG_GETARG_IP6R_P(1), res); - PG_RETURN_IP6R_P(res); -} - -PG_FUNCTION_INFO_V1(ip6r_inter); -Datum -ip6r_inter(PG_FUNCTION_ARGS) -{ - IP6R *res = palloc(sizeof(IP6R)); - if (ip6r_inter_internal(PG_GETARG_IP6R_P(0), PG_GETARG_IP6R_P(1), res)) - { - PG_RETURN_IP6R_P(res); - } - pfree(res); - PG_RETURN_NULL(); -} - -PG_FUNCTION_INFO_V1(ip6r_size); -Datum -ip6r_size(PG_FUNCTION_ARGS) -{ - double size = ip6r_metric(PG_GETARG_IP6R_P(0)); - PG_RETURN_FLOAT8(size); -} - -PG_FUNCTION_INFO_V1(ip6r_size_exact); -Datum -ip6r_size_exact(PG_FUNCTION_ARGS) -{ - IP6R *ipr = PG_GETARG_IP6R_P(0); - Datum l = DirectFunctionCall1(ip6_cast_to_numeric, IP6PGetDatum(&ipr->lower)); - Datum u = DirectFunctionCall1(ip6_cast_to_numeric, IP6PGetDatum(&ipr->upper)); - Datum d = DirectFunctionCall2(numeric_sub, u, l); - Datum s = DirectFunctionCall1(numeric_inc, d); - PG_RETURN_DATUM(s); -} - -PG_FUNCTION_INFO_V1(ip6r_prefixlen); -Datum -ip6r_prefixlen(PG_FUNCTION_ARGS) -{ - IP6R *ipr = PG_GETARG_IP6R_P(0); - unsigned len = masklen6(&ipr->lower, &ipr->upper); - if (len <= 128) - PG_RETURN_INT32((int32) len); - PG_RETURN_NULL(); -} - - -/***************************************************************************** - * Btree functions - *****************************************************************************/ - -PG_FUNCTION_INFO_V1(ip6r_cmp); -Datum -ip6r_cmp(PG_FUNCTION_ARGS) -{ - IP6R *a = PG_GETARG_IP6R_P(0); - IP6R *b = PG_GETARG_IP6R_P(1); - if (ip6r_lessthan(a,b)) - PG_RETURN_INT32(-1); - if (ip6r_equal(a,b)) - PG_RETURN_INT32(0); - PG_RETURN_INT32(1); -} - -PG_FUNCTION_INFO_V1(ip6_cmp); -Datum -ip6_cmp(PG_FUNCTION_ARGS) -{ - IP6 *a = PG_GETARG_IP6_P(0); - IP6 *b = PG_GETARG_IP6_P(1); - PG_RETURN_INT32(ip6_compare(a,b)); -} - - -/***************************************************************************** - * GiST functions - *****************************************************************************/ - -/* -** GiST support methods -*/ - -Datum gip6r_consistent(PG_FUNCTION_ARGS); -Datum gip6r_compress(PG_FUNCTION_ARGS); -Datum gip6r_decompress(PG_FUNCTION_ARGS); -Datum gip6r_penalty(PG_FUNCTION_ARGS); -Datum gip6r_picksplit(PG_FUNCTION_ARGS); -Datum gip6r_union(PG_FUNCTION_ARGS); -Datum gip6r_same(PG_FUNCTION_ARGS); -Datum gip6r_fetch(PG_FUNCTION_ARGS); - -static bool gip6r_leaf_consistent(IP6R * key, IP6R * query, StrategyNumber strategy); -static bool gip6r_internal_consistent(IP6R * key, IP6R * query, StrategyNumber strategy); - -/* -** The GiST Consistent method for IP ranges -** Should return false if for all data items x below entry, -** the predicate x op query == FALSE, where op is the oper -** corresponding to strategy in the pg_amop table. -*/ -PG_FUNCTION_INFO_V1(gip6r_consistent); -Datum -gip6r_consistent(PG_FUNCTION_ARGS) -{ - GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); - IP6R *query = (IP6R *) PG_GETARG_POINTER(1); - StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); - bool *recheck = (bool *) PG_GETARG_POINTER(4); - IP6R *key = (IP6R *) DatumGetPointer(entry->key); - bool retval; - - /* recheck is never needed with this type */ - if (recheck) - *recheck = false; - - /* - * * if entry is not leaf, use gip6r_internal_consistent, * else use - * gip6r_leaf_consistent - */ - if (GIST_LEAF(entry)) - retval = gip6r_leaf_consistent(key, query, strategy); - else - retval = gip6r_internal_consistent(key, query, strategy); - - PG_RETURN_BOOL(retval); -} - -/* -** The GiST Union method for IP ranges -** returns the minimal bounding IP4R that encloses all the entries in entryvec -*/ -PG_FUNCTION_INFO_V1(gip6r_union); -Datum -gip6r_union(PG_FUNCTION_ARGS) -{ - GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0); - int *sizep = (int *) PG_GETARG_POINTER(1); - GISTENTRY *ent = GISTENTRYVEC(entryvec); - - int numranges, i; - IP6R *out = palloc(sizeof(IP6R)); - IP6R *tmp; - -#ifdef GIST_DEBUG - fprintf(stderr, "union\n"); -#endif - - numranges = GISTENTRYCOUNT(entryvec); - tmp = (IP6R *) DatumGetPointer(ent[0].key); - *sizep = sizeof(IP6R); - *out = *tmp; - - for (i = 1; i < numranges; i++) - { - tmp = (IP6R *) DatumGetPointer(ent[i].key); - if (ip6_lessthan(&tmp->lower,&out->lower)) - out->lower = tmp->lower; - if (ip6_lessthan(&out->upper,&tmp->upper)) - out->upper = tmp->upper; - } - - PG_RETURN_IP6R_P(out); -} - -/* -** GiST Compress and Decompress methods for IP ranges -** do not do anything. -*/ -PG_FUNCTION_INFO_V1(gip6r_compress); -Datum -gip6r_compress(PG_FUNCTION_ARGS) -{ - PG_RETURN_POINTER(PG_GETARG_POINTER(0)); -} - -PG_FUNCTION_INFO_V1(gip6r_decompress); -Datum -gip6r_decompress(PG_FUNCTION_ARGS) -{ - PG_RETURN_POINTER(PG_GETARG_POINTER(0)); -} - -PG_FUNCTION_INFO_V1(gip6r_fetch); -Datum -gip6r_fetch(PG_FUNCTION_ARGS) -{ - PG_RETURN_POINTER(PG_GETARG_POINTER(0)); -} - -/* -** The GiST Penalty method for IP ranges -** As in the R-tree paper, we use change in area as our penalty metric -*/ -PG_FUNCTION_INFO_V1(gip6r_penalty); -Datum -gip6r_penalty(PG_FUNCTION_ARGS) -{ - GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0); - GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1); - float *result = (float *) PG_GETARG_POINTER(2); - IP6R *key = (IP6R *) DatumGetPointer(origentry->key); - IP6R *newkey = (IP6R *) DatumGetPointer(newentry->key); - IP6R ud; - double tmp = 0.0; - - /* rather than subtract the sizes, which might lose due to rounding errors, - * we calculate the actual number of addresses added to the range. - */ - - if (ip6_lessthan(&newkey->lower,&key->lower)) - { - ud.lower = newkey->lower; - ud.upper = key->lower; - ip6_sub_int(&ud.upper,1,&ud.upper); - tmp = ip6r_metric(&ud); - } - if (ip6_lessthan(&key->upper,&newkey->upper)) - { - ud.lower = key->upper; - ud.upper = newkey->upper; - ip6_sub_int(&ud.upper,1,&ud.upper); - tmp += ip6r_metric(&ud); - } - - /* - * we want to scale the result a bit. For one thing, the gist code implicitly - * assigns a penalty of 1e10 for a union of null and non-null values, and we - * want to keep our values less than that. For another, the penalty is sometimes - * summed across columns of a multi-column index, and we don't want our huge - * metrics (>2^80) to completely swamp anything else. - * - * So, we scale as the fourth power of the log2 of the computed penalty, which - * gives us a range 0 - 268435456. - */ - - *result = (float) pow(log(tmp+1) / log(2), 4); - -#ifdef GIST_DEBUG - fprintf(stderr, "penalty\n"); - fprintf(stderr, "\t%g\n", *result); -#endif - - PG_RETURN_POINTER(result); -} - - -/* Helper functions for picksplit. We might need to sort a list of - * ranges by size; these are for that. - */ - -struct gip6r_sort -{ - IP6R *key; - OffsetNumber pos; -}; - -static int -gip6r_sort_compare(const void *a, const void *b) -{ - double sa = ip6r_metric(((struct gip6r_sort *)a)->key); - double sb = ip6r_metric(((struct gip6r_sort *)b)->key); - return (sa > sb) ? 1 : ((sa == sb) ? 0 : -1); -} - -/* -** The GiST PickSplit method for IP ranges -** This is a linear-time algorithm based on a left/right split, -** based on the box functions in rtree_gist simplified to one -** dimension -*/ -PG_FUNCTION_INFO_V1(gip6r_picksplit); -Datum -gip6r_picksplit(PG_FUNCTION_ARGS) -{ - GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0); - GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1); - GISTENTRY *ent = GISTENTRYVEC(entryvec); - OffsetNumber i; - int nbytes; - OffsetNumber maxoff; - OffsetNumber *listL; - OffsetNumber *listR; - bool allisequal = true; - IP6R pageunion; - IP6R *cur; - IP6R *unionL; - IP6R *unionR; - int posL = 0; - int posR = 0; - - posL = posR = 0; - maxoff = GISTENTRYCOUNT(entryvec) - 1; - - cur = (IP6R *) DatumGetPointer(ent[FirstOffsetNumber].key); - pageunion = *cur; - - /* find MBR */ - for (i = OffsetNumberNext(FirstOffsetNumber); i <= maxoff; i = OffsetNumberNext(i)) - { - cur = (IP6R *) DatumGetPointer(ent[i].key); - if (allisequal == true && !ip6r_equal(&pageunion,cur)) - allisequal = false; - - if (ip6_lessthan(&cur->lower,&pageunion.lower)) - pageunion.lower = cur->lower; - if (ip6_lessthan(&pageunion.upper,&cur->upper)) - pageunion.upper = cur->upper; - } - - nbytes = (maxoff + 2) * sizeof(OffsetNumber); - listL = (OffsetNumber *) palloc(nbytes); - listR = (OffsetNumber *) palloc(nbytes); - unionL = palloc(sizeof(IP6R)); - unionR = palloc(sizeof(IP6R)); - v->spl_ldatum = PointerGetDatum(unionL); - v->spl_rdatum = PointerGetDatum(unionR); - v->spl_left = listL; - v->spl_right = listR; - - if (allisequal) - { - cur = (IP6R *) DatumGetPointer(ent[OffsetNumberNext(FirstOffsetNumber)].key); - if (ip6r_equal(cur, &pageunion)) - { - OffsetNumber split_at = FirstOffsetNumber + (maxoff - FirstOffsetNumber + 1)/2; - v->spl_nleft = v->spl_nright = 0; - *unionL = pageunion; - *unionR = pageunion; - - for (i = FirstOffsetNumber; i < split_at; i = OffsetNumberNext(i)) - v->spl_left[v->spl_nleft++] = i; - for (; i <= maxoff; i = OffsetNumberNext(i)) - v->spl_right[v->spl_nright++] = i; - - PG_RETURN_POINTER(v); - } - } - -#define ADDLIST( list_, u_, pos_, num_ ) do { \ - if ( pos_ ) { \ - if ( ip6_lessthan(&(u_)->upper, &(cur)->upper) ) (u_)->upper = (cur)->upper; \ - if ( ip6_lessthan(&(cur)->lower, &(u_)->lower) ) (u_)->lower = (cur)->lower; \ - } else { \ - *(u_) = *(cur); \ - } \ - (list_)[(pos_)++] = (num_); \ -} while(0) - - for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) - { - IP6 diff1; - IP6 diff2; - - cur = (IP6R *) DatumGetPointer(ent[i].key); - ip6_sub(&cur->lower, &pageunion.lower, &diff1); - ip6_sub(&pageunion.upper, &cur->upper, &diff2); - if (ip6_lessthan(&diff1,&diff2)) - ADDLIST(listL, unionL, posL, i); - else - ADDLIST(listR, unionR, posR, i); - } - - /* bad disposition, sort by ascending size and resplit */ - if (posR == 0 || posL == 0) - { - struct gip6r_sort *arr = (struct gip6r_sort *) - palloc(sizeof(struct gip6r_sort) * (maxoff + FirstOffsetNumber)); - - for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) - { - arr[i].key = (IP6R *) DatumGetPointer(ent[i].key); - arr[i].pos = i; - } - - qsort(arr + FirstOffsetNumber, - maxoff - FirstOffsetNumber + 1, - sizeof(struct gip6r_sort), - gip6r_sort_compare); - - posL = posR = 0; - for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) - { - IP6 diff1; - IP6 diff2; - - cur = arr[i].key; - ip6_sub(&cur->lower, &pageunion.lower, &diff1); - ip6_sub(&pageunion.upper, &cur->upper, &diff2); - - if (ip6_lessthan(&diff1,&diff2)) - ADDLIST(listL, unionL, posL, arr[i].pos); - else if (ip6_equal(&diff1,&diff2)) - { - if (posL > posR) - ADDLIST(listR, unionR, posR, arr[i].pos); - else - ADDLIST(listL, unionL, posL, arr[i].pos); - } - else - ADDLIST(listR, unionR, posR, arr[i].pos); - } - pfree(arr); - } - - v->spl_nleft = posL; - v->spl_nright = posR; - - PG_RETURN_POINTER(v); -} - -#undef ADDLIST - -/* -** Equality methods -*/ -PG_FUNCTION_INFO_V1(gip6r_same); -Datum -gip6r_same(PG_FUNCTION_ARGS) -{ - IP6R *v1 = (IP6R *) PG_GETARG_POINTER(0); - IP6R *v2 = (IP6R *) PG_GETARG_POINTER(1); - bool *result = (bool *) PG_GETARG_POINTER(2); - - if (v1 && v2) - *result = ip6r_equal(v1,v2); - else - *result = (v1 == NULL && v2 == NULL); - -#ifdef GIST_DEBUG - fprintf(stderr, "same: %s\n", (*result ? "TRUE" : "FALSE")); -#endif - - PG_RETURN_POINTER(result); -} - - -/* - * Strategy numbers: - * OPERATOR 1 >>= , - * OPERATOR 2 <<= , - * OPERATOR 3 >> , - * OPERATOR 4 << , - * OPERATOR 5 && , - * OPERATOR 6 = , - */ - -/* -** SUPPORT ROUTINES -*/ -static bool -gip6r_leaf_consistent(IP6R * key, - IP6R * query, - StrategyNumber strategy) -{ -#ifdef GIST_QUERY_DEBUG - fprintf(stderr, "leaf_consistent, %d\n", strategy); -#endif - - switch (strategy) - { - case 1: /* left contains right nonstrict */ - return ip6r_contains_internal(key, query, TRUE); - case 2: /* left contained in right nonstrict */ - return ip6r_contains_internal(query, key, TRUE); - case 3: /* left contains right strict */ - return ip6r_contains_internal(key, query, FALSE); - case 4: /* left contained in right strict */ - return ip6r_contains_internal(query, key, FALSE); - case 5: /* left overlaps right */ - return ip6r_overlaps_internal(key, query); - case 6: /* left equal right */ - return ip6r_equal(key, query); - default: - return FALSE; - } -} - -/* logic notes: - * If the union value we're looking at overlaps with our query value - * at all, then any of the values underneath it might overlap with us - * or be contained by us, so all the "contained by" and "overlaps" - * cases degenerate to "overlap". - * If the union value is equal to the query value, then none of the - * values under it can strictly contain the query value, so for - * "contained" queries the strictness is preserved. - * If we're looking for an "equal" value, then we have to enter any - * subtree whose union contains (not strictly) our query value. - */ - -bool -gip6r_internal_consistent(IP6R * key, - IP6R * query, - StrategyNumber strategy) -{ -#ifdef GIST_QUERY_DEBUG - fprintf(stderr, "internal_consistent, %d\n", strategy); -#endif - - switch (strategy) - { - case 2: /* left contained in right nonstrict */ - case 4: /* left contained in right strict */ - case 5: /* left overlaps right */ - return ip6r_overlaps_internal(key, query); - case 3: /* left contains right strict */ - return ip6r_contains_internal(key, query, FALSE); - case 1: /* left contains right nonstrict */ - case 6: /* left equal right */ - return ip6r_contains_internal(key, query, TRUE); - default: - return FALSE; - } -} - -/* end */ diff -Nru ip4r-2.3/ip6r_funcs.h ip4r-2.4/ip6r_funcs.h --- ip4r-2.3/ip6r_funcs.h 2018-05-24 21:30:28.000000000 +0000 +++ ip4r-2.4/ip6r_funcs.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,319 +0,0 @@ -/* $Id: ip6r_funcs.h,v 1.1 2011/08/03 20:16:03 andrewsn Exp $ */ - -/**************************************************************************/ -/* This part is the internal implementation of all functionality, with no - * reference to the interface with postgres. That part comes later and is - * implemented in terms of these functions. - */ - -static inline -uint64 hostmask6_hi(unsigned masklen) -{ - if (masklen >= 64) - return 0; - if (masklen == 0) - return ~((uint64)0); - return (((uint64)(1U)) << (64-masklen)) - 1U; -} - -static inline -uint64 hostmask6_lo(unsigned masklen) -{ - if (masklen <= 64) - return ~((uint64)0); - return (((uint64)(1U)) << (128-masklen)) - 1U; -} - -static inline -uint64 netmask6_hi(unsigned masklen) -{ - return ~hostmask6_hi(masklen); -} - -static inline -uint64 netmask6_lo(unsigned masklen) -{ - return ~hostmask6_lo(masklen); -} - -/* if LO and HI are ends of a CIDR prefix, return the mask length. - * If not, returns ~0. - */ - -static inline -unsigned masklen64(uint64 lo, uint64 hi, int offset) -{ - uint64 d = (lo ^ hi) + 1; - int t = 0; - int b; - - /* at this point, d can be: - * 0 if A and B have all bits different - * 1 if A and B are equal - * 1 << (64-masklen) - * some other value if A and B are not ends of a CIDR range - * but in any case, after extracting the masklen, we have to - * recheck because some non-CIDR ranges will produce the same - * results. - */ - if (d == 0) - return (lo == 0 && hi == ~((uint64)0)) ? offset : ~0; - if (d == 1) - return (lo == hi) ? 64+offset : ~0; - - if (!(d & 0xFFFFFFFFUL)) - { - t = 32; - d >>= 32; - } - - b = ffs((uint32) d); - if ((((uint32)1U) << (b-1)) != d) - return ~0; - - { - uint64 mask = ((uint64)(1U) << (t+b-1)) - 1U; - if ((lo & mask) == 0 && (hi & mask) == mask) - return 65-t-b + offset; - } - - return ~0; -} - -static inline -unsigned masklen6(IP6 *lo, IP6 *hi) -{ - if (lo->bits[0] == hi->bits[0]) /* masklen >= 64 */ - { - return masklen64(lo->bits[1], hi->bits[1], 64); - } - else /* masklen < 64 */ - { - if (lo->bits[1] != 0 || hi->bits[1] != ~((uint64)0)) - return ~0U; - return masklen64(lo->bits[0], hi->bits[0], 0); - } -} - -static inline -bool ip6_valid_netmask(uint64 maskhi, uint64 masklo) -{ - uint64 d; - int fbit; - - if (maskhi == ~((uint64)0)) - d = ~masklo + 1; - else if (masklo == 0) - d = ~maskhi + 1; - else - return FALSE; - - /* at this point, d can be: - * 0 if mask was 0x00000000 (valid) - * 1 << (32-masklen) (valid) - * some other value (invalid) - */ - - if (!(d & 0xFFFFFFFFUL)) - d >>= 32; - if (!d) - return TRUE; - - fbit = ffs((uint32)d); - return ((uint32)(1U) << (fbit-1)) == d; -} - - -static inline -bool ip6_equal(IP6 *a, IP6 *b) -{ - return (a->bits[0] == b->bits[0]) && (a->bits[1] == b->bits[1]); -} - -static inline -int ip6_compare(IP6 *a, IP6 *b) -{ - if (a->bits[0] != b->bits[0]) - return (a->bits[0] > b->bits[0]) ? 1 : -1; - if (a->bits[1] != b->bits[1]) - return (a->bits[1] > b->bits[1]) ? 1 : -1; - return 0; -} - -static inline -bool ip6_lessthan(IP6 *a, IP6 *b) -{ - return ( (a->bits[0] < b->bits[0]) - || ((a->bits[0] == b->bits[0]) && (a->bits[1] < b->bits[1])) ); -} - -static inline -void ip6_sub(IP6 *minuend, IP6 *subtrahend, IP6 *result) -{ - result->bits[1] = minuend->bits[1] - subtrahend->bits[1]; - result->bits[0] = minuend->bits[0] - subtrahend->bits[0] - (minuend->bits[1] < subtrahend->bits[1]); -} - -static inline -void ip6_sub_int(IP6 *minuend, int subtrahend, IP6 *result) -{ - uint64 res_lo; - - if (subtrahend >= 0) - { - res_lo = minuend->bits[1] - (uint64)(subtrahend); - result->bits[0] = minuend->bits[0] - (res_lo > minuend->bits[1]); - } - else - { - res_lo = minuend->bits[1] + (uint64)(-subtrahend); - result->bits[0] = minuend->bits[0] + (res_lo < minuend->bits[1]); - } - - result->bits[1] = res_lo; -} - - -static inline -bool ip6r_from_cidr(IP6 *prefix, unsigned masklen, IP6R *ipr) -{ - uint64 mask_lo = hostmask6_lo(masklen); - uint64 mask_hi = hostmask6_hi(masklen); - if (masklen > 128) - return FALSE; - if ((prefix->bits[0] & mask_hi) || (prefix->bits[1] & mask_lo)) - return FALSE; - ipr->upper.bits[0] = (prefix->bits[0] | mask_hi); - ipr->upper.bits[1] = (prefix->bits[1] | mask_lo); - ipr->lower = *prefix; - return TRUE; -} - -static inline -bool ip6r_from_inet(IP6 *addr, unsigned masklen, IP6R *ipr) -{ - uint64 mask_lo = hostmask6_lo(masklen); - uint64 mask_hi = hostmask6_hi(masklen); - if (masklen > 128) - return FALSE; - ipr->lower.bits[0] = (addr->bits[0] & ~mask_hi); - ipr->lower.bits[1] = (addr->bits[1] & ~mask_lo); - ipr->upper.bits[0] = (addr->bits[0] | mask_hi); - ipr->upper.bits[1] = (addr->bits[1] | mask_lo); - return TRUE; -} - -/* helpers for union/intersection for indexing */ - -/* note that this function has to handle the case where RESULT aliases - * either of A or B - */ - -static inline -IP6R *ip6r_union_internal(IP6R *a, IP6R *b, IP6R *result) -{ - if (ip6_lessthan(&a->lower,&b->lower)) - result->lower = a->lower; - else - result->lower = b->lower; - - if (ip6_lessthan(&b->upper,&a->upper)) - result->upper = a->upper; - else - result->upper = b->upper; - - return result; -} - -static inline -IP6R *ip6r_inter_internal(IP6R *a, IP6R *b, IP6R *result) -{ - if (ip6_lessthan(&a->upper,&b->lower) || ip6_lessthan(&b->upper,&a->lower)) - { - /* disjoint */ - result->lower.bits[0] = 0; - result->lower.bits[1] = 1; - result->upper.bits[0] = 0; /* INVALID VALUE */ - result->upper.bits[1] = 0; /* INVALID VALUE */ - return NULL; - } - - if (ip6_lessthan(&a->upper,&b->upper)) - result->upper = a->upper; - else - result->upper = b->upper; - - if (ip6_lessthan(&b->lower,&a->lower)) - result->lower = a->lower; - else - result->lower = b->lower; - - return result; -} - -static inline -double ip6r_metric(IP6R *v) -{ - IP6 diff; - double res = 0.0; - if (!v) - return res; - - ip6_sub(&v->upper, &v->lower, &diff); - - return ( (ldexp((double)diff.bits[0],64)) - + (diff.bits[1] + 1.0) ); -} - -/* comparisons */ - -static inline -bool ip6_less_eq(IP6 *a, IP6 *b) -{ - return !ip6_lessthan(b,a); -} - -static inline -bool ip6r_equal(IP6R *a, IP6R *b) -{ - return ip6_equal(&a->lower,&b->lower) && ip6_equal(&a->upper,&b->upper); -} - -static inline -bool ip6r_lessthan(IP6R *a, IP6R *b) -{ - switch (ip6_compare(&a->lower,&b->lower)) - { - default: return ip6_lessthan(&a->upper,&b->upper); - case -1: return true; - case 1: return false; - } -} - -static inline -bool ip6r_less_eq(IP6R *a, IP6R *b) -{ - return !ip6r_lessthan(b,a); -} - -static inline -bool ip6r_contains_internal(IP6R *left, IP6R *right, bool eqval) -{ - if (ip6r_equal(left,right)) - return eqval; - return !ip6_lessthan(&right->lower,&left->lower) && !ip6_lessthan(&left->upper,&right->upper); -} - -static inline -bool ip6r_overlaps_internal(IP6R *left, IP6R *right) -{ - return !ip6_lessthan(&left->upper,&right->lower) && !ip6_lessthan(&right->upper,&left->lower); -} - -static inline -bool ip6_contains_internal(IP6R *left, IP6 *right) -{ - return !ip6_lessthan(right,&left->lower) && !ip6_lessthan(&left->upper,right); -} - -/* end */ diff -Nru ip4r-2.3/ipaddr.c ip4r-2.4/ipaddr.c --- ip4r-2.3/ipaddr.c 2018-05-24 21:30:28.000000000 +0000 +++ ip4r-2.4/ipaddr.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,746 +0,0 @@ -/* $Id: ipaddr.c,v 1.1 2011/08/03 20:16:03 andrewsn Exp $ */ - -#include "ipr.h" - -#include "ip4r_funcs.h" -#include "ip6r_funcs.h" - -void ipaddr_internal_error(void) -{ - elog(ERROR,"Invalid IP datum"); - - /* just to shut the compiler up */ - abort(); -} - - -/* - * generic transforms of IP values - apply the specified ip4 or ip6 function - * to the given args according to parameter type. Where the result type is an - * IP, it's the same family as the parameter IP. - */ - -/* func(IP) returns Datum */ - -static inline -Datum -ipaddr_transform_1d(Datum d, PGFunction ip4func, PGFunction ip6func) -{ - IP_P ipp = DatumGetIP_P(d); - IP ip; - int af = ip_unpack(ipp, &ip); - - switch (af) - { - case PGSQL_AF_INET: - return DirectFunctionCall1(ip4func, IP4GetDatum(ip.ip4)); - - case PGSQL_AF_INET6: - return DirectFunctionCall1(ip6func, IP6PGetDatum(&ip.ip6)); - } - - ipaddr_internal_error(); -} - - -/* func(IP) returns IP */ - -static inline -IP_P -ipaddr_transform_1(Datum d, PGFunction ip4func, PGFunction ip6func) -{ - IP_P ipp = DatumGetIP_P(d); - IP ip; - int af = ip_unpack(ipp, &ip); - - switch (af) - { - case PGSQL_AF_INET: - ip.ip4 = DatumGetIP4(DirectFunctionCall1(ip4func, IP4GetDatum(ip.ip4))); - break; - - case PGSQL_AF_INET6: - ip.ip6 = *(DatumGetIP6P(DirectFunctionCall1(ip6func, IP6PGetDatum(&ip.ip6)))); - break; - - default: - ipaddr_internal_error(); - } - - return ip_pack(af, &ip); -} - - -/* func(IP, Datum) returns IP */ - -static inline -IP_P -ipaddr_transform_2d(Datum d1, Datum d2, PGFunction ip4func, PGFunction ip6func) -{ - IP_P ipp = DatumGetIP_P(d1); - IP ip; - int af = ip_unpack(ipp, &ip); - - switch (af) - { - case PGSQL_AF_INET: - ip.ip4 = DatumGetIP4(DirectFunctionCall2(ip4func, IP4GetDatum(ip.ip4), d2)); - break; - - case PGSQL_AF_INET6: - ip.ip6 = *(DatumGetIP6P(DirectFunctionCall2(ip6func, IP6PGetDatum(&ip.ip6), d2))); - break; - - default: - ipaddr_internal_error(); - } - - return ip_pack(af, &ip); -} - -/* func(IP,IP) returns IP; it's an error for the source IPs to be in different families */ - -static inline -IP_P -ipaddr_transform_2(Datum d1, Datum d2, PGFunction ip4func, PGFunction ip6func) -{ - IP_P ipp1 = DatumGetIP_P(d1); - IP_P ipp2 = DatumGetIP_P(d2); - IP ip1; - IP ip2; - IP out; - int af1 = ip_unpack(ipp1, &ip1); - int af2 = ip_unpack(ipp2, &ip2); - - if (af1 != af2) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid mixing of IP address families"))); - - switch (af1) - { - case PGSQL_AF_INET: - out.ip4 = DatumGetIP4(DirectFunctionCall2(ip4func, IP4GetDatum(ip1.ip4), IP4GetDatum(ip2.ip4))); - break; - - case PGSQL_AF_INET6: - out.ip6 = *(DatumGetIP6P(DirectFunctionCall2(ip6func, IP6PGetDatum(&ip1.ip6), IP6PGetDatum(&ip2.ip6)))); - break; - - default: - ipaddr_internal_error(); - } - - return ip_pack(af1, &out); -} - - - - -/* -#define GIST_DEBUG -#define GIST_QUERY_DEBUG -*/ - -static -text * -make_text(char *str, int len) -{ - text *ret = (text *) palloc(len + VARHDRSZ); - SET_VARSIZE(ret, len + VARHDRSZ); - if (str) - memcpy(VARDATA(ret), str, len); - else - memset(VARDATA(ret), 0, len); - return ret; -} - -static inline -void -set_text_len(text *txt, int len) -{ - if ((len + VARHDRSZ) < VARSIZE(txt)) - SET_VARSIZE(txt, len + VARHDRSZ); -} - - -/* -** Input/Output routines -*/ - -PG_FUNCTION_INFO_V1(ipaddr_in); -Datum -ipaddr_in(PG_FUNCTION_ARGS) -{ - char *str = PG_GETARG_CSTRING(0); - IP ip; - - if (strchr(str,':')) - { - if (ip6_raw_input(str, ip.ip6.bits)) - PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET6, &ip)); - } - else - { - if (ip4_raw_input(str, &ip.ip4)) - PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET, &ip)); - } - - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid IP value: '%s'", str))); - PG_RETURN_NULL(); -} - -PG_FUNCTION_INFO_V1(ipaddr_out); -Datum -ipaddr_out(PG_FUNCTION_ARGS) -{ - IP_P ipp = PG_GETARG_IP_P(0); - char *out = palloc(IP6_STRING_MAX); - IP ip; - - switch (ip_unpack(ipp, &ip)) - { - case PGSQL_AF_INET: - ip4_raw_output(ip.ip4, out, IP6_STRING_MAX); - break; - case PGSQL_AF_INET6: - ip6_raw_output(ip.ip6.bits, out, IP6_STRING_MAX); - break; - } - - PG_RETURN_CSTRING(out); -} - -PG_FUNCTION_INFO_V1(ipaddr_recv); -Datum -ipaddr_recv(PG_FUNCTION_ARGS) -{ - StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); - IP ip; - int af, bits, nbytes; - - /* we copy the external format used by inet/cidr, just because. */ - - af = pq_getmsgbyte(buf); - if (af != PGSQL_AF_INET && af != PGSQL_AF_INET6) - ereport(ERROR, - (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), - errmsg("invalid address family in external IP value"))); - bits = pq_getmsgbyte(buf); - if (bits != ipr_af_maxbits(af)) - ereport(ERROR, - (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), - errmsg("invalid bit length in external IP value"))); - (void) pq_getmsgbyte(buf); /* ignore flag */ - nbytes = pq_getmsgbyte(buf); - if (nbytes*8 != bits) - ereport(ERROR, - (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), - errmsg("invalid address length in external IP value"))); - - switch (af) - { - case PGSQL_AF_INET: - ip.ip4 = (IP4) pq_getmsgint(buf, sizeof(IP4)); - break; - - case PGSQL_AF_INET6: - ip.ip6.bits[0] = pq_getmsgint64(buf); - ip.ip6.bits[1] = pq_getmsgint64(buf); - break; - } - - PG_RETURN_IP_P(ip_pack(af, &ip)); -} - -PG_FUNCTION_INFO_V1(ipaddr_send); -Datum -ipaddr_send(PG_FUNCTION_ARGS) -{ - IP_P arg1 = PG_GETARG_IP_P(0); - StringInfoData buf; - IP ip; - int af = ip_unpack(arg1, &ip); - - pq_begintypsend(&buf); - pq_sendbyte(&buf, af); - pq_sendbyte(&buf, (int8) ipr_af_maxbits(af)); - pq_sendbyte(&buf, 1); - pq_sendbyte(&buf, ip_sizeof(af)); - - switch (af) - { - case PGSQL_AF_INET: - pq_sendint(&buf, ip.ip4, sizeof(IP4)); - break; - - case PGSQL_AF_INET6: - pq_sendint64(&buf, ip.ip6.bits[0]); - pq_sendint64(&buf, ip.ip6.bits[1]); - break; - } - - PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); -} - -PG_FUNCTION_INFO_V1(ipaddr_hash); -Datum -ipaddr_hash(PG_FUNCTION_ARGS) -{ - IP_P arg1 = PG_GETARG_IP_P(0); - - return hash_any((void*)(VARDATA_ANY(arg1)), VARSIZE_ANY_EXHDR(arg1)); -} - -PG_FUNCTION_INFO_V1(ipaddr_cast_to_text); -Datum -ipaddr_cast_to_text(PG_FUNCTION_ARGS) -{ - IP_P ipp = PG_GETARG_IP_P(0); - IP ip; - int af = ip_unpack(ipp, &ip); - text *out = NULL; - - switch (af) - { - case PGSQL_AF_INET: - out = make_text(NULL, IP4_STRING_MAX); - set_text_len(out, ip4_raw_output(ip.ip4, VARDATA(out), IP4_STRING_MAX)); - break; - case PGSQL_AF_INET6: - out = make_text(NULL, IP6_STRING_MAX); - set_text_len(out, ip6_raw_output(ip.ip6.bits, VARDATA(out), IP6_STRING_MAX)); - break; - } - - PG_RETURN_TEXT_P(out); -} - -PG_FUNCTION_INFO_V1(ipaddr_cast_from_text); -Datum -ipaddr_cast_from_text(PG_FUNCTION_ARGS) -{ - text *txt = PG_GETARG_TEXT_PP(0); - int tlen = VARSIZE_ANY_EXHDR(txt); - char buf[IP6_STRING_MAX]; - - if (tlen < sizeof(buf)) - { - IP ip; - - memcpy(buf, VARDATA_ANY(txt), tlen); - buf[tlen] = 0; - - if (strchr(buf,':')) - { - if (ip6_raw_input(buf, ip.ip6.bits)) - PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET6, &ip)); - } - else - { - if (ip4_raw_input(buf, &ip.ip4)) - PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET, &ip)); - } - } - - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid IP value in text"))); - PG_RETURN_NULL(); -} - -PG_FUNCTION_INFO_V1(ipaddr_cast_from_inet); -Datum -ipaddr_cast_from_inet(PG_FUNCTION_ARGS) -{ - inet *inetptr = PG_GETARG_INET_P(0); - inet_struct *in = INET_STRUCT_DATA(inetptr); - IP ip; - - switch (in->family) - { - case PGSQL_AF_INET: - ip.ip4 = DatumGetIP4(DirectFunctionCall1(ip4_cast_from_inet, InetPGetDatum(inetptr))); - PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET, &ip)); - case PGSQL_AF_INET6: - ip.ip6 = *(DatumGetIP6P(DirectFunctionCall1(ip6_cast_from_inet, InetPGetDatum(inetptr)))); - PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET6, &ip)); - } - - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid INET value for conversion to IP"))); - PG_RETURN_NULL(); -} - -PG_FUNCTION_INFO_V1(ipaddr_cast_to_cidr); -Datum -ipaddr_cast_to_cidr(PG_FUNCTION_ARGS) -{ - PG_RETURN_DATUM(ipaddr_transform_1d(PG_GETARG_DATUM(0), ip4_cast_to_cidr, ip6_cast_to_cidr)); -} - - -PG_FUNCTION_INFO_V1(ipaddr_cast_to_numeric); -Datum -ipaddr_cast_to_numeric(PG_FUNCTION_ARGS) -{ - PG_RETURN_DATUM(ipaddr_transform_1d(PG_GETARG_DATUM(0), ip4_cast_to_numeric, ip6_cast_to_numeric)); -} - -PG_FUNCTION_INFO_V1(ipaddr_cast_from_ip4); -Datum -ipaddr_cast_from_ip4(PG_FUNCTION_ARGS) -{ - IP ip; - - ip.ip4 = PG_GETARG_IP4(0); - - PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET, &ip)); -} - -PG_FUNCTION_INFO_V1(ipaddr_cast_from_ip6); -Datum -ipaddr_cast_from_ip6(PG_FUNCTION_ARGS) -{ - IP6 *in = PG_GETARG_IP6_P(0); - IP ip; - - ip.ip6 = *in; - - PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET6, &ip)); -} - - -PG_FUNCTION_INFO_V1(ipaddr_cast_to_ip4); -Datum -ipaddr_cast_to_ip4(PG_FUNCTION_ARGS) -{ - IP_P ipp = PG_GETARG_IP_P(0); - IP ip; - - if (ip_unpack(ipp, &ip) == PGSQL_AF_INET) - { - PG_RETURN_IP4(ip.ip4); - } - - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid IP value in cast to IP4"))); - PG_RETURN_NULL(); -} - -PG_FUNCTION_INFO_V1(ipaddr_cast_to_ip6); -Datum -ipaddr_cast_to_ip6(PG_FUNCTION_ARGS) -{ - IP_P ipp = PG_GETARG_IP_P(0); - IP ip; - - if (ip_unpack(ipp, &ip) == PGSQL_AF_INET6) - { - IP6 *out = palloc(sizeof(IP6)); - *out = ip.ip6; - PG_RETURN_IP6_P(out); - } - - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid IP value in cast to IP4"))); - PG_RETURN_NULL(); -} - - -PG_FUNCTION_INFO_V1(ipaddr_family); -Datum -ipaddr_family(PG_FUNCTION_ARGS) -{ - IP_P ipp = PG_GETARG_IP_P(0); - IP ip; - - if (ip_unpack(ipp, &ip) == PGSQL_AF_INET6) - PG_RETURN_INT32(6); - else - PG_RETURN_INT32(4); -} - - -PG_FUNCTION_INFO_V1(ipaddr_net_lower); -Datum -ipaddr_net_lower(PG_FUNCTION_ARGS) -{ - PG_RETURN_IP_P(ipaddr_transform_2d(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), ip4_net_lower, ip6_net_lower)); -} - -PG_FUNCTION_INFO_V1(ipaddr_net_upper); -Datum -ipaddr_net_upper(PG_FUNCTION_ARGS) -{ - PG_RETURN_IP_P(ipaddr_transform_2d(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), ip4_net_upper, ip6_net_upper)); -} - -PG_FUNCTION_INFO_V1(ipaddr_plus_int); -Datum -ipaddr_plus_int(PG_FUNCTION_ARGS) -{ - PG_RETURN_IP_P(ipaddr_transform_2d(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), ip4_plus_int, ip6_plus_int)); -} - -PG_FUNCTION_INFO_V1(ipaddr_plus_bigint); -Datum -ipaddr_plus_bigint(PG_FUNCTION_ARGS) -{ - PG_RETURN_IP_P(ipaddr_transform_2d(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), ip4_plus_bigint, ip6_plus_bigint)); -} - -PG_FUNCTION_INFO_V1(ipaddr_plus_numeric); -Datum -ipaddr_plus_numeric(PG_FUNCTION_ARGS) -{ - PG_RETURN_IP_P(ipaddr_transform_2d(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), ip4_plus_numeric, ip6_plus_numeric)); -} - -PG_FUNCTION_INFO_V1(ipaddr_minus_int); -Datum -ipaddr_minus_int(PG_FUNCTION_ARGS) -{ - PG_RETURN_IP_P(ipaddr_transform_2d(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), ip4_minus_int, ip6_minus_int)); -} - -PG_FUNCTION_INFO_V1(ipaddr_minus_bigint); -Datum -ipaddr_minus_bigint(PG_FUNCTION_ARGS) -{ - PG_RETURN_IP_P(ipaddr_transform_2d(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), ip4_minus_bigint, ip6_minus_bigint)); -} - -PG_FUNCTION_INFO_V1(ipaddr_minus_numeric); -Datum -ipaddr_minus_numeric(PG_FUNCTION_ARGS) -{ - PG_RETURN_IP_P(ipaddr_transform_2d(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), ip4_minus_numeric, ip6_minus_numeric)); -} - -PG_FUNCTION_INFO_V1(ipaddr_minus_ipaddr); -Datum -ipaddr_minus_ipaddr(PG_FUNCTION_ARGS) -{ - Datum minuend = PG_GETARG_DATUM(0); - Datum subtrahend = PG_GETARG_DATUM(1); - Datum res; - IP ip1; - IP ip2; - int af1 = ip_unpack(DatumGetIP_P(minuend), &ip1); - int af2 = ip_unpack(DatumGetIP_P(subtrahend), &ip2); - - if (af1 != af2) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid mixing of IP address families"))); - - switch (af1) - { - case PGSQL_AF_INET: - res = DirectFunctionCall2(numeric_sub, - DirectFunctionCall1(ip4_cast_to_numeric,IP4GetDatum(ip1.ip4)), - DirectFunctionCall1(ip4_cast_to_numeric,IP4GetDatum(ip2.ip4))); - break; - - case PGSQL_AF_INET6: - res = DirectFunctionCall2(numeric_sub, - DirectFunctionCall1(ip6_cast_to_numeric,IP6PGetDatum(&ip1.ip6)), - DirectFunctionCall1(ip6_cast_to_numeric,IP6PGetDatum(&ip2.ip6))); - break; - - default: - ipaddr_internal_error(); - } - - PG_RETURN_DATUM(res); -} - -PG_FUNCTION_INFO_V1(ipaddr_and); -Datum -ipaddr_and(PG_FUNCTION_ARGS) -{ - PG_RETURN_IP_P(ipaddr_transform_2(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), ip4_and, ip6_and)); -} - -PG_FUNCTION_INFO_V1(ipaddr_or); -Datum -ipaddr_or(PG_FUNCTION_ARGS) -{ - PG_RETURN_IP_P(ipaddr_transform_2(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), ip4_or, ip6_or)); -} - -PG_FUNCTION_INFO_V1(ipaddr_xor); -Datum -ipaddr_xor(PG_FUNCTION_ARGS) -{ - PG_RETURN_IP_P(ipaddr_transform_2(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), ip4_xor, ip6_xor)); -} - -PG_FUNCTION_INFO_V1(ipaddr_not); -Datum -ipaddr_not(PG_FUNCTION_ARGS) -{ - PG_RETURN_IP_P(ipaddr_transform_1(PG_GETARG_DATUM(0), ip4_not, ip6_not)); -} - - -/* - * generic boolean comparison of two IPs. If in the same family, then the - * passed-in comparison function is called; if in different families, then - * the result is mismatch_af1 or _af2 according to which of the first or - * second address is in the larger family. - */ - -static inline -bool -ipaddr_comparison_bool(Datum d1, Datum d2, - bool mismatch_af1, bool mismatch_af2, - PGFunction ip4func, PGFunction ip6func) -{ - IP_P ipp1 = DatumGetIP_P(d1); - IP_P ipp2 = DatumGetIP_P(d2); - IP ip1; - IP ip2; - int af1 = ip_unpack(ipp1, &ip1); - int af2 = ip_unpack(ipp2, &ip2); - bool retval; - - if (af1 != af2) - { - retval = (af1 > af2) ? mismatch_af1 : mismatch_af2; - } - else - { - switch (af1) - { - case PGSQL_AF_INET: - retval = DatumGetBool(DirectFunctionCall2(ip4func, IP4GetDatum(ip1.ip4), IP4GetDatum(ip2.ip4))); - break; - - case PGSQL_AF_INET6: - retval = DatumGetBool(DirectFunctionCall2(ip6func, IP6PGetDatum(&ip1.ip6), IP6PGetDatum(&ip2.ip6))); - break; - - default: - ipaddr_internal_error(); - } - } - - if ((Pointer)ipp1 != DatumGetPointer(d1)) - pfree(ipp1); - if ((Pointer)ipp2 != DatumGetPointer(d2)) - pfree(ipp2); - - return retval; -} - -PG_FUNCTION_INFO_V1(ipaddr_lt); -Datum -ipaddr_lt(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( - ipaddr_comparison_bool(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), - false, true, - ip4_lt, ip6_lt)); -} - -PG_FUNCTION_INFO_V1(ipaddr_le); -Datum -ipaddr_le(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( - ipaddr_comparison_bool(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), - false, true, - ip4_le, ip6_le)); -} - -PG_FUNCTION_INFO_V1(ipaddr_gt); -Datum -ipaddr_gt(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( - ipaddr_comparison_bool(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), - true, false, - ip4_gt, ip6_gt)); -} - -PG_FUNCTION_INFO_V1(ipaddr_ge); -Datum -ipaddr_ge(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( - ipaddr_comparison_bool(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), - true, false, - ip4_ge, ip6_ge)); -} - -PG_FUNCTION_INFO_V1(ipaddr_eq); -Datum -ipaddr_eq(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( - ipaddr_comparison_bool(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), - false, false, - ip4_eq, ip6_eq)); -} - -PG_FUNCTION_INFO_V1(ipaddr_neq); -Datum -ipaddr_neq(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( - ipaddr_comparison_bool(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), - true, true, - ip4_neq, ip6_neq)); -} - - -/***************************************************************************** - * Btree functions - *****************************************************************************/ - -PG_FUNCTION_INFO_V1(ipaddr_cmp); -Datum -ipaddr_cmp(PG_FUNCTION_ARGS) -{ - IP_P ipp1 = PG_GETARG_IP_P(0); - IP_P ipp2 = PG_GETARG_IP_P(1); - IP ip1; - IP ip2; - int af1 = ip_unpack(ipp1, &ip1); - int af2 = ip_unpack(ipp2, &ip2); - int32 retval; - - if (af1 != af2) - { - retval = (af1 > af2) ? 1 : -1; - } - else - { - switch (af1) - { - case PGSQL_AF_INET: - retval = DatumGetInt32(DirectFunctionCall2(ip4_cmp, IP4GetDatum(ip1.ip4), IP4GetDatum(ip2.ip4))); - break; - - case PGSQL_AF_INET6: - retval = DatumGetInt32(DirectFunctionCall2(ip6_cmp, IP6PGetDatum(&ip1.ip6), IP6PGetDatum(&ip2.ip6))); - break; - - default: - ipaddr_internal_error(); - } - } - - PG_FREE_IF_COPY(ipp1,0); - PG_FREE_IF_COPY(ipp2,1); - - PG_RETURN_INT32(retval); -} - diff -Nru ip4r-2.3/iprange.c ip4r-2.4/iprange.c --- ip4r-2.3/iprange.c 2018-05-24 21:30:28.000000000 +0000 +++ ip4r-2.4/iprange.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,2244 +0,0 @@ -/* $Id: iprange.c,v 1.4 2011/11/02 07:47:24 andrewsn Exp $ */ - -#include "ipr.h" - -#include "ip4r_funcs.h" -#include "ip6r_funcs.h" - -/* - * Some C compilers including GCC really get confused by the use of the IP and - * IPR unions, generating a lot of completely spurious "may be used - * uninitialized" warnings. The various uses of IP*_INITIALIZER in this file - * ought to be unnecessary; so this macro is used to make them conditional for - * ease of experimentation. - */ - -#define XINIT(_i) = _i - -static void iprange_internal_error(void) __attribute__((noreturn,noinline)); -static void iprange_af_mismatch(void) __attribute__((noreturn,noinline)); - -static -void iprange_internal_error(void) -{ - elog(ERROR,"Invalid IPR datum"); - - /* just to shut the compiler up */ - abort(); -} - -static -void iprange_af_mismatch(void) -{ - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid mixing of IP address families"))); - /* just to shut the compiler up */ - abort(); -} - - -/* - * Rather than use 32 bytes + length for every IP range, we make the - * assumption that most ranges (at least in table data and hence gist - * leaf nodes) will be CIDRs, and many of those /64 or shorter. - * - * So we allow the following formats (excluding varlena header): - * - * 0 bytes - special 'match all' range (af==0) - * 8 bytes - IP4R - * 1 byte pfxlen + 8 bytes - IP6R cidr range /64 or shorter - * 1 byte pfxlen + 16 bytes - IP6R cidr range /65 or longer - * 32 bytes - arbitrary IP6R range - */ - -static -int ipr_unpack(IPR_P in, IPR *out) -{ - unsigned char *ptr = (unsigned char *) VARDATA_ANY(in); - - switch (VARSIZE_ANY_EXHDR(in)) - { - case 0: - return 0; - - case sizeof(IP4R): - memcpy(&out->ip4r, ptr, sizeof(IP4R)); - return PGSQL_AF_INET; - - case 1+sizeof(uint64): - { - unsigned pfxlen = *ptr++; - memcpy(out->ip6r.lower.bits, ptr, sizeof(uint64)); - out->ip6r.lower.bits[1] = 0; - out->ip6r.upper.bits[0] = out->ip6r.lower.bits[0] | hostmask6_hi(pfxlen); - out->ip6r.upper.bits[1] = hostmask6_lo(pfxlen); - return PGSQL_AF_INET6; - } - - case 1+sizeof(IP6): - { - unsigned pfxlen = *ptr++; - memcpy(&out->ip6r.lower, ptr, sizeof(IP6)); - out->ip6r.upper.bits[0] = out->ip6r.lower.bits[0] | hostmask6_hi(pfxlen); - out->ip6r.upper.bits[1] = out->ip6r.lower.bits[1] | hostmask6_lo(pfxlen); - return PGSQL_AF_INET6; - } - - case sizeof(IP6R): - memcpy(&out->ip6r, ptr, sizeof(IP6R)); - return PGSQL_AF_INET6; - - default: - iprange_internal_error(); - } -} - -static -IPR_P ipr_pack(int af, IPR *val) -{ - IPR_P out = palloc(VARHDRSZ + sizeof(IP6R)); - unsigned char *ptr = (unsigned char *) VARDATA(out); - - switch (af) - { - case 0: - SET_VARSIZE(out, VARHDRSZ); - break; - - case PGSQL_AF_INET: - memcpy(ptr, &val->ip4r, sizeof(IP4R)); - SET_VARSIZE(out, VARHDRSZ + sizeof(IP4R)); - break; - - case PGSQL_AF_INET6: - { - unsigned pfxlen = masklen6(&val->ip6r.lower, &val->ip6r.upper); - if (pfxlen <= 64) - { - *ptr++ = pfxlen; - memcpy(ptr, val->ip6r.lower.bits, sizeof(uint64)); - SET_VARSIZE(out, VARHDRSZ + 1 + sizeof(uint64)); - } - else if (pfxlen <= 128) - { - *ptr++ = pfxlen; - memcpy(ptr, &val->ip6r.lower, sizeof(IP6)); - SET_VARSIZE(out, VARHDRSZ + 1 + sizeof(IP6)); - } - else - { - memcpy(ptr, &val->ip6r, sizeof(IP6R)); - SET_VARSIZE(out, VARHDRSZ + sizeof(IP6R)); - } - break; - } - - default: - iprange_internal_error(); - } - - return out; -} - - -/**************************************************************************/ -/* This part handles all aspects of postgres interfacing. - */ - -/* -** Input/Output routines -*/ - -/*---- ipr ----*/ - -PG_FUNCTION_INFO_V1(iprange_in); -Datum -iprange_in(PG_FUNCTION_ARGS) -{ - char *str = PG_GETARG_CSTRING(0); - IPR ipr; - - if (str[0] == '-' && str[1] == 0) - { - PG_RETURN_IPR_P(ipr_pack(0, NULL)); - } - else if (strchr(str,':')) - { - ipr.ip6r = *DatumGetIP6RP(DirectFunctionCall1(ip6r_in,CStringGetDatum(str))); - PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET6, &ipr)); - } - else - { - ipr.ip4r = *DatumGetIP4RP(DirectFunctionCall1(ip4r_in,CStringGetDatum(str))); - PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET, &ipr)); - } -} - -PG_FUNCTION_INFO_V1(iprange_out); -Datum -iprange_out(PG_FUNCTION_ARGS) -{ - IPR_P *iprp = PG_GETARG_IPR_P(0); - IPR ipr; - int af = ipr_unpack(iprp, &ipr); - - switch (af) - { - case 0: - { - char *out = palloc(2); - strcpy(out,"-"); - PG_RETURN_CSTRING(out); - } - - case PGSQL_AF_INET: - PG_RETURN_DATUM(DirectFunctionCall1(ip4r_out,IP4RPGetDatum(&ipr.ip4r))); - - case PGSQL_AF_INET6: - PG_RETURN_DATUM(DirectFunctionCall1(ip6r_out,IP6RPGetDatum(&ipr.ip6r))); - - default: - iprange_internal_error(); - } -} - -PG_FUNCTION_INFO_V1(iprange_recv); -Datum -iprange_recv(PG_FUNCTION_ARGS) -{ - StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); - IPR ipr; - unsigned af, bits, nbytes; - - /* - * This isn't quite the same format as inet/cidr but we keep reasonably - * close for no very good reason. - * - * 1 byte AF - * 1 byte pfx len (255 if the range is not a prefix) - * 1 byte flag (unused) - * 1 byte number of remaining bytes (0,4,8,16 or 32) - * - */ - - af = pq_getmsgbyte(buf); - if (af != 0 && af != PGSQL_AF_INET && af != PGSQL_AF_INET6) - ereport(ERROR, - (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), - errmsg("invalid address family in external IPR value"))); - bits = pq_getmsgbyte(buf); - if (bits != 255 && bits > ipr_af_maxbits(af)) - ereport(ERROR, - (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), - errmsg("invalid bit length in external IP value"))); - (void) pq_getmsgbyte(buf); /* ignore flag */ - nbytes = pq_getmsgbyte(buf); - - switch (af) - { - case 0: /* special 'match all' range */ - if (nbytes == 0) - PG_RETURN_IPR_P(ipr_pack(0,NULL)); - break; - - case PGSQL_AF_INET: - if (nbytes == sizeof(IP4) && bits <= ipr_af_maxbits(PGSQL_AF_INET)) - { - ipr.ip4r.lower = (IP4) pq_getmsgint(buf, sizeof(IP4)); - ipr.ip4r.upper = ipr.ip4r.lower | hostmask(bits); - PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET,&ipr)); - } - else if (nbytes == sizeof(IP4R)) - { - ipr.ip4r.lower = (IP4) pq_getmsgint(buf, sizeof(IP4)); - ipr.ip4r.upper = (IP4) pq_getmsgint(buf, sizeof(IP4)); - PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET,&ipr)); - } - break; - - case PGSQL_AF_INET6: - if (nbytes == sizeof(uint64) && bits <= 64) - { - ipr.ip6r.lower.bits[0] = (uint64) pq_getmsgint64(buf); - ipr.ip6r.lower.bits[1] = 0; - ipr.ip6r.upper.bits[0] = ipr.ip6r.lower.bits[0] | hostmask6_hi(bits); - ipr.ip6r.upper.bits[1] = ~(uint64)0; - PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET6,&ipr)); - } - else if (nbytes == sizeof(IP6) && bits <= ipr_af_maxbits(PGSQL_AF_INET6)) - { - ipr.ip6r.lower.bits[0] = (uint64) pq_getmsgint64(buf); - ipr.ip6r.lower.bits[1] = (uint64) pq_getmsgint64(buf); - ipr.ip6r.upper.bits[0] = ipr.ip6r.lower.bits[0] | hostmask6_hi(bits); - ipr.ip6r.upper.bits[1] = ipr.ip6r.lower.bits[1] | hostmask6_lo(bits); - PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET6,&ipr)); - } - else if (nbytes == sizeof(IP6R)) - { - ipr.ip6r.lower.bits[0] = (uint64) pq_getmsgint64(buf); - ipr.ip6r.lower.bits[1] = (uint64) pq_getmsgint64(buf); - ipr.ip6r.upper.bits[0] = (uint64) pq_getmsgint64(buf); - ipr.ip6r.upper.bits[1] = (uint64) pq_getmsgint64(buf); - PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET6,&ipr)); - } - break; - } - - ereport(ERROR, - (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), - errmsg("invalid address length in external IPR value"))); - PG_RETURN_NULL(); -} - -PG_FUNCTION_INFO_V1(iprange_send); -Datum -iprange_send(PG_FUNCTION_ARGS) -{ - IPR_P *iprp = PG_GETARG_IPR_P(0); - IPR ipr; - int af = ipr_unpack(iprp, &ipr); - StringInfoData buf; - unsigned bits = ~0; - - switch (af) - { - case PGSQL_AF_INET: - bits = masklen(ipr.ip4r.lower,ipr.ip4r.upper); - break; - case PGSQL_AF_INET6: - bits = masklen6(&ipr.ip6r.lower,&ipr.ip6r.upper); - break; - } - - pq_begintypsend(&buf); - pq_sendbyte(&buf, af); - pq_sendbyte(&buf, (int8) bits); - pq_sendbyte(&buf, 1); - - switch (af) - { - case 0: - pq_sendbyte(&buf,0); - break; - - case PGSQL_AF_INET: - if (bits <= ipr_af_maxbits(PGSQL_AF_INET)) - { - pq_sendbyte(&buf, sizeof(IP4)); - pq_sendint(&buf, ipr.ip4r.lower, sizeof(IP4)); - } - else - { - pq_sendbyte(&buf, sizeof(IP4R)); - pq_sendint(&buf, ipr.ip4r.lower, sizeof(IP4)); - pq_sendint(&buf, ipr.ip4r.upper, sizeof(IP4)); - } - break; - - case PGSQL_AF_INET6: - if (bits <= 64) - { - pq_sendbyte(&buf, sizeof(uint64)); - pq_sendint64(&buf, ipr.ip6r.lower.bits[0]); - } - else if (bits <= ipr_af_maxbits(PGSQL_AF_INET6)) - { - pq_sendbyte(&buf, sizeof(IP6)); - pq_sendint64(&buf, ipr.ip6r.lower.bits[0]); - pq_sendint64(&buf, ipr.ip6r.lower.bits[1]); - } - else - { - pq_sendbyte(&buf, sizeof(IP6R)); - pq_sendint64(&buf, ipr.ip6r.lower.bits[0]); - pq_sendint64(&buf, ipr.ip6r.lower.bits[1]); - pq_sendint64(&buf, ipr.ip6r.upper.bits[0]); - pq_sendint64(&buf, ipr.ip6r.upper.bits[1]); - } - break; - } - - PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); -} - -PG_FUNCTION_INFO_V1(iprange_hash); -Datum -iprange_hash(PG_FUNCTION_ARGS) -{ - IPR_P arg1 = PG_GETARG_IPR_P(0); - - return hash_any((void *) VARDATA_ANY(arg1), VARSIZE_ANY_EXHDR(arg1)); -} - -PG_FUNCTION_INFO_V1(iprange_cast_to_text); -Datum -iprange_cast_to_text(PG_FUNCTION_ARGS) -{ - IPR_P iprp = PG_GETARG_IPR_P(0); - IPR ipr; - int af = ipr_unpack(iprp,&ipr); - - switch (af) - { - case 0: - { - text *out = cstring_to_text_with_len("-",1); - PG_RETURN_TEXT_P(out); - } - - case PGSQL_AF_INET: - PG_RETURN_DATUM(DirectFunctionCall1(ip4r_cast_to_text,IP4RPGetDatum(&ipr.ip4r))); - - case PGSQL_AF_INET6: - PG_RETURN_DATUM(DirectFunctionCall1(ip6r_cast_to_text,IP6RPGetDatum(&ipr.ip6r))); - - default: - iprange_internal_error(); - } -} - -PG_FUNCTION_INFO_V1(iprange_cast_from_text); -Datum -iprange_cast_from_text(PG_FUNCTION_ARGS) -{ - text *txt = PG_GETARG_TEXT_PP(0); - int tlen = VARSIZE_ANY_EXHDR(txt); - char buf[IP6R_STRING_MAX]; - - if (tlen < sizeof(buf)) - { - memcpy(buf, VARDATA_ANY(txt), tlen); - buf[tlen] = 0; - - PG_RETURN_DATUM(DirectFunctionCall1(iprange_in, CStringGetDatum(buf))); - } - - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid IPR value in text"))); - PG_RETURN_NULL(); -} - -PG_FUNCTION_INFO_V1(iprange_cast_from_cidr); -Datum -iprange_cast_from_cidr(PG_FUNCTION_ARGS) -{ - inet *inetptr = PG_GETARG_INET_P(0); - inet_struct *in = INET_STRUCT_DATA(inetptr); - unsigned char *p = in->ipaddr; - IPR ipr; - - if (in->bits <= ipr_af_maxbits(in->family)) - { - switch (in->family) - { - case PGSQL_AF_INET: - { - IP4 ip = (p[0] << 24)|(p[1] << 16)|(p[2] << 8)|p[3]; - if (ip4r_from_cidr(ip, in->bits, &ipr.ip4r)) - PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET,&ipr)); - } - break; - - case PGSQL_AF_INET6: - { - IP6 ip; - ip.bits[0] = (((uint64)p[0] << 56) - | ((uint64)p[1] << 48) - | ((uint64)p[2] << 40) - | ((uint64)p[3] << 32) - | ((uint64)p[4] << 24) - | ((uint64)p[5] << 16) - | ((uint64)p[6] << 8) - | p[7]); - ip.bits[1] = (((uint64)p[8] << 56) - | ((uint64)p[9] << 48) - | ((uint64)p[10] << 40) - | ((uint64)p[11] << 32) - | ((uint64)p[12] << 24) - | ((uint64)p[13] << 16) - | ((uint64)p[14] << 8) - | p[15]); - if (ip6r_from_cidr(&ip, in->bits, &ipr.ip6r)) - PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET6,&ipr)); - } - break; - } - } - - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid CIDR value for conversion to IPR"))); - PG_RETURN_NULL(); -} - -PG_FUNCTION_INFO_V1(iprange_cast_to_cidr); -Datum -iprange_cast_to_cidr(PG_FUNCTION_ARGS) -{ - IPR_P iprp = PG_GETARG_IPR_P(0); - IPR ipr; - int af = ipr_unpack(iprp, &ipr); - inet *res; - inet_struct *in; - unsigned bits; - - switch (af) - { - case 0: - PG_RETURN_NULL(); - - case PGSQL_AF_INET: - bits = masklen(ipr.ip4r.lower, ipr.ip4r.upper); - if (bits > ipr_af_maxbits(PGSQL_AF_INET)) - PG_RETURN_NULL(); - - res = palloc0(VARHDRSZ + sizeof(inet_struct)); - SET_VARSIZE(res, VARHDRSZ + offsetof(inet_struct, ipaddr) + 4); - - in = ((inet_struct *)VARDATA(res)); - in->bits = bits; - in->family = PGSQL_AF_INET; - { - unsigned char *p = in->ipaddr; - IP4 ip = ipr.ip4r.lower; - p[0] = (ip >> 24); - p[1] = (ip >> 16); - p[2] = (ip >> 8); - p[3] = (ip ); - } - - PG_RETURN_INET_P(res); - - case PGSQL_AF_INET6: - bits = masklen6(&ipr.ip6r.lower, &ipr.ip6r.upper); - if (bits > ipr_af_maxbits(PGSQL_AF_INET6)) - PG_RETURN_NULL(); - - res = palloc0(VARHDRSZ + sizeof(inet_struct)); - SET_VARSIZE(res, VARHDRSZ + offsetof(inet_struct, ipaddr) + 16); - - in = ((inet_struct *)VARDATA(res)); - in->bits = bits; - in->family = PGSQL_AF_INET6; - { - unsigned char *p = in->ipaddr; - uint64 b = ipr.ip6r.lower.bits[0]; - p[0] = (b >> 56); - p[1] = (b >> 48); - p[2] = (b >> 40); - p[3] = (b >> 32); - p[4] = (b >> 24); - p[5] = (b >> 16); - p[6] = (b >> 8); - p[7] = (b); - b = ipr.ip6r.lower.bits[1]; - p[8] = (b >> 56); - p[9] = (b >> 48); - p[10] = (b >> 40); - p[11] = (b >> 32); - p[12] = (b >> 24); - p[13] = (b >> 16); - p[14] = (b >> 8); - p[15] = (b); - } - - PG_RETURN_INET_P(res); - - default: - iprange_internal_error(); - } -} - -PG_FUNCTION_INFO_V1(iprange_cast_from_ip4); -Datum -iprange_cast_from_ip4(PG_FUNCTION_ARGS) -{ - IP4 ip = PG_GETARG_IP4(0); - IPR res; - - if (ip4r_from_inet(ip, 32, &res.ip4r)) - PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET, &res)); - - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid IP4 value for conversion to IPR (shouldn't be possible)"))); - PG_RETURN_NULL(); -} - -PG_FUNCTION_INFO_V1(iprange_cast_from_ip6); -Datum -iprange_cast_from_ip6(PG_FUNCTION_ARGS) -{ - IP6 *ip = PG_GETARG_IP6_P(0); - IPR res; - - if (ip6r_from_inet(ip, 128, &res.ip6r)) - PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET6, &res)); - - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid IP6 value for conversion to IPR (shouldn't be possible)"))); - PG_RETURN_NULL(); -} - -PG_FUNCTION_INFO_V1(iprange_cast_from_ipaddr); -Datum -iprange_cast_from_ipaddr(PG_FUNCTION_ARGS) -{ - IP_P ipp = PG_GETARG_IP_P(0); - IP ip; - IPR res; - int af = ip_unpack(ipp, &ip); - - switch (af) - { - case PGSQL_AF_INET: - if (ip4r_from_inet(ip.ip4, 32, &res.ip4r)) - PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET, &res)); - break; - - case PGSQL_AF_INET6: - if (ip6r_from_inet(&ip.ip6, 128, &res.ip6r)) - PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET6, &res)); - break; - } - - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid IP6 value for conversion to IPR (shouldn't be possible)"))); - PG_RETURN_NULL(); -} - -PG_FUNCTION_INFO_V1(iprange_cast_from_ip4r); -Datum -iprange_cast_from_ip4r(PG_FUNCTION_ARGS) -{ - IP4R *ipr = PG_GETARG_IP4R_P(0); - IPR res; - - res.ip4r = *ipr; - PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET, &res)); -} - -PG_FUNCTION_INFO_V1(iprange_cast_from_ip6r); -Datum -iprange_cast_from_ip6r(PG_FUNCTION_ARGS) -{ - IP6R *ipr = PG_GETARG_IP6R_P(0); - IPR res; - - res.ip6r = *ipr; - PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET6, &res)); -} - -PG_FUNCTION_INFO_V1(iprange_cast_to_ip4r); -Datum -iprange_cast_to_ip4r(PG_FUNCTION_ARGS) -{ - IPR_P iprp = PG_GETARG_IPR_P(0); - IPR ipr; - int af = ipr_unpack(iprp,&ipr); - IP4R *res; - - if (af != PGSQL_AF_INET) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid IPR value for conversion to IP4R"))); - - res = palloc(sizeof(IP4R)); - *res = ipr.ip4r; - - PG_RETURN_IP4R_P(res); -} - -PG_FUNCTION_INFO_V1(iprange_cast_to_ip6r); -Datum -iprange_cast_to_ip6r(PG_FUNCTION_ARGS) -{ - IPR_P iprp = PG_GETARG_IPR_P(0); - IPR ipr; - int af = ipr_unpack(iprp,&ipr); - IP6R *res; - - if (af != PGSQL_AF_INET6) - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid IPR value for conversion to IP6R"))); - - res = palloc(sizeof(IP6R)); - *res = ipr.ip6r; - - PG_RETURN_IP6R_P(res); -} - - -static -Datum -iprange_from_ipaddrs_internal(int af, IP4 a4, IP4 b4, IP6 *a6, IP6 *b6) -{ - IPR res; - - switch (af) - { - case PGSQL_AF_INET: - if (ip4_lessthan(a4,b4)) - res.ip4r.lower = a4, res.ip4r.upper = b4; - else - res.ip4r.lower = b4, res.ip4r.upper = a4; - PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET,&res)); - - case PGSQL_AF_INET6: - if (ip6_lessthan(a6,b6)) - res.ip6r.lower = *a6, res.ip6r.upper = *b6; - else - res.ip6r.lower = *b6, res.ip6r.upper = *a6; - PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET6,&res)); - - default: - iprange_internal_error(); - } -} - -PG_FUNCTION_INFO_V1(iprange_from_ip4s); -Datum -iprange_from_ip4s(PG_FUNCTION_ARGS) -{ - IP4 a = PG_GETARG_IP4(0); - IP4 b = PG_GETARG_IP4(1); - - PG_RETURN_DATUM(iprange_from_ipaddrs_internal(PGSQL_AF_INET, a, b, NULL, NULL)); -} - -PG_FUNCTION_INFO_V1(iprange_from_ip6s); -Datum -iprange_from_ip6s(PG_FUNCTION_ARGS) -{ - IP6 *a = PG_GETARG_IP6_P(0); - IP6 *b = PG_GETARG_IP6_P(1); - - PG_RETURN_DATUM(iprange_from_ipaddrs_internal(PGSQL_AF_INET6, 0, 0, a, b)); -} - -PG_FUNCTION_INFO_V1(iprange_from_ipaddrs); -Datum -iprange_from_ipaddrs(PG_FUNCTION_ARGS) -{ - IP_P ap = PG_GETARG_IP_P(0); - IP_P bp = PG_GETARG_IP_P(1); - IP a,b; - int af_a = ip_unpack(ap,&a); - int af_b = ip_unpack(bp,&b); - - if (af_a != af_b) - iprange_af_mismatch(); - - PG_RETURN_DATUM(iprange_from_ipaddrs_internal(af_a, a.ip4, b.ip4, &a.ip6, &b.ip6)); -} - - -static Datum -iprange_net_prefix_internal(int af, IP4 ip4, IP6 *ip6, int pfxlen) -{ - IPR res; - - if (pfxlen < 0 || pfxlen > ipr_af_maxbits(af)) - { - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("prefix length out of range"))); - } - - switch (af) - { - case PGSQL_AF_INET: - ip4r_from_inet(ip4, (unsigned)pfxlen, &res.ip4r); - break; - case PGSQL_AF_INET6: - ip6r_from_inet(ip6, (unsigned)pfxlen, &res.ip6r); - break; - default: - iprange_internal_error(); - } - - PG_RETURN_IPR_P(ipr_pack(af,&res)); -} - -PG_FUNCTION_INFO_V1(iprange_net_prefix_ip4); -Datum -iprange_net_prefix_ip4(PG_FUNCTION_ARGS) -{ - IP4 ip = PG_GETARG_IP4(0); - int pfxlen = PG_GETARG_INT32(1); - - PG_RETURN_DATUM(iprange_net_prefix_internal(PGSQL_AF_INET, ip, NULL, pfxlen)); -} - -PG_FUNCTION_INFO_V1(iprange_net_prefix_ip6); -Datum -iprange_net_prefix_ip6(PG_FUNCTION_ARGS) -{ - IP6 *ip = PG_GETARG_IP6_P(0); - int pfxlen = PG_GETARG_INT32(1); - - PG_RETURN_DATUM(iprange_net_prefix_internal(PGSQL_AF_INET6, 0, ip, pfxlen)); -} - -PG_FUNCTION_INFO_V1(iprange_net_prefix); -Datum -iprange_net_prefix(PG_FUNCTION_ARGS) -{ - IP_P ipp = PG_GETARG_IP_P(0); - IP ip; - int pfxlen = PG_GETARG_INT32(1); - int af = ip_unpack(ipp,&ip); - - PG_RETURN_DATUM(iprange_net_prefix_internal(af, ip.ip4, &ip.ip6, pfxlen)); -} - - -static Datum -iprange_net_mask_internal(int af, IP4 ip4, IP6 *ip6, IP4 mask4, IP6 *mask6) -{ - IPR res; - - switch (af) - { - case PGSQL_AF_INET: - if (!ip4_valid_netmask(mask4)) - break; - - res.ip4r.lower = ip4 & mask4; - res.ip4r.upper = ip4 | ~mask4; - - PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET,&res)); - - case PGSQL_AF_INET6: - if (!ip6_valid_netmask(mask6->bits[0], mask6->bits[1])) - break; - - res.ip6r.lower.bits[0] = ip6->bits[0] & mask6->bits[0]; - res.ip6r.lower.bits[1] = ip6->bits[1] & mask6->bits[1]; - res.ip6r.upper.bits[0] = ip6->bits[0] | ~(mask6->bits[0]); - res.ip6r.upper.bits[1] = ip6->bits[1] | ~(mask6->bits[1]); - - PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET6,&res)); - } - - ereport(ERROR, - (errcode(ERRCODE_INVALID_PARAMETER_VALUE), - errmsg("invalid netmask"))); - PG_RETURN_VOID(); -} - -PG_FUNCTION_INFO_V1(iprange_net_mask_ip4); -Datum -iprange_net_mask_ip4(PG_FUNCTION_ARGS) -{ - IP4 ip = PG_GETARG_IP4(0); - IP4 mask = PG_GETARG_IP4(1); - - PG_RETURN_DATUM(iprange_net_mask_internal(PGSQL_AF_INET, ip, NULL, mask, NULL)); -} - -PG_FUNCTION_INFO_V1(iprange_net_mask_ip6); -Datum -iprange_net_mask_ip6(PG_FUNCTION_ARGS) -{ - IP6 *ip = PG_GETARG_IP6_P(0); - IP6 *mask = PG_GETARG_IP6_P(1); - - PG_RETURN_DATUM(iprange_net_mask_internal(PGSQL_AF_INET6, 0, ip, 0, mask)); -} - -PG_FUNCTION_INFO_V1(iprange_net_mask); -Datum -iprange_net_mask(PG_FUNCTION_ARGS) -{ - IP_P ipp = PG_GETARG_IP_P(0); - IP_P maskp = PG_GETARG_IP_P(1); - IP ip XINIT(IP_INITIALIZER); - IP mask XINIT(IP_INITIALIZER); - int af1 = ip_unpack(ipp,&ip); - int af2 = ip_unpack(maskp,&mask); - - if (af1 != af2) - iprange_af_mismatch(); - - PG_RETURN_DATUM(iprange_net_mask_internal(af1, ip.ip4, &ip.ip6, mask.ip4, &mask.ip6)); -} - - -PG_FUNCTION_INFO_V1(iprange_lower); -Datum -iprange_lower(PG_FUNCTION_ARGS) -{ - IPR_P iprp = PG_GETARG_IPR_P(0); - IPR ipr; - IP ip; - int af = ipr_unpack(iprp,&ipr); - - switch (af) - { - case 0: - ip.ip4 = 0; - PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET,&ip)); - - case PGSQL_AF_INET: - ip.ip4 = ipr.ip4r.lower; - PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET,&ip)); - - case PGSQL_AF_INET6: - ip.ip6 = ipr.ip6r.lower; - PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET6,&ip)); - - default: - iprange_internal_error(); - } -} - -PG_FUNCTION_INFO_V1(iprange_upper); -Datum -iprange_upper(PG_FUNCTION_ARGS) -{ - IPR_P iprp = PG_GETARG_IPR_P(0); - IPR ipr; - IP ip; - int af = ipr_unpack(iprp,&ipr); - - switch (af) - { - case 0: - ip.ip6.bits[0] = ip.ip6.bits[1] = ~(uint64)0; - PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET6,&ip)); - - case PGSQL_AF_INET: - ip.ip4 = ipr.ip4r.upper; - PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET,&ip)); - - case PGSQL_AF_INET6: - ip.ip6 = ipr.ip6r.upper; - PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET6,&ip)); - - default: - iprange_internal_error(); - } -} - -PG_FUNCTION_INFO_V1(iprange_is_cidr); -Datum -iprange_is_cidr(PG_FUNCTION_ARGS) -{ - IPR_P iprp = PG_GETARG_IPR_P(0); - IPR ipr; - int af = ipr_unpack(iprp,&ipr); - - switch (af) - { - case 0: - PG_RETURN_BOOL(false); - - case PGSQL_AF_INET: - PG_RETURN_BOOL( (masklen(ipr.ip4r.lower,ipr.ip4r.upper) <= 32U) ); - - case PGSQL_AF_INET6: - PG_RETURN_BOOL( (masklen6(&ipr.ip6r.lower,&ipr.ip6r.upper) <= 128U) ); - - default: - iprange_internal_error(); - } -} - -PG_FUNCTION_INFO_V1(iprange_family); -Datum -iprange_family(PG_FUNCTION_ARGS) -{ - IPR_P iprp = PG_GETARG_IPR_P(0); - IPR ipr; - int af = ipr_unpack(iprp,&ipr); - - switch (af) - { - case 0: - PG_RETURN_NULL(); - - case PGSQL_AF_INET: - PG_RETURN_INT32(4); - - case PGSQL_AF_INET6: - PG_RETURN_INT32(6); - - default: - iprange_internal_error(); - } -} - - -static int -iprange_cmp_internal(Datum d1, Datum d2) -{ - IPR_P ipp1 = DatumGetIPR_P(d1); - IPR_P ipp2 = DatumGetIPR_P(d2); - IPR ipr1 XINIT(IPR_INITIALIZER); - IPR ipr2 XINIT(IPR_INITIALIZER); - int af1 = ipr_unpack(ipp1, &ipr1); - int af2 = ipr_unpack(ipp2, &ipr2); - int retval = 0; - - if (af1 == af2) - { - switch (af1) - { - case 0: - break; - - case PGSQL_AF_INET: - if (ip4r_lessthan(&ipr1.ip4r,&ipr2.ip4r)) - retval = -1; - else if (ip4r_lessthan(&ipr2.ip4r,&ipr1.ip4r)) - retval = 1; - break; - - case PGSQL_AF_INET6: - if (ip6r_lessthan(&ipr1.ip6r,&ipr2.ip6r)) - retval = -1; - else if (ip6r_lessthan(&ipr2.ip6r,&ipr1.ip6r)) - retval = 1; - break; - - default: - iprange_internal_error(); - } - } - else if (af1 < af2) - retval = -1; - else - retval = 1; - - if ((Pointer)ipp1 != DatumGetPointer(d1)) - pfree(ipp1); - if ((Pointer)ipp2 != DatumGetPointer(d2)) - pfree(ipp2); - - return retval; -} - -PG_FUNCTION_INFO_V1(iprange_lt); -Datum -iprange_lt(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( iprange_cmp_internal(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1)) < 0 ); -} - -PG_FUNCTION_INFO_V1(iprange_le); -Datum -iprange_le(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( iprange_cmp_internal(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1)) <= 0 ); -} - -PG_FUNCTION_INFO_V1(iprange_gt); -Datum -iprange_gt(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( iprange_cmp_internal(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1)) > 0 ); -} - -PG_FUNCTION_INFO_V1(iprange_ge); -Datum -iprange_ge(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( iprange_cmp_internal(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1)) >= 0 ); -} - -PG_FUNCTION_INFO_V1(iprange_eq); -Datum -iprange_eq(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( iprange_cmp_internal(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1)) == 0 ); -} - -PG_FUNCTION_INFO_V1(iprange_neq); -Datum -iprange_neq(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( iprange_cmp_internal(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1)) != 0 ); -} - -static bool -iprange_overlaps_internal(Datum d1, Datum d2) -{ - IPR_P ipp1 = DatumGetIPR_P(d1); - IPR_P ipp2 = DatumGetIPR_P(d2); - IPR ipr1 XINIT(IPR_INITIALIZER); - IPR ipr2 XINIT(IPR_INITIALIZER); - int af1 = ipr_unpack(ipp1, &ipr1); - int af2 = ipr_unpack(ipp2, &ipr2); - bool retval; - - if (af1 == af2) - { - switch (af1) - { - case 0: - retval = true; - break; - - case PGSQL_AF_INET: - retval = ip4r_overlaps_internal(&ipr1.ip4r,&ipr2.ip4r); - break; - - case PGSQL_AF_INET6: - retval = ip6r_overlaps_internal(&ipr1.ip6r,&ipr2.ip6r); - break; - - default: - iprange_internal_error(); - } - } - else - retval = (af1 == 0) || (af2 == 0); - - if ((Pointer)ipp1 != DatumGetPointer(d1)) - pfree(ipp1); - if ((Pointer)ipp2 != DatumGetPointer(d2)) - pfree(ipp2); - - return retval; -} - -static int -iprange_contains_internal(Datum d1, Datum d2, bool eqval) -{ - IPR_P ipp1 = DatumGetIPR_P(d1); - IPR_P ipp2 = DatumGetIPR_P(d2); - IPR ipr1 XINIT(IPR_INITIALIZER); - IPR ipr2 XINIT(IPR_INITIALIZER); - int af1 = ipr_unpack(ipp1, &ipr1); - int af2 = ipr_unpack(ipp2, &ipr2); - bool retval; - - if (af1 == af2) - { - switch (af1) - { - case 0: - retval = eqval; - break; - - case PGSQL_AF_INET: - retval = ip4r_contains_internal(&ipr1.ip4r,&ipr2.ip4r,eqval); - break; - - case PGSQL_AF_INET6: - retval = ip6r_contains_internal(&ipr1.ip6r,&ipr2.ip6r,eqval); - break; - - default: - iprange_internal_error(); - } - } - else - retval = (af1 == 0); - - if ((Pointer)ipp1 != DatumGetPointer(d1)) - pfree(ipp1); - if ((Pointer)ipp2 != DatumGetPointer(d2)) - pfree(ipp2); - - return retval; -} - -static int -iprange_contains_ip_internal(Datum d1, int af2, IP4 ip4, IP6 *ip6) -{ - IPR_P ipp1 = DatumGetIPR_P(d1); - IPR ipr1 XINIT(IPR_INITIALIZER); - int af1 = ipr_unpack(ipp1, &ipr1); - bool retval; - - if (af1 == af2) - { - switch (af1) - { - case 0: - retval = true; - break; - - case PGSQL_AF_INET: - retval = ip4_contains_internal(&ipr1.ip4r,ip4); - break; - - case PGSQL_AF_INET6: - retval = ip6_contains_internal(&ipr1.ip6r,ip6); - break; - - default: - iprange_internal_error(); - } - } - else - retval = (af1 == 0); - - if ((Pointer)ipp1 != DatumGetPointer(d1)) - pfree(ipp1); - - return retval; -} - -PG_FUNCTION_INFO_V1(iprange_overlaps); -Datum -iprange_overlaps(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( iprange_overlaps_internal(PG_GETARG_DATUM(0), - PG_GETARG_DATUM(1)) ); -} - -PG_FUNCTION_INFO_V1(iprange_contains); -Datum -iprange_contains(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( iprange_contains_internal(PG_GETARG_DATUM(0), - PG_GETARG_DATUM(1), - TRUE) ); -} - -PG_FUNCTION_INFO_V1(iprange_contains_strict); -Datum -iprange_contains_strict(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( iprange_contains_internal(PG_GETARG_DATUM(0), - PG_GETARG_DATUM(1), - FALSE) ); -} - -PG_FUNCTION_INFO_V1(iprange_contained_by); -Datum -iprange_contained_by(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( iprange_contains_internal(PG_GETARG_DATUM(1), - PG_GETARG_DATUM(0), - TRUE) ); -} - -PG_FUNCTION_INFO_V1(iprange_contained_by_strict); -Datum -iprange_contained_by_strict(PG_FUNCTION_ARGS) -{ - PG_RETURN_BOOL( iprange_contains_internal(PG_GETARG_DATUM(1), - PG_GETARG_DATUM(0), - FALSE) ); -} - -PG_FUNCTION_INFO_V1(iprange_contains_ip); -Datum -iprange_contains_ip(PG_FUNCTION_ARGS) -{ - IP_P ipp = PG_GETARG_IP_P(1); - IP ip XINIT(IP_INITIALIZER); - int af = ip_unpack(ipp,&ip); - bool retval = iprange_contains_ip_internal(PG_GETARG_DATUM(0), af, ip.ip4, &ip.ip6); - - PG_FREE_IF_COPY(ipp,1); - PG_RETURN_BOOL(retval); -} - -PG_FUNCTION_INFO_V1(iprange_contains_ip4); -Datum -iprange_contains_ip4(PG_FUNCTION_ARGS) -{ - IP4 ip = PG_GETARG_IP4(1); - PG_RETURN_BOOL(iprange_contains_ip_internal(PG_GETARG_DATUM(0), PGSQL_AF_INET, ip, NULL)); -} - -PG_FUNCTION_INFO_V1(iprange_contains_ip6); -Datum -iprange_contains_ip6(PG_FUNCTION_ARGS) -{ - IP6 *ip = PG_GETARG_IP6_P(1); - PG_RETURN_BOOL(iprange_contains_ip_internal(PG_GETARG_DATUM(0), PGSQL_AF_INET6, 0, ip)); -} - -PG_FUNCTION_INFO_V1(iprange_ip6_contained_by); -Datum -iprange_ip6_contained_by(PG_FUNCTION_ARGS) -{ - IP6 *ip = PG_GETARG_IP6_P(0); - PG_RETURN_BOOL( iprange_contains_ip_internal(PG_GETARG_DATUM(1), PGSQL_AF_INET6, 0, ip) ); -} - -PG_FUNCTION_INFO_V1(iprange_ip4_contained_by); -Datum -iprange_ip4_contained_by(PG_FUNCTION_ARGS) -{ - IP4 ip = PG_GETARG_IP4(0); - PG_RETURN_BOOL( iprange_contains_ip_internal(PG_GETARG_DATUM(1), PGSQL_AF_INET, ip, NULL) ); -} - -PG_FUNCTION_INFO_V1(iprange_ip_contained_by); -Datum -iprange_ip_contained_by(PG_FUNCTION_ARGS) -{ - IP_P ipp = PG_GETARG_IP_P(0); - IP ip XINIT(IP_INITIALIZER); - int af = ip_unpack(ipp,&ip); - bool retval = iprange_contains_ip_internal(PG_GETARG_DATUM(1), af, ip.ip4, &ip.ip6); - - PG_FREE_IF_COPY(ipp,0); - PG_RETURN_BOOL(retval); -} - -PG_FUNCTION_INFO_V1(iprange_union); -Datum -iprange_union(PG_FUNCTION_ARGS) -{ - IPR_P ipp1 = PG_GETARG_IPR_P(0); - IPR_P ipp2 = PG_GETARG_IPR_P(1); - IPR ipr1; - IPR ipr2; - int af1 = ipr_unpack(ipp1, &ipr1); - int af2 = ipr_unpack(ipp2, &ipr2); - IPR res; - - if (af1 == af2) - { - switch (af1) - { - case 0: - PG_RETURN_IPR_P(ipr_pack(0,NULL)); - - case PGSQL_AF_INET: - ip4r_union_internal(&ipr1.ip4r,&ipr2.ip4r,&res.ip4r); - PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET,&res)); - - case PGSQL_AF_INET6: - ip6r_union_internal(&ipr1.ip6r,&ipr2.ip6r,&res.ip6r); - PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET6,&res)); - - default: - iprange_internal_error(); - } - } - else - PG_RETURN_IPR_P(ipr_pack(0,NULL)); -} - -PG_FUNCTION_INFO_V1(iprange_inter); -Datum -iprange_inter(PG_FUNCTION_ARGS) -{ - IPR_P ipp1 = PG_GETARG_IPR_P(0); - IPR_P ipp2 = PG_GETARG_IPR_P(1); - IPR ipr1; - IPR ipr2; - int af1 = ipr_unpack(ipp1, &ipr1); - int af2 = ipr_unpack(ipp2, &ipr2); - IPR res; - - if (af1 == af2) - { - switch (af1) - { - case 0: - PG_RETURN_IPR_P(ipr_pack(0,NULL)); - - case PGSQL_AF_INET: - if (ip4r_inter_internal(&ipr1.ip4r,&ipr2.ip4r,&res.ip4r)) - PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET,&res)); - break; - - case PGSQL_AF_INET6: - if (ip6r_inter_internal(&ipr1.ip6r,&ipr2.ip6r,&res.ip6r)) - PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET6,&res)); - break; - - default: - iprange_internal_error(); - } - } - else if (af1 == 0) - PG_RETURN_IPR_P(ipr_pack(af2,&ipr2)); - else if (af2 == 0) - PG_RETURN_IPR_P(ipr_pack(af1,&ipr1)); - - PG_RETURN_NULL(); -} - -PG_FUNCTION_INFO_V1(iprange_size); -Datum -iprange_size(PG_FUNCTION_ARGS) -{ - IPR_P ipp = PG_GETARG_IPR_P(0); - IPR ipr; - int af = ipr_unpack(ipp, &ipr); - - switch (af) - { - case 0: - PG_RETURN_FLOAT8(ldexp(1.0, 129)); - - case PGSQL_AF_INET: - PG_RETURN_FLOAT8(ip4r_metric(&ipr.ip4r)); - - case PGSQL_AF_INET6: - PG_RETURN_FLOAT8(ip6r_metric(&ipr.ip6r)); - - default: - iprange_internal_error(); - } -} - -PG_FUNCTION_INFO_V1(iprange_size_exact); -Datum -iprange_size_exact(PG_FUNCTION_ARGS) -{ - IPR_P ipp = PG_GETARG_IPR_P(0); - IPR ipr; - int af = ipr_unpack(ipp, &ipr); - Datum u,l,d,s; - - switch (af) - { - case 0: - s = DirectFunctionCall3(numeric_in, CStringGetDatum("680564733841876926926749214863536422912"), 0, Int32GetDatum(-1)); - PG_RETURN_DATUM(s); - - case PGSQL_AF_INET: - l = DirectFunctionCall1(ip4_cast_to_numeric, IP4GetDatum(ipr.ip4r.lower)); - u = DirectFunctionCall1(ip4_cast_to_numeric, IP4GetDatum(ipr.ip4r.upper)); - break; - - case PGSQL_AF_INET6: - l = DirectFunctionCall1(ip6_cast_to_numeric, IP6PGetDatum(&ipr.ip6r.lower)); - u = DirectFunctionCall1(ip6_cast_to_numeric, IP6PGetDatum(&ipr.ip6r.upper)); - break; - - default: - iprange_internal_error(); - } - - d = DirectFunctionCall2(numeric_sub, u, l); - s = DirectFunctionCall1(numeric_inc, d); - PG_RETURN_DATUM(s); -} - -PG_FUNCTION_INFO_V1(iprange_prefixlen); -Datum -iprange_prefixlen(PG_FUNCTION_ARGS) -{ - IPR_P iprp = PG_GETARG_IPR_P(0); - IPR ipr; - int af = ipr_unpack(iprp,&ipr); - unsigned len = ~0; - unsigned maxbits = 0; - - if (af == PGSQL_AF_INET) - maxbits = 32, len = masklen(ipr.ip4r.lower, ipr.ip4r.upper); - else if (af == PGSQL_AF_INET6) - maxbits = 128, len = masklen6(&ipr.ip6r.lower, &ipr.ip6r.upper); - - if (len <= maxbits) - PG_RETURN_INT32((int32) len); - - PG_RETURN_NULL(); -} - - -/***************************************************************************** - * Btree functions - *****************************************************************************/ - -PG_FUNCTION_INFO_V1(iprange_cmp); -Datum -iprange_cmp(PG_FUNCTION_ARGS) -{ - PG_RETURN_INT32( iprange_cmp_internal(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1)) ); -} - - -/***************************************************************************** - * GiST functions - *****************************************************************************/ - -/* -** GiST support methods -*/ - -Datum gipr_consistent(PG_FUNCTION_ARGS); -Datum gipr_compress(PG_FUNCTION_ARGS); -Datum gipr_decompress(PG_FUNCTION_ARGS); -Datum gipr_penalty(PG_FUNCTION_ARGS); -Datum gipr_picksplit(PG_FUNCTION_ARGS); -Datum gipr_union(PG_FUNCTION_ARGS); -Datum gipr_same(PG_FUNCTION_ARGS); -Datum gipr_fetch(PG_FUNCTION_ARGS); - -typedef struct { - int32 vl_len_; - int32 af; - IPR ipr; -} IPR_KEY; - -static bool gipr_leaf_consistent(IPR_KEY *key, IPR_P query, StrategyNumber strategy); -static bool gipr_internal_consistent(IPR_KEY *key, IPR_P query, StrategyNumber strategy); - - -/* - * compress is passed a GISTENTRY* containing a leaf or nonleaf key, and is - * expected to return either the same entry or a new one containing the data to - * be actually written to the index tuple. The key is a leaf key if and only if - * it came from outside GiST (via insert or bulkinsert). - */ - -PG_FUNCTION_INFO_V1(gipr_compress); -Datum -gipr_compress(PG_FUNCTION_ARGS) -{ - GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); - GISTENTRY *retval = entry; - - if (!entry->leafkey) - { - IPR_KEY *key = (IPR_KEY *) DatumGetPointer(entry->key); - - retval = palloc(sizeof(GISTENTRY)); - - Assert(!VARATT_IS_EXTENDED(key) && VARSIZE(key) == sizeof(IPR_KEY)); - Assert(key->af == 0 || key->af == PGSQL_AF_INET || key->af == PGSQL_AF_INET6); - - gistentryinit(*retval, PointerGetDatum(ipr_pack(key->af, &key->ipr)), - entry->rel, entry->page, - entry->offset, FALSE); - } - - PG_RETURN_POINTER(retval); -} - -PG_FUNCTION_INFO_V1(gipr_decompress); -Datum -gipr_decompress(PG_FUNCTION_ARGS) -{ - GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); - GISTENTRY *retval = palloc(sizeof(GISTENTRY)); - IPR_KEY *key = palloc(sizeof(IPR_KEY)); - - SET_VARSIZE(key, sizeof(IPR_KEY)); - key->af = ipr_unpack((IPR_P) DatumGetPointer(entry->key), &key->ipr); - - gistentryinit(*retval, PointerGetDatum(key), - entry->rel, entry->page, - entry->offset, FALSE); - - PG_RETURN_POINTER(retval); -} - -PG_FUNCTION_INFO_V1(gipr_fetch); -Datum -gipr_fetch(PG_FUNCTION_ARGS) -{ - PG_RETURN_POINTER(PG_GETARG_POINTER(0)); -} - - -/* -** The GiST Consistent method for IP ranges -** Should return false if for all data items x below entry, -** the predicate x op query == FALSE, where op is the oper -** corresponding to strategy in the pg_amop table. -*/ - -PG_FUNCTION_INFO_V1(gipr_consistent); -Datum -gipr_consistent(PG_FUNCTION_ARGS) -{ - GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); - IPR_P query = (IPR_P) PG_GETARG_POINTER(1); - StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); - bool *recheck = (bool *) PG_GETARG_POINTER(4); - IPR_KEY *key = (IPR_KEY *) DatumGetPointer(entry->key); - bool retval; - - /* recheck is never needed with this type */ - if (recheck) - *recheck = false; - - /* - * * if entry is not leaf, use gipr_internal_consistent, * else use - * gipr_leaf_consistent - */ - - if (GIST_LEAF(entry)) - retval = gipr_leaf_consistent(key, query, strategy); - else - retval = gipr_internal_consistent(key, query, strategy); - - PG_RETURN_BOOL(retval); -} - -/* -** The GiST Union method for IP ranges -** returns the minimal bounding IPR that encloses all the entries in entryvec -*/ - -static void -gipr_union_internal_1(IPR_KEY *out, IPR_KEY *tmp) -{ - if (out->af != tmp->af) - out->af = 0; - - switch (out->af) - { - case 0: - break; - - case PGSQL_AF_INET: - { - if (ip4_lessthan(tmp->ipr.ip4r.lower,out->ipr.ip4r.lower)) - out->ipr.ip4r.lower = tmp->ipr.ip4r.lower; - if (ip4_lessthan(out->ipr.ip4r.upper,tmp->ipr.ip4r.upper)) - out->ipr.ip4r.upper = tmp->ipr.ip4r.upper; - break; - } - - case PGSQL_AF_INET6: - { - if (ip6_lessthan(&tmp->ipr.ip6r.lower,&out->ipr.ip6r.lower)) - out->ipr.ip6r.lower = tmp->ipr.ip6r.lower; - if (ip6_lessthan(&out->ipr.ip6r.upper,&tmp->ipr.ip6r.upper)) - out->ipr.ip6r.upper = tmp->ipr.ip6r.upper; - break; - } - - default: - iprange_internal_error(); - } -} - -static void -gipr_union_internal(IPR_KEY *out, bool *allequalp, bool *afequalp, - GISTENTRY *ent, int numranges) -{ - int i; - bool allequal = true; - bool afequal = true; - IPR_KEY *tmp; - - tmp = (IPR_KEY *) DatumGetPointer(ent[0].key); - *out = *tmp; - - for (i = 1; out->af != 0 && i < numranges; ++i) - { - tmp = (IPR_KEY *) DatumGetPointer(ent[i].key); - if (tmp->af != out->af) - { - out->af = 0; - afequal = allequal = false; - } - } - - switch (out->af) - { - case 0: - break; - - case PGSQL_AF_INET: - { - tmp = (IPR_KEY *) DatumGetPointer(ent[0].key); - out->ipr.ip4r = tmp->ipr.ip4r; - - for (i = 1; i < numranges; i++) - { - tmp = (IPR_KEY *) DatumGetPointer(ent[i].key); - - if (allequal && !ip4r_equal(&tmp->ipr.ip4r, &out->ipr.ip4r)) - allequal = false; - - if (ip4_lessthan(tmp->ipr.ip4r.lower,out->ipr.ip4r.lower)) - out->ipr.ip4r.lower = tmp->ipr.ip4r.lower; - if (ip4_lessthan(out->ipr.ip4r.upper,tmp->ipr.ip4r.upper)) - out->ipr.ip4r.upper = tmp->ipr.ip4r.upper; - } - break; - } - - case PGSQL_AF_INET6: - { - tmp = (IPR_KEY *) DatumGetPointer(ent[0].key); - out->ipr.ip4r = tmp->ipr.ip4r; - - for (i = 1; i < numranges; i++) - { - tmp = (IPR_KEY *) DatumGetPointer(ent[i].key); - - if (allequal && !ip6r_equal(&tmp->ipr.ip6r, &out->ipr.ip6r)) - allequal = false; - - if (ip6_lessthan(&tmp->ipr.ip6r.lower,&out->ipr.ip6r.lower)) - out->ipr.ip6r.lower = tmp->ipr.ip6r.lower; - if (ip6_lessthan(&out->ipr.ip6r.upper,&tmp->ipr.ip6r.upper)) - out->ipr.ip6r.upper = tmp->ipr.ip6r.upper; - } - break; - } - - default: - iprange_internal_error(); - } - - if (afequalp) - *afequalp = afequal; - if (allequalp) - *allequalp = allequal; -} - - -PG_FUNCTION_INFO_V1(gipr_union); -Datum -gipr_union(PG_FUNCTION_ARGS) -{ - GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0); - int *sizep = (int *) PG_GETARG_POINTER(1); - GISTENTRY *ent = GISTENTRYVEC(entryvec); - int numranges; - IPR_KEY *out = palloc(sizeof(IPR_KEY)); - -#ifdef GIST_DEBUG - fprintf(stderr, "union\n"); -#endif - - numranges = GISTENTRYCOUNT(entryvec); - - gipr_union_internal(out, NULL, NULL, ent, numranges); - - *sizep = sizeof(IPR_KEY); - - PG_RETURN_POINTER(out); -} - - -/* -** The GiST Penalty method for IP ranges -** As in the R-tree paper, we use change in area as our penalty metric -*/ -PG_FUNCTION_INFO_V1(gipr_penalty); -Datum -gipr_penalty(PG_FUNCTION_ARGS) -{ - GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0); - GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1); - float *result = (float *) PG_GETARG_POINTER(2); - IPR_KEY *key = (IPR_KEY *) DatumGetPointer(origentry->key); - IPR_KEY *newkey = (IPR_KEY *) DatumGetPointer(newentry->key); - IP4R ud4; - IP6R ud6; - double tmp = 0.0; - - if (key->af != newkey->af) - { - if (key->af != 0 && newkey->af != 0) - tmp = 1e10; - } - else - { - switch (key->af) - { - case 0: - break; - - /* - * rather than subtract the sizes, which might lose - * due to rounding errors in v6, we calculate the - * actual number of addresses added to the range. - */ - - case PGSQL_AF_INET: - if (newkey->ipr.ip4r.lower < key->ipr.ip4r.lower) - { - ud4.lower = newkey->ipr.ip4r.lower; - ud4.upper = key->ipr.ip4r.lower - 1; - tmp = ip4r_metric(&ud4); - } - if (key->ipr.ip4r.upper < newkey->ipr.ip4r.upper) - { - ud4.lower = key->ipr.ip4r.upper; - ud4.upper = newkey->ipr.ip4r.upper - 1; - tmp += ip4r_metric(&ud4); - } - break; - - case PGSQL_AF_INET6: - if (ip6_lessthan(&newkey->ipr.ip6r.lower,&key->ipr.ip6r.lower)) - { - ud6.lower = newkey->ipr.ip6r.lower; - ud6.upper = key->ipr.ip6r.lower; - ip6_sub_int(&ud6.upper,1,&ud6.upper); - tmp = ip6r_metric(&ud6); - } - if (ip6_lessthan(&key->ipr.ip6r.upper,&newkey->ipr.ip6r.upper)) - { - ud6.lower = key->ipr.ip6r.upper; - ud6.upper = newkey->ipr.ip6r.upper; - ip6_sub_int(&ud6.upper,1,&ud6.upper); - tmp += ip6r_metric(&ud6); - } - - /* - * we want to scale the result a bit. For one thing, the gist code implicitly - * assigns a penalty of 1e10 for a union of null and non-null values, and we - * want to keep our values less than that. For another, the penalty is sometimes - * summed across columns of a multi-column index, and we don't want our huge - * metrics (>2^80) to completely swamp anything else. - * - * So, we scale as the fourth power of the log2 of the computed penalty, which - * gives us a range 0 - 268435456. - */ - - tmp = pow(log(tmp+1) / log(2), 4); - break; - - default: - iprange_internal_error(); - } - } - - *result = (float) tmp; - -#ifdef GIST_DEBUG - fprintf(stderr, "penalty\n"); - fprintf(stderr, "\t%g\n", *result); -#endif - - PG_RETURN_POINTER(result); -} - - -/* Helper functions for picksplit. We might need to sort a list of - * ranges by size; these are for that. We don't ever need to sort - * mixed address families though. - */ - -struct gipr_sort -{ - IPR_KEY *key; - OffsetNumber pos; -}; - -static int -gipr_sort_compare_v4(const void *av, const void *bv) -{ - IPR_KEY *a = ((struct gipr_sort *)av)->key; - IPR_KEY *b = ((struct gipr_sort *)bv)->key; - double sa = ip4r_metric(&a->ipr.ip4r); - double sb = ip4r_metric(&b->ipr.ip4r); - return (sa > sb) ? 1 : ((sa == sb) ? 0 : -1); -} - -static int -gipr_sort_compare_v6(const void *av, const void *bv) -{ - IPR_KEY *a = ((struct gipr_sort *)av)->key; - IPR_KEY *b = ((struct gipr_sort *)bv)->key; - double sa = ip6r_metric(&a->ipr.ip6r); - double sb = ip6r_metric(&b->ipr.ip6r); - return (sa > sb) ? 1 : ((sa == sb) ? 0 : -1); -} - -/* -** The GiST PickSplit method for IP ranges -** This is a linear-time algorithm based on a left/right split, -** based on the box functions in rtree_gist simplified to one -** dimension -*/ -PG_FUNCTION_INFO_V1(gipr_picksplit); -Datum -gipr_picksplit(PG_FUNCTION_ARGS) -{ - GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0); - GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1); - GISTENTRY *ent = GISTENTRYVEC(entryvec); - OffsetNumber i; - int nbytes; - OffsetNumber maxoff; - OffsetNumber *listL; - OffsetNumber *listR; - bool allisequal = true; - bool allafequal = true; - IPR_KEY pageunion; - IPR_KEY *cur; - IPR_KEY *unionL; - IPR_KEY *unionR; - int posL = 0; - int posR = 0; - - posL = posR = 0; - maxoff = GISTENTRYCOUNT(entryvec) - 1; - - gipr_union_internal(&pageunion, &allisequal, &allafequal, - &ent[FirstOffsetNumber], maxoff); - - nbytes = (maxoff + 2) * sizeof(OffsetNumber); - listL = (OffsetNumber *) palloc(nbytes); - listR = (OffsetNumber *) palloc(nbytes); - unionL = palloc(sizeof(IPR_KEY)); - unionR = palloc(sizeof(IPR_KEY)); - v->spl_ldatum = PointerGetDatum(unionL); - v->spl_rdatum = PointerGetDatum(unionR); - v->spl_left = listL; - v->spl_right = listR; - - if (allisequal) - { - OffsetNumber split_at = FirstOffsetNumber + (maxoff - FirstOffsetNumber + 1)/2; - v->spl_nleft = v->spl_nright = 0; - *unionL = pageunion; - *unionR = pageunion; - - for (i = FirstOffsetNumber; i < split_at; i = OffsetNumberNext(i)) - v->spl_left[v->spl_nleft++] = i; - for (; i <= maxoff; i = OffsetNumberNext(i)) - v->spl_right[v->spl_nright++] = i; - - PG_RETURN_POINTER(v); - } - - /* - * if we have a mix of address families present, then we split by AF regardless - * of all other factors, since the penalty for mixing them is so high. If there's - * at least one universal range, we split those into the right page and leave - * everything else in the left page; otherwise, we split ivp6 into the right page. - * We accept a bad split ratio here in the interests of keeping AFs separate. - */ - -#define ADDLIST( list_, u_, pos_, num_ ) do { \ - if ( pos_ ) { \ - gipr_union_internal_1(u_, cur); \ - } else { \ - *(u_) = *(cur); \ - } \ - (list_)[(pos_)++] = (num_); \ -} while(0) - - if (!allafequal) - { - int right_af = PGSQL_AF_INET6; - - for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) - if ( ((IPR_KEY *)DatumGetPointer(ent[i].key))->af == 0) - break; - - if (i <= maxoff) - right_af = 0; - - for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) - { - cur = (IPR_KEY *)DatumGetPointer(ent[i].key); - if (cur->af != right_af) - ADDLIST(listL, unionL, posL, i); - else - ADDLIST(listR, unionR, posR, i); - } - } - else if (pageunion.af == PGSQL_AF_INET) - { - for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) - { - cur = (IPR_KEY *) DatumGetPointer(ent[i].key); - if ((cur->ipr.ip4r.upper - pageunion.ipr.ip4r.lower) - < (pageunion.ipr.ip4r.upper - cur->ipr.ip4r.lower)) - ADDLIST(listL, unionL, posL, i); - else - ADDLIST(listR, unionR, posR, i); - } - } - else - { - for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) - { - IP6 diff1; - IP6 diff2; - - cur = (IPR_KEY *) DatumGetPointer(ent[i].key); - ip6_sub(&cur->ipr.ip6r.upper, &pageunion.ipr.ip6r.lower, &diff1); - ip6_sub(&pageunion.ipr.ip6r.upper, &cur->ipr.ip6r.lower, &diff2); - if (ip6_lessthan(&diff1,&diff2)) - ADDLIST(listL, unionL, posL, i); - else - ADDLIST(listR, unionR, posR, i); - } - } - - /* bad disposition, sort by ascending size and resplit */ - if (posR == 0 || posL == 0) - { - struct gipr_sort *arr = (struct gipr_sort *) - palloc(sizeof(struct gipr_sort) * (maxoff + FirstOffsetNumber)); - - Assert(allafequal); - - for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) - { - arr[i].key = (IPR_KEY *) DatumGetPointer(ent[i].key); - arr[i].pos = i; - } - - qsort(arr + FirstOffsetNumber, - maxoff - FirstOffsetNumber + 1, - sizeof(struct gipr_sort), - (pageunion.af == PGSQL_AF_INET6) ? gipr_sort_compare_v6 : gipr_sort_compare_v4); - - posL = posR = 0; - - for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) - { - IP6 diff1; - IP6 diff2; - - cur = arr[i].key; - if (pageunion.af == PGSQL_AF_INET) - { - diff1.bits[0] = (cur->ipr.ip4r.upper - pageunion.ipr.ip4r.lower); - diff2.bits[0] = (pageunion.ipr.ip4r.upper - cur->ipr.ip4r.lower); - diff1.bits[1] = diff2.bits[1] = 0; - } - else - { - ip6_sub(&cur->ipr.ip6r.upper, &pageunion.ipr.ip6r.lower, &diff1); - ip6_sub(&pageunion.ipr.ip6r.upper, &cur->ipr.ip6r.lower, &diff2); - } - switch (ip6_compare(&diff1,&diff2)) - { - case -1: - ADDLIST(listL, unionL, posL, arr[i].pos); - break; - case 0: - if (posL > posR) - ADDLIST(listR, unionR, posR, arr[i].pos); - else - ADDLIST(listL, unionL, posL, arr[i].pos); - break; - case 1: - ADDLIST(listR, unionR, posR, arr[i].pos); - break; - } - } - - pfree(arr); - } - - v->spl_nleft = posL; - v->spl_nright = posR; - - PG_RETURN_POINTER(v); -} - -#undef ADDLIST - -/* -** Equality methods -*/ -PG_FUNCTION_INFO_V1(gipr_same); -Datum -gipr_same(PG_FUNCTION_ARGS) -{ - IPR_KEY *v1 = (IPR_KEY *) PG_GETARG_POINTER(0); - IPR_KEY *v2 = (IPR_KEY *) PG_GETARG_POINTER(1); - bool *result = (bool *) PG_GETARG_POINTER(2); - - if (!v1 || !v2) - *result = (v1 == NULL && v2 == NULL); - if (v1->af != v2->af) - *result = false; - else - { - switch (v1->af) - { - case 0: - *result = true; - break; - - case PGSQL_AF_INET: - *result = ip4r_equal(&v1->ipr.ip4r,&v2->ipr.ip4r); - break; - - case PGSQL_AF_INET6: - *result = ip6r_equal(&v1->ipr.ip6r,&v2->ipr.ip6r); - break; - } - } - -#ifdef GIST_DEBUG - fprintf(stderr, "same: %s\n", (*result ? "TRUE" : "FALSE")); -#endif - - PG_RETURN_POINTER(result); -} - - -/* - * Strategy numbers: - * OPERATOR 1 >>= , - * OPERATOR 2 <<= , - * OPERATOR 3 >> , - * OPERATOR 4 << , - * OPERATOR 5 && , - * OPERATOR 6 = , - */ - -/* -** SUPPORT ROUTINES -*/ - -static bool -gipr_leaf_consistent(IPR_KEY *key, - IPR_P queryp, - StrategyNumber strategy) -{ - IPR query; - int af = ipr_unpack(queryp, &query); - -#ifdef GIST_QUERY_DEBUG - fprintf(stderr, "leaf_consistent, %d\n", strategy); -#endif - - if (key->af == 0) - { - switch (strategy) - { - case 1: /* left contains right nonstrict */ - return true; - case 2: /* left contained in right nonstrict */ - return (af == 0); - case 3: /* left contains right strict */ - return !(af == 0); - case 4: /* left contained in right strict */ - return false; - case 5: /* left overlaps right */ - return true; - case 6: /* left equal right */ - return (af == 0); - } - } - else if (af == 0) - { - switch (strategy) - { - case 1: /* left contains right nonstrict */ - return false; - case 2: /* left contained in right nonstrict */ - return true; - case 3: /* left contains right strict */ - return false; - case 4: /* left contained in right strict */ - return true; - case 5: /* left overlaps right */ - return true; - case 6: /* left equal right */ - return false; - } - } - else if (af != key->af) - return false; - else if (af == PGSQL_AF_INET) - { - switch (strategy) - { - case 1: /* left contains right nonstrict */ - return ip4r_contains_internal(&key->ipr.ip4r, &query.ip4r, TRUE); - case 2: /* left contained in right nonstrict */ - return ip4r_contains_internal(&query.ip4r, &key->ipr.ip4r, TRUE); - case 3: /* left contains right strict */ - return ip4r_contains_internal(&key->ipr.ip4r, &query.ip4r, FALSE); - case 4: /* left contained in right strict */ - return ip4r_contains_internal(&query.ip4r, &key->ipr.ip4r, FALSE); - case 5: /* left overlaps right */ - return ip4r_overlaps_internal(&key->ipr.ip4r, &query.ip4r); - case 6: /* left equal right */ - return ip4r_equal(&key->ipr.ip4r, &query.ip4r); - } - } - else if (af == PGSQL_AF_INET6) - { - switch (strategy) - { - case 1: /* left contains right nonstrict */ - return ip6r_contains_internal(&key->ipr.ip6r, &query.ip6r, TRUE); - case 2: /* left contained in right nonstrict */ - return ip6r_contains_internal(&query.ip6r, &key->ipr.ip6r, TRUE); - case 3: /* left contains right strict */ - return ip6r_contains_internal(&key->ipr.ip6r, &query.ip6r, FALSE); - case 4: /* left contained in right strict */ - return ip6r_contains_internal(&query.ip6r, &key->ipr.ip6r, FALSE); - case 5: /* left overlaps right */ - return ip6r_overlaps_internal(&key->ipr.ip6r, &query.ip6r); - case 6: /* left equal right */ - return ip6r_equal(&key->ipr.ip6r, &query.ip6r); - } - } - return FALSE; -} - -/* logic notes: - * If the union value we're looking at overlaps with our query value - * at all, then any of the values underneath it might overlap with us - * or be contained by us, so all the "contained by" and "overlaps" - * cases degenerate to "overlap". - * If the union value is equal to the query value, then none of the - * values under it can strictly contain the query value, so for - * "contained" queries the strictness is preserved. - * If we're looking for an "equal" value, then we have to enter any - * subtree whose union contains (not strictly) our query value. - */ - -static bool -gipr_internal_consistent(IPR_KEY *key, - IPR_P queryp, - StrategyNumber strategy) -{ - IPR query; - int af = ipr_unpack(queryp, &query); - -#ifdef GIST_QUERY_DEBUG - fprintf(stderr, "leaf_consistent, %d\n", strategy); -#endif - - if (af == 0 && strategy == 4) - return false; - else if (key->af == 0 || af == 0) - return true; - else if (af != key->af) - return false; - else if (af == PGSQL_AF_INET) - { - switch (strategy) - { - case 2: /* left contained in right nonstrict */ - case 4: /* left contained in right strict */ - case 5: /* left overlaps right */ - return ip4r_overlaps_internal(&key->ipr.ip4r, &query.ip4r); - case 3: /* left contains right strict */ - return ip4r_contains_internal(&key->ipr.ip4r, &query.ip4r, FALSE); - case 1: /* left contains right nonstrict */ - case 6: /* left equal right */ - return ip4r_contains_internal(&key->ipr.ip4r, &query.ip4r, TRUE); - } - } - else if (af == PGSQL_AF_INET6) - { - switch (strategy) - { - case 2: /* left contained in right nonstrict */ - case 4: /* left contained in right strict */ - case 5: /* left overlaps right */ - return ip6r_overlaps_internal(&key->ipr.ip6r, &query.ip6r); - case 3: /* left contains right strict */ - return ip6r_contains_internal(&key->ipr.ip6r, &query.ip6r, FALSE); - case 1: /* left contains right nonstrict */ - case 6: /* left equal right */ - return ip6r_contains_internal(&key->ipr.ip6r, &query.ip6r, TRUE); - } - } - return FALSE; -} - -/* end */ diff -Nru ip4r-2.3/ipr.h ip4r-2.4/ipr.h --- ip4r-2.3/ipr.h 2018-05-24 21:30:28.000000000 +0000 +++ ip4r-2.4/ipr.h 1970-01-01 00:00:00.000000000 +0000 @@ -1,403 +0,0 @@ -/* $Id: ipr.h,v 1.2 2011/08/22 14:05:19 andrewsn Exp $ */ - -#include "postgres.h" - -#include -#include -#include -#include - -#include "access/gist.h" -#include "access/hash.h" -#include "access/skey.h" -#include "libpq/pqformat.h" -#include "utils/builtins.h" -#include "utils/elog.h" -#include "utils/inet.h" -#include "utils/numeric.h" -#include "utils/palloc.h" - -#if !defined(PG_VERSION_NUM) -#error "Unknown or unsupported postgresql version" -#endif -#if PG_VERSION_NUM < 80400 -#error "Unknown or unsupported postgresql version" -#endif - -/* - * pg11 removed these; consider removing them later, but for now easier to keep - * them - */ -#ifndef TRUE -#define TRUE true -#endif -#ifndef FALSE -#define FALSE false -#endif - -bool ip4_raw_input(const char *src, uint32 *dst); -bool ip6_raw_input(const char *src, uint64 *dst); -int ip4_raw_output(uint32 ip, char *str, int len); -int ip6_raw_output(uint64 *ip, char *str, int len); - -/* IP4 = uint32, stored in host-order. fixed-length and pass by value. */ -typedef uint32 IP4; - -#define IP4_INITIALIZER 0 - -/* IP4R = range of IP4, stored in host-order. fixed-length by reference */ -typedef struct IP4R { - IP4 lower; - IP4 upper; -} IP4R; - -#define IP4R_INITIALIZER {0,0} - -/* - * IP6 = 2 x uint64, stored hi to lo, each stored in host-order. - * fixed-length and pass by reference. - */ - -typedef struct IP6 { - uint64 bits[2]; -} IP6; - -#define IP6_INITIALIZER {{0,0}} - -/* IP6R = range of IP6. fixed-length by reference */ -typedef struct IP6R { - IP6 lower; - IP6 upper; -} IP6R; - -#define IP6R_INITIALIZER {IP6_INITIALIZER,IP6_INITIALIZER} - -#define IP6_STRING_MAX (sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")+2) -#define IP6R_STRING_MAX (2*IP6_STRING_MAX) - -#define IP4_STRING_MAX (sizeof("255.255.255.255")) -#define IP4R_STRING_MAX (2*IP4_STRING_MAX) - -typedef union IP { - IP6 ip6; - IP4 ip4; -} IP; - -#define IP_INITIALIZER {IP6_INITIALIZER} - -#define ipr_af_maxbits(af_) ((af_) == PGSQL_AF_INET ? 32 : 128) -#define ip_sizeof(af_) ((af_) == PGSQL_AF_INET ? sizeof(IP4) : sizeof(IP6)) -#define ipr_sizeof(af_) ((af_) == PGSQL_AF_INET ? sizeof(IP4R) : sizeof(IP6R)) - -typedef void *IP_P; /* unaligned! */ - -void ipaddr_internal_error(void) __attribute__((noreturn)); - -static inline -int ip_unpack(IP_P in, IP *out) -{ - switch (VARSIZE_ANY_EXHDR(in)) - { - case sizeof(IP4): - memcpy(&out->ip4, VARDATA_ANY(in), sizeof(IP4)); - return PGSQL_AF_INET; - case sizeof(IP6): - memcpy(&out->ip6, VARDATA_ANY(in), sizeof(IP6)); - return PGSQL_AF_INET6; - default: - ipaddr_internal_error(); - } -} - -static inline -IP_P ip_pack(int af, IP *val) -{ - int sz = ip_sizeof(af); - IP_P out = palloc(VARHDRSZ + sz); - - SET_VARSIZE(out, VARHDRSZ + sz); - memcpy(VARDATA(out), val, sz); - return out; -} - -typedef union IPR { - IP6R ip6r; - IP4R ip4r; -} IPR; - -#define IPR_INITIALIZER {IP6R_INITIALIZER} - -typedef void *IPR_P; /* unaligned! */ - -#define DatumGetIP4RP(X) ((IP4R *) DatumGetPointer(X)) -#define IP4RPGetDatum(X) PointerGetDatum(X) -#define PG_GETARG_IP4R_P(n) DatumGetIP4RP(PG_GETARG_DATUM(n)) -#define PG_RETURN_IP4R_P(x) return IP4RPGetDatum(x) - -#define DatumGetIP4(X) DatumGetUInt32(X) -#define IP4GetDatum(X) UInt32GetDatum(X) -#define PG_GETARG_IP4(n) PG_GETARG_UINT32(n) -#define PG_RETURN_IP4(x) PG_RETURN_UINT32(x) - -#define DatumGetIP6RP(X) ((IP6R *) DatumGetPointer(X)) -#define IP6RPGetDatum(X) PointerGetDatum(X) -#define PG_GETARG_IP6R_P(n) DatumGetIP6RP(PG_GETARG_DATUM(n)) -#define PG_RETURN_IP6R_P(x) return IP6RPGetDatum(x) - -#define DatumGetIP6P(X) ((IP6 *) DatumGetPointer(X)) -#define IP6PGetDatum(X) PointerGetDatum(X) -#define PG_GETARG_IP6_P(n) DatumGetIP6P(PG_GETARG_DATUM(n)) -#define PG_RETURN_IP6_P(x) return IP6PGetDatum(x) - -#define DatumGetIP_P(X) ((IP_P) PG_DETOAST_DATUM_PACKED(X)) -#define IP_PGetDatum(X) PointerGetDatum(X) -#define PG_GETARG_IP_P(n) DatumGetIP_P(PG_GETARG_DATUM(n)) -#define PG_RETURN_IP_P(x) return IP_PGetDatum(x) - -#define DatumGetIPR_P(X) ((IP_P) PG_DETOAST_DATUM_PACKED(X)) -#define IPR_PGetDatum(X) PointerGetDatum(X) -#define PG_GETARG_IPR_P(n) DatumGetIPR_P(PG_GETARG_DATUM(n)) -#define PG_RETURN_IPR_P(x) return IPR_PGetDatum(x) - -/* PG version dependencies */ - -#define INET_STRUCT_DATA(is_) ((inet_struct *)VARDATA_ANY(is_)) - -#define GISTENTRYCOUNT(v) ((v)->n) -#define GISTENTRYVEC(v) ((v)->vector) - -/* funcs */ - -Datum ip4_in(PG_FUNCTION_ARGS); -Datum ip4_out(PG_FUNCTION_ARGS); -Datum ip4_recv(PG_FUNCTION_ARGS); -Datum ip4_send(PG_FUNCTION_ARGS); -Datum ip4hash(PG_FUNCTION_ARGS); -Datum ip4_cast_to_text(PG_FUNCTION_ARGS); -Datum ip4_cast_from_text(PG_FUNCTION_ARGS); -Datum ip4_cast_from_inet(PG_FUNCTION_ARGS); -Datum ip4_cast_to_cidr(PG_FUNCTION_ARGS); -Datum ip4_cast_to_bigint(PG_FUNCTION_ARGS); -Datum ip4_cast_to_numeric(PG_FUNCTION_ARGS); -Datum ip4_cast_from_bigint(PG_FUNCTION_ARGS); -Datum ip4_cast_from_numeric(PG_FUNCTION_ARGS); -Datum ip4_cast_to_double(PG_FUNCTION_ARGS); -Datum ip4_cast_from_double(PG_FUNCTION_ARGS); -Datum ip4r_in(PG_FUNCTION_ARGS); -Datum ip4r_out(PG_FUNCTION_ARGS); -Datum ip4r_recv(PG_FUNCTION_ARGS); -Datum ip4r_send(PG_FUNCTION_ARGS); -Datum ip4rhash(PG_FUNCTION_ARGS); -Datum ip4r_cast_to_text(PG_FUNCTION_ARGS); -Datum ip4r_cast_from_text(PG_FUNCTION_ARGS); -Datum ip4r_cast_from_cidr(PG_FUNCTION_ARGS); -Datum ip4r_cast_to_cidr(PG_FUNCTION_ARGS); -Datum ip4r_cast_from_ip4(PG_FUNCTION_ARGS); -Datum ip4r_from_ip4s(PG_FUNCTION_ARGS); -Datum ip4r_net_prefix(PG_FUNCTION_ARGS); -Datum ip4r_net_mask(PG_FUNCTION_ARGS); -Datum ip4r_lower(PG_FUNCTION_ARGS); -Datum ip4r_upper(PG_FUNCTION_ARGS); -Datum ip4r_is_cidr(PG_FUNCTION_ARGS); -Datum ip4_netmask(PG_FUNCTION_ARGS); -Datum ip4_net_lower(PG_FUNCTION_ARGS); -Datum ip4_net_upper(PG_FUNCTION_ARGS); -Datum ip4_plus_int(PG_FUNCTION_ARGS); -Datum ip4_plus_bigint(PG_FUNCTION_ARGS); -Datum ip4_plus_numeric(PG_FUNCTION_ARGS); -Datum ip4_minus_int(PG_FUNCTION_ARGS); -Datum ip4_minus_bigint(PG_FUNCTION_ARGS); -Datum ip4_minus_numeric(PG_FUNCTION_ARGS); -Datum ip4_minus_ip4(PG_FUNCTION_ARGS); -Datum ip4_and(PG_FUNCTION_ARGS); -Datum ip4_or(PG_FUNCTION_ARGS); -Datum ip4_xor(PG_FUNCTION_ARGS); -Datum ip4_not(PG_FUNCTION_ARGS); -Datum ip4_lt(PG_FUNCTION_ARGS); -Datum ip4_le(PG_FUNCTION_ARGS); -Datum ip4_gt(PG_FUNCTION_ARGS); -Datum ip4_ge(PG_FUNCTION_ARGS); -Datum ip4_eq(PG_FUNCTION_ARGS); -Datum ip4_neq(PG_FUNCTION_ARGS); -Datum ip4r_lt(PG_FUNCTION_ARGS); -Datum ip4r_le(PG_FUNCTION_ARGS); -Datum ip4r_gt(PG_FUNCTION_ARGS); -Datum ip4r_ge(PG_FUNCTION_ARGS); -Datum ip4r_eq(PG_FUNCTION_ARGS); -Datum ip4r_neq(PG_FUNCTION_ARGS); -Datum ip4r_overlaps(PG_FUNCTION_ARGS); -Datum ip4r_contains(PG_FUNCTION_ARGS); -Datum ip4r_contains_strict(PG_FUNCTION_ARGS); -Datum ip4r_contained_by(PG_FUNCTION_ARGS); -Datum ip4r_contained_by_strict(PG_FUNCTION_ARGS); -Datum ip4_contains(PG_FUNCTION_ARGS); -Datum ip4_contained_by(PG_FUNCTION_ARGS); -Datum ip4r_union(PG_FUNCTION_ARGS); -Datum ip4r_inter(PG_FUNCTION_ARGS); -Datum ip4r_size(PG_FUNCTION_ARGS); -Datum ip4r_size_exact(PG_FUNCTION_ARGS); -Datum ip4r_prefixlen(PG_FUNCTION_ARGS); -Datum ip4r_cmp(PG_FUNCTION_ARGS); -Datum ip4_cmp(PG_FUNCTION_ARGS); -Datum ip4r_left_of(PG_FUNCTION_ARGS); -Datum ip4r_right_of(PG_FUNCTION_ARGS); - -Datum ip6_in(PG_FUNCTION_ARGS); -Datum ip6_out(PG_FUNCTION_ARGS); -Datum ip6_recv(PG_FUNCTION_ARGS); -Datum ip6_send(PG_FUNCTION_ARGS); -Datum ip6hash(PG_FUNCTION_ARGS); -Datum ip6_cast_to_text(PG_FUNCTION_ARGS); -Datum ip6_cast_from_text(PG_FUNCTION_ARGS); -Datum ip6_cast_from_inet(PG_FUNCTION_ARGS); -Datum ip6_cast_to_cidr(PG_FUNCTION_ARGS); -Datum ip6_cast_to_numeric(PG_FUNCTION_ARGS); -Datum ip6_cast_from_numeric(PG_FUNCTION_ARGS); -Datum ip6r_in(PG_FUNCTION_ARGS); -Datum ip6r_out(PG_FUNCTION_ARGS); -Datum ip6r_recv(PG_FUNCTION_ARGS); -Datum ip6r_send(PG_FUNCTION_ARGS); -Datum ip6rhash(PG_FUNCTION_ARGS); -Datum ip6r_cast_to_text(PG_FUNCTION_ARGS); -Datum ip6r_cast_from_text(PG_FUNCTION_ARGS); -Datum ip6r_cast_from_cidr(PG_FUNCTION_ARGS); -Datum ip6r_cast_to_cidr(PG_FUNCTION_ARGS); -Datum ip6r_cast_from_ip6(PG_FUNCTION_ARGS); -Datum ip6r_from_ip6s(PG_FUNCTION_ARGS); -Datum ip6r_net_prefix(PG_FUNCTION_ARGS); -Datum ip6r_net_mask(PG_FUNCTION_ARGS); -Datum ip6r_lower(PG_FUNCTION_ARGS); -Datum ip6r_upper(PG_FUNCTION_ARGS); -Datum ip6r_is_cidr(PG_FUNCTION_ARGS); -Datum ip6_netmask(PG_FUNCTION_ARGS); -Datum ip6_net_lower(PG_FUNCTION_ARGS); -Datum ip6_net_upper(PG_FUNCTION_ARGS); -Datum ip6_plus_int(PG_FUNCTION_ARGS); -Datum ip6_plus_bigint(PG_FUNCTION_ARGS); -Datum ip6_plus_numeric(PG_FUNCTION_ARGS); -Datum ip6_minus_int(PG_FUNCTION_ARGS); -Datum ip6_minus_bigint(PG_FUNCTION_ARGS); -Datum ip6_minus_numeric(PG_FUNCTION_ARGS); -Datum ip6_minus_ip6(PG_FUNCTION_ARGS); -Datum ip6_and(PG_FUNCTION_ARGS); -Datum ip6_or(PG_FUNCTION_ARGS); -Datum ip6_xor(PG_FUNCTION_ARGS); -Datum ip6_not(PG_FUNCTION_ARGS); -Datum ip6_lt(PG_FUNCTION_ARGS); -Datum ip6_le(PG_FUNCTION_ARGS); -Datum ip6_gt(PG_FUNCTION_ARGS); -Datum ip6_ge(PG_FUNCTION_ARGS); -Datum ip6_eq(PG_FUNCTION_ARGS); -Datum ip6_neq(PG_FUNCTION_ARGS); -Datum ip6r_lt(PG_FUNCTION_ARGS); -Datum ip6r_le(PG_FUNCTION_ARGS); -Datum ip6r_gt(PG_FUNCTION_ARGS); -Datum ip6r_ge(PG_FUNCTION_ARGS); -Datum ip6r_eq(PG_FUNCTION_ARGS); -Datum ip6r_neq(PG_FUNCTION_ARGS); -Datum ip6r_overlaps(PG_FUNCTION_ARGS); -Datum ip6r_contains(PG_FUNCTION_ARGS); -Datum ip6r_contains_strict(PG_FUNCTION_ARGS); -Datum ip6r_contained_by(PG_FUNCTION_ARGS); -Datum ip6r_contained_by_strict(PG_FUNCTION_ARGS); -Datum ip6_contains(PG_FUNCTION_ARGS); -Datum ip6_contained_by(PG_FUNCTION_ARGS); -Datum ip6r_union(PG_FUNCTION_ARGS); -Datum ip6r_inter(PG_FUNCTION_ARGS); -Datum ip6r_size(PG_FUNCTION_ARGS); -Datum ip6r_size_exact(PG_FUNCTION_ARGS); -Datum ip6r_prefixlen(PG_FUNCTION_ARGS); -Datum ip6r_cmp(PG_FUNCTION_ARGS); -Datum ip6_cmp(PG_FUNCTION_ARGS); -Datum ip6r_left_of(PG_FUNCTION_ARGS); -Datum ip6r_right_of(PG_FUNCTION_ARGS); - -Datum ipaddr_in(PG_FUNCTION_ARGS); -Datum ipaddr_out(PG_FUNCTION_ARGS); -Datum ipaddr_recv(PG_FUNCTION_ARGS); -Datum ipaddr_send(PG_FUNCTION_ARGS); -Datum ipaddr_hash(PG_FUNCTION_ARGS); -Datum ipaddr_cast_to_text(PG_FUNCTION_ARGS); -Datum ipaddr_cast_from_text(PG_FUNCTION_ARGS); -Datum ipaddr_cast_from_inet(PG_FUNCTION_ARGS); -Datum ipaddr_cast_to_cidr(PG_FUNCTION_ARGS); -Datum ipaddr_cast_to_numeric(PG_FUNCTION_ARGS); -Datum ipaddr_cast_from_ip4(PG_FUNCTION_ARGS); -Datum ipaddr_cast_from_ip6(PG_FUNCTION_ARGS); -Datum ipaddr_cast_to_ip4(PG_FUNCTION_ARGS); -Datum ipaddr_cast_to_ip6(PG_FUNCTION_ARGS); -Datum ipaddr_net_lower(PG_FUNCTION_ARGS); -Datum ipaddr_net_upper(PG_FUNCTION_ARGS); -Datum ipaddr_family(PG_FUNCTION_ARGS); -Datum ipaddr_plus_int(PG_FUNCTION_ARGS); -Datum ipaddr_plus_bigint(PG_FUNCTION_ARGS); -Datum ipaddr_plus_numeric(PG_FUNCTION_ARGS); -Datum ipaddr_minus_int(PG_FUNCTION_ARGS); -Datum ipaddr_minus_bigint(PG_FUNCTION_ARGS); -Datum ipaddr_minus_numeric(PG_FUNCTION_ARGS); -Datum ipaddr_minus_ipaddr(PG_FUNCTION_ARGS); -Datum ipaddr_and(PG_FUNCTION_ARGS); -Datum ipaddr_or(PG_FUNCTION_ARGS); -Datum ipaddr_xor(PG_FUNCTION_ARGS); -Datum ipaddr_not(PG_FUNCTION_ARGS); -Datum ipaddr_lt(PG_FUNCTION_ARGS); -Datum ipaddr_le(PG_FUNCTION_ARGS); -Datum ipaddr_gt(PG_FUNCTION_ARGS); -Datum ipaddr_ge(PG_FUNCTION_ARGS); -Datum ipaddr_eq(PG_FUNCTION_ARGS); -Datum ipaddr_neq(PG_FUNCTION_ARGS); -Datum ipaddr_cmp(PG_FUNCTION_ARGS); - -Datum iprange_in(PG_FUNCTION_ARGS); -Datum iprange_out(PG_FUNCTION_ARGS); -Datum iprange_recv(PG_FUNCTION_ARGS); -Datum iprange_send(PG_FUNCTION_ARGS); -Datum iprange_hash(PG_FUNCTION_ARGS); -Datum iprange_cast_to_text(PG_FUNCTION_ARGS); -Datum iprange_cast_from_text(PG_FUNCTION_ARGS); -Datum iprange_cast_from_cidr(PG_FUNCTION_ARGS); -Datum iprange_cast_to_cidr(PG_FUNCTION_ARGS); -Datum iprange_cast_from_ip4(PG_FUNCTION_ARGS); -Datum iprange_cast_from_ip6(PG_FUNCTION_ARGS); -Datum iprange_cast_from_ipaddr(PG_FUNCTION_ARGS); -Datum iprange_cast_from_ip4r(PG_FUNCTION_ARGS); -Datum iprange_cast_from_ip6r(PG_FUNCTION_ARGS); -Datum iprange_cast_to_ip4r(PG_FUNCTION_ARGS); -Datum iprange_cast_to_ip6r(PG_FUNCTION_ARGS); -Datum iprange_from_ip4s(PG_FUNCTION_ARGS); -Datum iprange_from_ip6s(PG_FUNCTION_ARGS); -Datum iprange_from_ipaddrs(PG_FUNCTION_ARGS); -Datum iprange_net_prefix_ip4(PG_FUNCTION_ARGS); -Datum iprange_net_prefix_ip6(PG_FUNCTION_ARGS); -Datum iprange_net_prefix(PG_FUNCTION_ARGS); -Datum iprange_net_mask_ip4(PG_FUNCTION_ARGS); -Datum iprange_net_mask_ip6(PG_FUNCTION_ARGS); -Datum iprange_net_mask(PG_FUNCTION_ARGS); -Datum iprange_lower(PG_FUNCTION_ARGS); -Datum iprange_upper(PG_FUNCTION_ARGS); -Datum iprange_is_cidr(PG_FUNCTION_ARGS); -Datum iprange_family(PG_FUNCTION_ARGS); -Datum iprange_lt(PG_FUNCTION_ARGS); -Datum iprange_le(PG_FUNCTION_ARGS); -Datum iprange_gt(PG_FUNCTION_ARGS); -Datum iprange_ge(PG_FUNCTION_ARGS); -Datum iprange_eq(PG_FUNCTION_ARGS); -Datum iprange_neq(PG_FUNCTION_ARGS); -Datum iprange_overlaps(PG_FUNCTION_ARGS); -Datum iprange_contains(PG_FUNCTION_ARGS); -Datum iprange_contains_strict(PG_FUNCTION_ARGS); -Datum iprange_contained_by(PG_FUNCTION_ARGS); -Datum iprange_contained_by_strict(PG_FUNCTION_ARGS); -Datum iprange_contains_ip(PG_FUNCTION_ARGS); -Datum iprange_contains_ip4(PG_FUNCTION_ARGS); -Datum iprange_contains_ip6(PG_FUNCTION_ARGS); -Datum iprange_ip_contained_by(PG_FUNCTION_ARGS); -Datum iprange_ip4_contained_by(PG_FUNCTION_ARGS); -Datum iprange_ip6_contained_by(PG_FUNCTION_ARGS); -Datum iprange_union(PG_FUNCTION_ARGS); -Datum iprange_inter(PG_FUNCTION_ARGS); -Datum iprange_size(PG_FUNCTION_ARGS); -Datum iprange_size_exact(PG_FUNCTION_ARGS); -Datum iprange_prefixlen(PG_FUNCTION_ARGS); -Datum iprange_cmp(PG_FUNCTION_ARGS); - diff -Nru ip4r-2.3/legacy-r.sed ip4r-2.4/legacy-r.sed --- ip4r-2.3/legacy-r.sed 2018-05-24 21:30:28.000000000 +0000 +++ ip4r-2.4/legacy-r.sed 1970-01-01 00:00:00.000000000 +0000 @@ -1,7 +0,0 @@ -# -/^CREATE EXTENSION/c\ -SET client_min_messages = warning;\ -\\set ECHO none\ -\\i ip4r.sql\ -\\set ECHO all\ -RESET client_min_messages; diff -Nru ip4r-2.3/legacy.sed ip4r-2.4/legacy.sed --- ip4r-2.3/legacy.sed 2018-05-24 21:30:28.000000000 +0000 +++ ip4r-2.4/legacy.sed 1970-01-01 00:00:00.000000000 +0000 @@ -1,22 +0,0 @@ -# -/^-- complain.*CREATE EXTENSION/,/^$/c\ --- Adjust this setting to control where the objects get created.\ -SET search_path = public;\ -\ - -# -/^-- Type definitions/a\ -\ -BEGIN; -# -/^-- type creation is needlessly chatty/a\ -\ -SET LOCAL client_min_messages = warning; - -# -/^COMMENT ON TYPE iprange/a\ -\ -COMMIT; -# -/^CREATE TYPE [^()]*;/,/^$/d -/^CREATE FUNCTION/s/CREATE FUNCTION/CREATE OR REPLACE FUNCTION/ diff -Nru ip4r-2.3/Makefile ip4r-2.4/Makefile --- ip4r-2.3/Makefile 2018-05-24 21:30:28.000000000 +0000 +++ ip4r-2.4/Makefile 2018-11-21 06:35:30.000000000 +0000 @@ -2,25 +2,44 @@ MODULE_big = ip4r ifndef NO_EXTENSION -EXTENSION = ip4r -DATA = ip4r--2.2.sql \ - ip4r--2.1--2.2.sql \ - ip4r--2.0--2.1.sql \ - ip4r--unpackaged2.1--2.1.sql \ - ip4r--unpackaged2.0--2.0.sql \ - ip4r--unpackaged1--2.0.sql -REGRESS = ip4r +EXTENSION= ip4r +SRC_SQL = ip4r--2.4.sql \ + ip4r--2.2--2.4.sql \ + ip4r--2.1--2.2.sql \ + ip4r--2.0--2.1.sql \ + ip4r--unpackaged2.1--2.1.sql \ + ip4r--unpackaged2.0--2.0.sql \ + ip4r--unpackaged1--2.0.sql +DATA = $(addprefix scripts/, $(SRC_SQL)) +REGRESS = ip4r $(REGRESS_$(MAJORVERSION)) +REGRESS_11 := ip4r-v11 +REGRESS_12 := $(REGRESS_11) else DATA_built = ip4r.sql EXTRA_CLEAN += ip4r.sql.in sql/ip4r-legacy.sql expected/ip4r-legacy.out REGRESS = ip4r-legacy endif -DOCS = README.ip4r -OBJS = ip4r_module.o ip4r.o ip6r.o ipaddr.o iprange.o raw_io.o +objdir = src + +DOCS = README.ip4r +OBJS_C = ip4r_module.o ip4r.o ip6r.o ipaddr.o iprange.o raw_io.o +OBJS = $(addprefix src/, $(OBJS_C)) +INCS = ipr.h ipr_internal.h + +HEADERS = src/ipr.h + +# if VPATH is not already set, but the makefile is not in the current +# dir, then assume a vpath build using the makefile's directory as +# source. PGXS will set $(srcdir) accordingly. +ifndef VPATH +ifneq ($(realpath $(CURDIR)),$(realpath $(dir $(firstword $(MAKEFILE_LIST))))) +VPATH := $(dir $(firstword $(MAKEFILE_LIST))) +endif +endif ifndef NO_PGXS -PG_CONFIG = pg_config +PG_CONFIG ?= pg_config PGXS = $(shell $(PG_CONFIG) --pgxs) include $(PGXS) else @@ -34,27 +53,48 @@ $(error unsupported PostgreSQL version) endif +$(OBJS): $(addprefix $(srcdir)/src/, $(INCS)) + +# for a vpath build, we need src/ to exist in the build dir before +# building any objects. +ifdef VPATH +all: vpath-mkdirs +.PHONY: vpath-mkdirs +$(OBJS): | vpath-mkdirs + +vpath-mkdirs: + $(MKDIR_P) $(objdir) +endif # VPATH + ifndef EXTENSION ifeq ($(filter-out 8.4, $(MAJORVERSION)),) -ip4r.sql.in: ip4r--2.2.sql legacy.sed - sed -f legacy.sed $< | sed -e '/^DO /,/^[$$]/d' >$@ +ip4r.sql.in: $(srcdir)/scripts/ip4r--2.4.sql $(srcdir)/tools/legacy.sed + sed -f $(srcdir)/tools/legacy.sed $< | sed -e '/^DO /,/^[$$]/d' >$@ else -ip4r.sql.in: ip4r--2.2.sql legacy.sed - sed -f legacy.sed $< >$@ +ip4r.sql.in: $(srcdir)/scripts/ip4r--2.4.sql $(srcdir)/tools/legacy.sed + sed -f $(srcdir)/tools/legacy.sed $< >$@ endif -sql/ip4r-legacy.sql: sql/ip4r.sql legacy-r.sed - sed -f legacy-r.sed $< >$@ +# regression test doesn't like the idea of having to build files in +# the sql/ subdir, and looks for that only in $(srcdir). So disable +# legacy regression tests in vpath build. +ifndef VPATH +sql/ip4r-legacy.sql: sql/ip4r.sql tools/legacy-r.sed + sed -f tools/legacy-r.sed $< >$@ -expected/ip4r-legacy.out: expected/ip4r.out - sed -f legacy-r.sed $< | sed -e '/^\\i /,+1d' >$@ +expected/ip4r-legacy.out: expected/ip4r.out tools/legacy-r.sed + sed -f tools/legacy-r.sed $< | sed -e '/^\\i /,+1d' >$@ installcheck: sql/ip4r-legacy.sql expected/ip4r-legacy.out +else +installcheck: + @echo regression tests are disabled in legacy vpath build +endif # VPATH else ifeq ($(filter-out 8.% 9.0, $(MAJORVERSION)),) diff -Nru ip4r-2.3/raw_io.c ip4r-2.4/raw_io.c --- ip4r-2.3/raw_io.c 2018-05-24 21:30:28.000000000 +0000 +++ ip4r-2.4/raw_io.c 1970-01-01 00:00:00.000000000 +0000 @@ -1,271 +0,0 @@ -/* $Id: raw_io.c,v 1.2 2011/08/22 14:05:19 andrewsn Exp $ */ - -/* - * Copyright (c) 2011 Andrew Gierth - * - * Licensed under the same terms as PostgreSQL itself. - */ - -#include "ipr.h" - -bool ip4_raw_input(const char *osrc, uint32 *dst) -{ - const unsigned char *src = (const unsigned char *)osrc; - int digits = 0; - int octets = 0; - int ch; - uint32 octet = 0; - uint32 tmp = 0; - - for (;;) - { - switch ((ch = *src++)) - { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - if (digits++ && octet == 0) - return false; /* must have been a leading 0, reject */ - octet = (octet * 10) + (ch - '0'); - if (octet > 255) - return false; - break; - - case '.': - if (!digits || ++octets > 3) - return false; - tmp = (tmp << 8) | octet; - digits = 0; - octet = 0; - break; - - case 0: - if (!digits || octets != 3) - return false; - tmp = (tmp << 8) | octet; - *dst = tmp; - return true; - - default: - return false; - } - } -} - -bool ip6_raw_input(const char *osrc, uint64 *dst) -{ - const unsigned char *src = (const unsigned char *)osrc; - const unsigned char *backtrack = src; - int ch; - int digits = 0; - int words = 0; - int gap = -1; - uint16 word = 0; - uint16 tmp[8]; - - /* leading :: needs a special case */ - if (*src == ':') - if (*++src != ':') - return false; - - for (;;) - { - switch ((ch = *src++)) - { - case '0': case '1': case '2': case '3': case '4': - case '5': case '6': case '7': case '8': case '9': - word = (word << 4) | (ch - '0'); - break; - - case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': - word = (word << 4) | ((ch - 'a') + 10); - break; - - case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': - word = (word << 4) | ((ch - 'A') + 10); - break; - - case ':': - if (digits == 0) - { - if (gap >= 0) - return false; - gap = words; - } - else if (!*src) - return false; /* trailing : not valid except as :: */ - - tmp[words++] = word; - if (words > 7 && *src) - return false; - backtrack = src; - word = 0; - digits = 0; - continue; - - case '.': - if (words < 1 || words > 6) - return false; - - { - uint32 ip4val; - if (!ip4_raw_input((const char *)backtrack, &ip4val)) - return false; - tmp[words++] = (ip4val >> 16); - word = (ip4val & 0xffff); - digits = 4; - } - - /* FALLTHROUGH */ - case 0: - if (digits) - tmp[words++] = word; - if (words < 8) - { - int i,d; - if (gap < 0) - return false; - d = 8 - words; - for (i = 7; i > gap+d; --i) - tmp[i] = tmp[i-d]; - for (; i > gap; --i) - tmp[i] = 0; - } - dst[0] = (((uint64)(tmp[0]) << 48) | ((uint64)(tmp[1]) << 32) - | ((uint64)(tmp[2]) << 16) | tmp[3]); - dst[1] = (((uint64)(tmp[4]) << 48) | ((uint64)(tmp[5]) << 32) - | ((uint64)(tmp[6]) << 16) | tmp[7]); - return true; - - default: - return false; - } - - if (++digits > 4) - return false; - } -} - -int ip4_raw_output(uint32 ip, char *str, int len) -{ - return snprintf(str, len, "%u.%u.%u.%u", - (ip >> 24)&0xff, (ip >> 16)&0xff, (ip >> 8)&0xff, (ip)&0xff); -} - -int ip6_raw_output(uint64 *ip, char *str, int len) -{ - uint16 tmp[8]; - char buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") + 2]; - char *ptr = buf; - unsigned flags = (1 << 8); - int best = -1; - int best_len = 1; - int best_end; - uint16 word; - int i,j; - - tmp[0] = ip[0] >> 48; - tmp[1] = ip[0] >> 32; - tmp[2] = ip[0] >> 16; - tmp[3] = ip[0]; - tmp[4] = ip[1] >> 48; - tmp[5] = ip[1] >> 32; - tmp[6] = ip[1] >> 16; - tmp[7] = ip[1]; - - /* - * Find the best place to put :: in the output. Per RFC5952, we must: - * - not use :: to replace a single 0 word - * - use :: to replace the longest string of 0 words - * - use :: to replace the leftmost candidate string of equal length - * - * The bitmask we construct here has the least significant bit - * representing the leftmost word, and we process the bitmask by - * shifting right, therefore we are processing the original words - * left to right. Thus we take a new best position only if it is - * strictly better than the previous one. - * - * best = -1 implies that there is no position to use :: - */ - - for (i = 0; i < 8; ++i) - flags |= (tmp[i] ? (1 << i) : 0); - for (i = 0; i < 8; ++i, flags >>= 1) - if ((flags & 1) == 0 && (ffs(flags)-1) > best_len) - best = i, best_len = ffs(flags)-1; - - best_end = best + best_len - 1; - - /* - * If we're starting with a string of more than one zero word, process - * the special cases: - * - * all zeros (8 zero words) - '::' - * 6 zero words followed by a non-zero word - '::1.2.3.4' - * 5 zero words followed by 0xffff - '::ffff:1.2.3.4' - * 4 zero words followed by ffff:0 - '::ffff:0:1.2.3.4' [rfc2765] - * - * The case of 7 zero words we leave alone; that avoids trying to output - * '::1' as '::0.0.0.1'. We assume that '0.0.x.y' will never be a valid - * IPv4 address used in an IPv4-compatible IPv6 address (which are in any - * event deprecated). - */ - - if (best == 0) - { - if (best_len == 6 - || (best_len == 5 && tmp[5] == 0xffff) - || (best_len == 4 && tmp[4] == 0xffff && tmp[5] == 0)) - { - ip4_raw_output(((uint32)(tmp[6]) << 16) | tmp[7], buf, sizeof(buf)-2); - return snprintf(str, len, ":%s%s:%s", - (best_len != 6) ? ":ffff" : "", - (best_len == 4) ? ":0" : "", - buf); - } - else if (best_len == 8) - return snprintf(str, len, "::"); - } - - for (i = 0; i < 8; ++i) - { - if (i >= best && i <= best_end) - { - if (i == best_end) - *ptr++ = ':'; - continue; - } - - if (i > 0) - *ptr++ = ':'; - - word = tmp[i]; - - /* - * canonicalization rules: - * - * leading zeros must be suppressed. - * output must be lowercase. - */ - - if (!word) - *ptr++ = '0'; - else - { - word = (word >> 8) | (word << 8); - word = ((word & 0xf0f0) >> 4) | ((word & 0x0f0f) << 4); - for (j = 0; j < 3; ++j, word >>= 4) - if (word & 0xf) - break; - for (; j < 4; ++j, word >>= 4) - *ptr++ = ((word & 0xf) > 9) ? ((word & 0xf) + 'a' - 10) : ((word & 0xf) + '0'); - } - } - - if (best_end == 7) - *ptr++ = ':'; - - *ptr = 0; - - return snprintf(str, len, "%s", buf); -} - diff -Nru ip4r-2.3/README.ip4r ip4r-2.4/README.ip4r --- ip4r-2.3/README.ip4r 2018-05-24 21:30:28.000000000 +0000 +++ ip4r-2.4/README.ip4r 2018-11-21 06:35:30.000000000 +0000 @@ -2,6 +2,59 @@ IP4R - IPv4/v6 and IPv4/v6 range index type for PostgreSQL =========================================================== +CHANGES in version 2.4: +======================= + + * Add new cidr_split functions to decompose an arbitrary range into + a set of CIDR blocks. + + * Add casts to and from bit and bytea types. + + * Support new hash functions for hash partitioning. + + * Support window function RANGE offsets in pg11+, including a special + case where negative offset values are treated as CIDR prefix lengths + (so RANGE BETWEEN -16 PRECEDING AND -16 FOLLOWING includes in the + window frame all rows in the same /16 as the current row). + + * Fix a historical oversight with the hash function for iprange, in which + it would return different values for ip6 cidr ranges than the ip6r hash + function. This was not a bug in that no queries would give wrong + answers, but it would prevent any future reorganization of the opclass + to handle cross-type comparisons. Since allowing hash partitioning has + the practical effect of casting the hash function in stone (far more so + than hash indexes do), best to fix this now. + + The result of the function iprangehash(iprange) is NOT changed by this + update, on the assumption that it might have been in use for + inheritance partitioning or other explicit uses. Instead, a new hash + function is added for the opclass to use. + + NOTE: This version requires any hash indexes on iprange columns to be + rebuilt. An ALTER EXTENSION ... UPDATE command will refuse to run if it + detects any such indexes (it will report the offending indexes in INFO + messages to the client). You can automatically drop or recreate + affected indexes by performing one of these commands before the ALTER + EXTENSION: + + SET ip4r.update_indexes = 'drop'; + SET ip4r.update_indexes = 'rebuild'; + + (on pg 9.1 you will have to add 'ip4r' to custom_variable_classes + in postgresql.conf and restart before doing this) + + The value 'drop' will drop any iprange hash indexes and complete the + upgrade. The DROP commands will be done with RESTRICT: if there are any + additional dependencies on the indexes in question, the upgrade will + not proceed; these will have to be dealt with manually. If any indexes + were dropped the upgrade will leave behind a new table named + ip4r_update_to_2_4.update_indexes containing the affected table and + index information, including the CREATE INDEX command as obtained by + pg_get_indexdef(). This table is not part of the extension and can be + dropped when the data is no longer needed. The value 'rebuild' will + cause the update script to perform the needed CREATE INDEX commands + itself (which of course may take some time). + CHANGES in version 2.3: ======================= @@ -188,6 +241,12 @@ bigint | ip4 | ip4(bigint) or bigint::ip4 (explicit) ip4 | float8 | to_double(ip4) or ip4::float8 (explicit) float8 | ip4 | ip4(float8) or float8::ip4 (explicit) + ipX | varbit | to_bit(ipX) or ipX::varbit (explicit) + bit(32) | ip4 | ip4(bit) or bit::ip4 (explicit) + bit(128) | ip6 | ip6(bit) or bit::ip6 (explicit) + varbit | ipX | ipX(varbit) or varbit::ipX (explicit) + ipX | bytea | to_bytea(ipX) or ipX::bytea (explicit) + bytea | ipX | ipX(bytea) or bytea::ipX (explicit) ipX | ipXr | ipXr(ipX) or ipX::ipXr (implicit) ip4 | ipaddress | ipaddress(ip4) or ip4::ipaddress (implicit) ip6 | ipaddress | ipaddress(ip6) or ip6::ipaddress (implicit) @@ -319,6 +378,9 @@ text | ipXr | ipXr(text) or text::ipXr (explicit) ipXr | cidr | cidr(ipXr) or ipXr::cidr (explicit) cidr | ipXr | ipXr(cidr) or cidr::ipXr (assignment) + ipXr | varbit | to_bit(ipXr) or ipXr::varbit (explicit) + varbit | ip4r | ip4r(varbit) or varbit::ip4r (explicit) + varbit | ip6r | ip6r(varbit) or varbit::ip6r (explicit) The conversion cidr(ipXr) returns NULL if the ipXr value does not represent a valid CIDR range. @@ -340,6 +402,10 @@ upper(ipXr) returns ipX | returns the upper end of the ipXr range, as an ipX value + cidr_split(ipXr) returns setof ipXr + | splits the range up into separate CIDR blocks, and returns each one + | as a separate row + ipXr supports the following operators: Operator | Description @@ -454,7 +520,7 @@ AUTHORS ======= -this code by andrew@tao11.riddles.org.uk Oct 2004 - Aug 2016 +this code by andrew@tao11.riddles.org.uk Oct 2004 - 2018 derived from 'ipr' by Steve Atkins August 2003 derived from the 'seg' type distributed with PostgreSQL. diff -Nru ip4r-2.3/scripts/ip4r--2.0--2.1.sql ip4r-2.4/scripts/ip4r--2.0--2.1.sql --- ip4r-2.3/scripts/ip4r--2.0--2.1.sql 1970-01-01 00:00:00.000000000 +0000 +++ ip4r-2.4/scripts/ip4r--2.0--2.1.sql 2018-11-21 06:35:30.000000000 +0000 @@ -0,0 +1,70 @@ +/* ip4r--2.0--2.1.sql */ + +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION ip4r UPDATE TO '2.1'" to load this file. \quit + +-- ugh. no ALTER CAST + +UPDATE pg_catalog.pg_cast SET castcontext = 'a' + WHERE (castsource,casttarget) IN ( + ('ipaddress'::regtype, 'ip4'::regtype), + ('ipaddress'::regtype, 'ip6'::regtype), + ('iprange'::regtype, 'ip4r'::regtype), + ('iprange'::regtype, 'ip6r'::regtype)); + +-- double ugh, to finally fix long-standing issue with function signature +-- of gist consistent functions + +WITH v(gname,gtype) AS ( + VALUES ('gip4r_consistent'::name, 'ip4r'::regtype), + ('gip6r_consistent'::name, 'ip6r'::regtype), + ('gipr_consistent'::name, 'iprange'::regtype)) +UPDATE pg_catalog.pg_proc + SET pronargs = 5, + proargtypes = array_to_string(array['internal', + v.gtype, + 'int2', + 'oid', + 'internal']::regtype[]::oid[], + ' ')::pg_catalog.oidvector + FROM v + WHERE proname = v.gname + AND probin = 'MODULE_PATHNAME'; + +-- actual new stuff + +CREATE FUNCTION gip4r_fetch(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE FUNCTION gip6r_fetch(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE FUNCTION gipr_fetch(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; + +DO $s$ + BEGIN + IF current_setting('server_version_num')::integer >= 90500 THEN + ALTER OPERATOR FAMILY gist_ip4r_ops USING gist ADD + FUNCTION 9 (ip4r,ip4r) gip4r_fetch (internal); + ALTER OPERATOR FAMILY gist_ip6r_ops USING gist ADD + FUNCTION 9 (ip6r,ip6r) gip6r_fetch (internal); + ALTER OPERATOR FAMILY gist_iprange_ops USING gist ADD + FUNCTION 9 (iprange,iprange) gipr_fetch (internal); + END IF; + IF current_setting('server_version_num')::integer >= 90600 THEN + DECLARE + r record; + BEGIN + FOR r IN SELECT oid::regprocedure as fsig + FROM pg_catalog.pg_proc + WHERE (probin = 'MODULE_PATHNAME' + AND prolang = (SELECT oid FROM pg_catalog.pg_language l WHERE l.lanname='c')) + OR (oid in ('family(ip4)'::regprocedure, + 'family(ip6)'::regprocedure, + 'family(ip4r)'::regprocedure, + 'family(ip6r)'::regprocedure)) + LOOP + EXECUTE format('ALTER FUNCTION %s PARALLEL SAFE', r.fsig); + END LOOP; + END; + END IF; + END; +$s$; + +-- end diff -Nru ip4r-2.3/scripts/ip4r--2.1--2.2.sql ip4r-2.4/scripts/ip4r--2.1--2.2.sql --- ip4r-2.3/scripts/ip4r--2.1--2.2.sql 1970-01-01 00:00:00.000000000 +0000 +++ ip4r-2.4/scripts/ip4r--2.1--2.2.sql 2018-11-21 06:35:30.000000000 +0000 @@ -0,0 +1,25 @@ +/* ip4r--2.1--2.2.sql */ + +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION ip4r UPDATE TO '2.2'" to load this file. \quit + +-- There's nothing actually new in this version, but it fixes an +-- incorrect fix in 2.1. + +WITH v(gname,gtype) AS ( + VALUES ('gip4r_consistent'::name, 'ip4r'::regtype), + ('gip6r_consistent'::name, 'ip6r'::regtype), + ('gipr_consistent'::name, 'iprange'::regtype)) +UPDATE pg_catalog.pg_proc + SET pronargs = 5, + proargtypes = array_to_string(array['internal', + v.gtype, + 'int2', + 'oid', + 'internal']::regtype[]::oid[], + ' ')::pg_catalog.oidvector + FROM v + WHERE proname = v.gname + AND probin = 'MODULE_PATHNAME'; + +-- end diff -Nru ip4r-2.3/scripts/ip4r--2.2--2.4.sql ip4r-2.4/scripts/ip4r--2.2--2.4.sql --- ip4r-2.3/scripts/ip4r--2.2--2.4.sql 1970-01-01 00:00:00.000000000 +0000 +++ ip4r-2.4/scripts/ip4r--2.2--2.4.sql 2018-11-21 06:35:30.000000000 +0000 @@ -0,0 +1,240 @@ +/* ip4r--2.2--2.4.sql */ + +-- complain if script is sourced in psql, rather than via ALTER EXTENSION +\echo Use "ALTER EXTENSION ip4r UPDATE TO '2.4'" to load this file. \quit + +-- new funcs +CREATE FUNCTION cidr_split(ip4r) RETURNS SETOF ip4r AS 'MODULE_PATHNAME','ip4r_cidr_split' LANGUAGE C IMMUTABLE STRICT ROWS 10; +CREATE FUNCTION cidr_split(ip6r) RETURNS SETOF ip6r AS 'MODULE_PATHNAME','ip6r_cidr_split' LANGUAGE C IMMUTABLE STRICT ROWS 50; +CREATE FUNCTION cidr_split(iprange) RETURNS SETOF iprange AS 'MODULE_PATHNAME','iprange_cidr_split' LANGUAGE C IMMUTABLE STRICT ROWS 30; + +-- new casts +CREATE FUNCTION ip4(bit) RETURNS ip4 AS 'MODULE_PATHNAME','ip4_cast_from_bit' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4(varbit) RETURNS ip4 AS 'MODULE_PATHNAME','ip4_cast_from_bit' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4(bytea) RETURNS ip4 AS 'MODULE_PATHNAME','ip4_cast_from_bytea' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6(bit) RETURNS ip6 AS 'MODULE_PATHNAME','ip6_cast_from_bit' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6(varbit) RETURNS ip6 AS 'MODULE_PATHNAME','ip6_cast_from_bit' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6(bytea) RETURNS ip6 AS 'MODULE_PATHNAME','ip6_cast_from_bytea' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress(bit) RETURNS ipaddress AS 'MODULE_PATHNAME','ipaddr_cast_from_bit' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress(varbit) RETURNS ipaddress AS 'MODULE_PATHNAME','ipaddr_cast_from_bit' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress(bytea) RETURNS ipaddress AS 'MODULE_PATHNAME','ipaddr_cast_from_bytea' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4r(varbit) RETURNS ip4r AS 'MODULE_PATHNAME','ip4r_cast_from_bit' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6r(varbit) RETURNS ip6r AS 'MODULE_PATHNAME','ip6r_cast_from_bit' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION to_bit(ip4) RETURNS varbit AS 'MODULE_PATHNAME','ip4_cast_to_bit' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION to_bit(ip6) RETURNS varbit AS 'MODULE_PATHNAME','ip6_cast_to_bit' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION to_bit(ipaddress) RETURNS varbit AS 'MODULE_PATHNAME','ipaddr_cast_to_bit' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION to_bit(ip4r) RETURNS varbit AS 'MODULE_PATHNAME','ip4r_cast_to_bit' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION to_bit(ip6r) RETURNS varbit AS 'MODULE_PATHNAME','ip6r_cast_to_bit' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION to_bit(iprange) RETURNS varbit AS 'MODULE_PATHNAME','iprange_cast_to_bit' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION to_bytea(ip4) RETURNS bytea AS 'MODULE_PATHNAME','ip4_cast_to_bytea' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION to_bytea(ip6) RETURNS bytea AS 'MODULE_PATHNAME','ip6_cast_to_bytea' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION to_bytea(ipaddress) RETURNS bytea AS 'MODULE_PATHNAME','ipaddr_cast_to_bytea' LANGUAGE C IMMUTABLE STRICT; +CREATE CAST (ip4 as varbit) WITH FUNCTION to_bit(ip4); +CREATE CAST (ip4 as bytea) WITH FUNCTION to_bytea(ip4); +CREATE CAST (ip4r as varbit) WITH FUNCTION to_bit(ip4r); +CREATE CAST (ip6 as varbit) WITH FUNCTION to_bit(ip6); +CREATE CAST (ip6 as bytea) WITH FUNCTION to_bytea(ip6); +CREATE CAST (ip6r as varbit) WITH FUNCTION to_bit(ip6r); +CREATE CAST (ipaddress as varbit) WITH FUNCTION to_bit(ipaddress); +CREATE CAST (ipaddress as bytea) WITH FUNCTION to_bytea(ipaddress); +CREATE CAST (iprange as varbit) WITH FUNCTION to_bit(iprange); +CREATE CAST (bit as ip4) WITH FUNCTION ip4(bit); +CREATE CAST (bit as ip6) WITH FUNCTION ip6(bit); +CREATE CAST (bit as ipaddress) WITH FUNCTION ipaddress(bit); +CREATE CAST (varbit as ip4) WITH FUNCTION ip4(bit); +CREATE CAST (varbit as ip6) WITH FUNCTION ip6(bit); +CREATE CAST (varbit as ipaddress) WITH FUNCTION ipaddress(varbit); +CREATE CAST (varbit as ip4r) WITH FUNCTION ip4r(varbit); +CREATE CAST (varbit as ip6r) WITH FUNCTION ip6r(varbit); +CREATE CAST (bytea as ip4) WITH FUNCTION ip4(bytea); +CREATE CAST (bytea as ip6) WITH FUNCTION ip6(bytea); +CREATE CAST (bytea as ipaddress) WITH FUNCTION ipaddress(bytea); + +-- new hash funcs +COMMENT ON FUNCTION iprangehash(iprange) IS 'deprecated, obsolete'; +CREATE FUNCTION iprange_hash(iprange) RETURNS integer AS 'MODULE_PATHNAME', 'iprange_hash_new' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4_hash_extended(ip4,bigint) RETURNS bigint AS 'MODULE_PATHNAME', 'ip4_hash_extended' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6_hash_extended(ip6,bigint) RETURNS bigint AS 'MODULE_PATHNAME', 'ip6_hash_extended' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress_hash_extended(ipaddress,bigint) RETURNS bigint AS 'MODULE_PATHNAME', 'ipaddr_hash_extended' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4r_hash_extended(ip4r,bigint) RETURNS bigint AS 'MODULE_PATHNAME', 'ip4r_hash_extended' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6r_hash_extended(ip6r,bigint) RETURNS bigint AS 'MODULE_PATHNAME', 'ip6r_hash_extended' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange_hash_extended(iprange,bigint) RETURNS bigint AS 'MODULE_PATHNAME', 'iprange_hash_extended' LANGUAGE C IMMUTABLE STRICT; + +-- new btree/range funcs +CREATE FUNCTION in_range(ip4,ip4,bigint,boolean,boolean) RETURNS boolean AS 'MODULE_PATHNAME','ip4_in_range_bigint' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION in_range(ip4,ip4,ip4,boolean,boolean) RETURNS boolean AS 'MODULE_PATHNAME','ip4_in_range_ip4' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION in_range(ip6,ip6,bigint,boolean,boolean) RETURNS boolean AS 'MODULE_PATHNAME','ip6_in_range_bigint' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION in_range(ip6,ip6,ip6,boolean,boolean) RETURNS boolean AS 'MODULE_PATHNAME','ip6_in_range_ip6' LANGUAGE C IMMUTABLE STRICT; + +-- drop/create hash opclass + +DO $s$ + DECLARE + r record; + opc_oid oid; + deps oid[]; + cmds text[] := NULL; + str text; + cfgval text := NULL; + BEGIN + BEGIN + cfgval := current_setting('ip4r.update_indexes'); + EXCEPTION WHEN OTHERS THEN + cfgval := NULL; + END; + IF cfgval NOT IN ('drop','rebuild') THEN + cfgval := NULL; + END IF; + SELECT oid INTO opc_oid + FROM pg_opclass + WHERE opcname='hash_iprange_ops' + AND pg_opclass_is_visible(oid); + -- first check for unknown/unexpected dependencies + SELECT format('%s object %s depends on hash_iprange_ops with type ''%s''', + classid::regclass, objid, deptype) + INTO str + FROM pg_depend + WHERE refclassid = 'pg_opclass'::regclass + AND refobjid = opc_oid + AND classid <> 'pg_class'::regclass + AND deptype NOT IN ('a','i') + LIMIT 1; + IF FOUND THEN + RAISE EXCEPTION dependent_objects_still_exist USING + MESSAGE = 'unexpected dependency on hash opclass', + DETAIL = str; + END IF; + -- find all dependent tables and indexes + deps := ARRAY(SELECT objid FROM pg_depend + WHERE refclassid = 'pg_opclass'::regclass + AND refobjid = opc_oid + AND classid = 'pg_class'::regclass + AND deptype = 'n'); + IF deps <> '{}' THEN + -- we don't expect to find anything except indexes + SELECT format('Table %s depends on hash_iprange_ops', oid::regclass) + INTO str + FROM pg_class + WHERE oid = ANY (deps) + AND relkind <> 'i'; + IF FOUND THEN + RAISE EXCEPTION dependent_objects_still_exist USING + MESSAGE = 'unexpected table dependency on hash opclass', + DETAIL = str; + END IF; + -- must be only indexes, as expected + IF cfgval IS NULL THEN + FOR r IN SELECT ci.relname as indexname, + n.nspname as schemaname, + ct.relname as tablename + FROM pg_index i + JOIN pg_class ci ON ci.oid=i.indexrelid + JOIN pg_class ct ON ct.oid=i.indrelid + JOIN pg_namespace n ON n.oid=ct.relnamespace + WHERE i.indexrelid = ANY (deps) + LOOP + RAISE INFO USING + MESSAGE = format('index %I on table %I.%I depends on hash_iprange_ops', + r.indexname, r.schemaname, r.tablename); + END LOOP; + RAISE EXCEPTION dependent_objects_still_exist USING + MESSAGE = 'existing indexes depend on hash opclass', + DETAIL = 'See previous INFO messages for list', + HINT = 'Use SET ip4r.update_indexes = ''drop'' or ''rebuild'' to process automatically'; + ELSIF cfgval = 'drop' THEN + CREATE SCHEMA ip4r_update_to_2_4; + ALTER EXTENSION ip4r DROP SCHEMA ip4r_update_to_2_4; + CREATE TABLE ip4r_update_to_2_4.update_indexes + AS SELECT ct.oid as table_oid, + n.nspname as schemaname, + ct.relname as tablename, + ci.relname as indexname, + pg_get_indexdef(ci.oid) as command + FROM pg_index i + JOIN pg_class ci ON ci.oid=i.indexrelid + JOIN pg_class ct ON ct.oid=i.indrelid + JOIN pg_namespace n ON n.oid=ct.relnamespace + WHERE i.indexrelid = ANY (deps); + ALTER EXTENSION ip4r DROP TABLE ip4r_update_to_2_4.update_indexes; + FOR r IN SELECT format('DROP INDEX %s RESTRICT', o::regclass) as cmd + FROM UNNEST(deps) u(o) LOOP + RAISE INFO 'executing %', r.cmd; + EXECUTE r.cmd; + END LOOP; + ELSIF cfgval = 'rebuild' THEN + cmds := '{}'; + FOR r IN SELECT format('DROP INDEX %s RESTRICT', o::regclass) as dropcmd, + pg_get_indexdef(o) as createcmd + FROM UNNEST(deps) u(o) LOOP + RAISE INFO 'executing %', r.dropcmd; + EXECUTE r.dropcmd; + cmds := cmds || r.createcmd; + END LOOP; + END IF; + END IF; + -- have now processed any dependencies, so try the actual drop + -- this will error out on the RESTRICT if we somehow missed any + -- relevant dependency in our checks. + ALTER EXTENSION ip4r DROP OPERATOR CLASS hash_iprange_ops USING hash; + DROP OPERATOR CLASS hash_iprange_ops USING hash RESTRICT; + CREATE OPERATOR CLASS hash_iprange_ops DEFAULT FOR TYPE iprange USING hash AS + OPERATOR 1 = , + FUNCTION 1 iprange_hash(iprange); + IF cmds IS NOT NULL THEN + FOR r IN SELECT cmd FROM UNNEST(cmds) u(cmd) LOOP + -- we rely here on CREATE INDEX not recording a dependency on + -- the extension + RAISE INFO 'executing %', r.cmd; + EXECUTE r.cmd; + END LOOP; + RAISE INFO 'index rebuilds completed'; + ELSIF cfgval = 'drop' AND deps <> '{}' THEN + RAISE LOG 'table ip4r_update_to_2_4.update_indexes was created'; + RAISE INFO 'table ip4r_update_to_2_4.update_indexes was created'; + END IF; + END; +$s$; + +DO $s$ + DECLARE + pg_ver integer := current_setting('server_version_num')::integer; + r record; + BEGIN + IF pg_ver >= 90600 THEN + FOR r IN SELECT oid::regprocedure as fsig + FROM pg_catalog.pg_proc + WHERE (probin = 'MODULE_PATHNAME' + AND prolang = (SELECT oid FROM pg_catalog.pg_language l WHERE l.lanname='c')) + OR (oid in ('family(ip4)'::regprocedure, + 'family(ip6)'::regprocedure, + 'family(ip4r)'::regprocedure, + 'family(ip6r)'::regprocedure)) + LOOP + EXECUTE format('ALTER FUNCTION %s PARALLEL SAFE', r.fsig); + END LOOP; + END IF; + IF pg_ver >= 110000 THEN + FOR r IN SELECT tname + FROM UNNEST(ARRAY['ip4','ip4r', + 'ip6','ip6r', + 'ipaddress','iprange']) u(tname) + LOOP + EXECUTE format('ALTER OPERATOR FAMILY %I USING hash' + ' ADD FUNCTION 2 %I(%I,bigint)', + format('hash_%s_ops', r.tname), + format('%s_hash_extended', r.tname), + r.tname); + END LOOP; + ALTER OPERATOR FAMILY btree_ip4_ops USING btree + ADD FUNCTION 3 (ip4,bigint) in_range(ip4,ip4,bigint,boolean,boolean); + ALTER OPERATOR FAMILY btree_ip4_ops USING btree + ADD FUNCTION 3 (ip4,ip4) in_range(ip4,ip4,ip4,boolean,boolean); + ALTER OPERATOR FAMILY btree_ip6_ops USING btree + ADD FUNCTION 3 (ip6,bigint) in_range(ip6,ip6,bigint,boolean,boolean); + ALTER OPERATOR FAMILY btree_ip6_ops USING btree + ADD FUNCTION 3 (ip6,ip6) in_range(ip6,ip6,ip6,boolean,boolean); + END IF; + END; +$s$; + +-- end diff -Nru ip4r-2.3/scripts/ip4r--2.4.sql ip4r-2.4/scripts/ip4r--2.4.sql --- ip4r-2.3/scripts/ip4r--2.4.sql 1970-01-01 00:00:00.000000000 +0000 +++ ip4r-2.4/scripts/ip4r--2.4.sql 2018-11-21 06:35:30.000000000 +0000 @@ -0,0 +1,872 @@ +-- ip4r extension + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION ip4r" to load this file. \quit + +-- ---------------------------------------------------------------------- +-- Type definitions + +-- type creation is needlessly chatty + +CREATE TYPE ip4; + +CREATE FUNCTION ip4_in(cstring) RETURNS ip4 AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4_out(ip4) RETURNS cstring AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4_recv(internal) RETURNS ip4 AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4_send(ip4) RETURNS bytea AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +CREATE TYPE ip4 ( + INPUT = ip4_in, OUTPUT = ip4_out, + RECEIVE = ip4_recv, SEND = ip4_send, + INTERNALLENGTH = 4, ALIGNMENT = int4, PASSEDBYVALUE +); + +COMMENT ON TYPE ip4 IS 'IPv4 address ''#.#.#.#'''; + +CREATE TYPE ip4r; + +CREATE FUNCTION ip4r_in(cstring) RETURNS ip4r AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4r_out(ip4r) RETURNS cstring AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4r_recv(internal) RETURNS ip4r AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4r_send(ip4r) RETURNS bytea AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +CREATE TYPE ip4r ( + INPUT = ip4r_in, OUTPUT = ip4r_out, + RECEIVE = ip4r_recv, SEND = ip4r_send, + INTERNALLENGTH = 8, ALIGNMENT = int4 +); + +COMMENT ON TYPE ip4r IS 'IPv4 range ''#.#.#.#-#.#.#.#'' or ''#.#.#.#/#'' or ''#.#.#.#'''; + +CREATE TYPE ip6; + +CREATE FUNCTION ip6_in(cstring) RETURNS ip6 AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6_out(ip6) RETURNS cstring AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6_recv(internal) RETURNS ip6 AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6_send(ip6) RETURNS bytea AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +CREATE TYPE ip6 ( + INPUT = ip6_in, OUTPUT = ip6_out, + RECEIVE = ip6_recv, SEND = ip6_send, + INTERNALLENGTH = 16, ALIGNMENT = double +); + +COMMENT ON TYPE ip6 IS 'IPv6 address ''xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx'''; + +CREATE TYPE ip6r; + +CREATE FUNCTION ip6r_in(cstring) RETURNS ip6r AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6r_out(ip6r) RETURNS cstring AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6r_recv(internal) RETURNS ip6r AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6r_send(ip6r) RETURNS bytea AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +CREATE TYPE ip6r ( + INPUT = ip6r_in, OUTPUT = ip6r_out, + RECEIVE = ip6r_recv, SEND = ip6r_send, + INTERNALLENGTH = 32, ALIGNMENT = double +); + +COMMENT ON TYPE ip6r IS 'IPv6 range ''#-#'' or ''#/#'' or ''#'''; + +CREATE TYPE ipaddress; + +CREATE FUNCTION ipaddress_in(cstring) RETURNS ipaddress AS 'MODULE_PATHNAME','ipaddr_in' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress_out(ipaddress) RETURNS cstring AS 'MODULE_PATHNAME','ipaddr_out' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress_recv(internal) RETURNS ipaddress AS 'MODULE_PATHNAME','ipaddr_recv' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress_send(ipaddress) RETURNS bytea AS 'MODULE_PATHNAME','ipaddr_send' LANGUAGE C IMMUTABLE STRICT; + +CREATE TYPE ipaddress ( + INPUT = ipaddress_in, OUTPUT = ipaddress_out, + RECEIVE = ipaddress_recv, SEND = ipaddress_send, + INTERNALLENGTH = VARIABLE, ALIGNMENT = int4, STORAGE = main +); + +COMMENT ON TYPE ipaddress IS 'IPv4 or IPv6 address'; + +CREATE TYPE iprange; + +CREATE FUNCTION iprange_in(cstring) RETURNS iprange AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange_out(iprange) RETURNS cstring AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange_recv(internal) RETURNS iprange AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange_send(iprange) RETURNS bytea AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +CREATE TYPE iprange ( + INPUT = iprange_in, OUTPUT = iprange_out, + RECEIVE = iprange_recv, SEND = iprange_send, + INTERNALLENGTH = VARIABLE, ALIGNMENT = int4, STORAGE = main +); + +COMMENT ON TYPE iprange IS 'IPv4 or IPv6 range'; + +-- ---------------------------------------------------------------------- +-- Cast functions (inward) + +CREATE FUNCTION ip4(bigint) RETURNS ip4 AS 'MODULE_PATHNAME','ip4_cast_from_bigint' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4(double precision) RETURNS ip4 AS 'MODULE_PATHNAME','ip4_cast_from_double' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4(numeric) RETURNS ip4 AS 'MODULE_PATHNAME','ip4_cast_from_numeric' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4(inet) RETURNS ip4 AS 'MODULE_PATHNAME','ip4_cast_from_inet' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4(text) RETURNS ip4 AS 'MODULE_PATHNAME','ip4_cast_from_text' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4(bit) RETURNS ip4 AS 'MODULE_PATHNAME','ip4_cast_from_bit' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4(varbit) RETURNS ip4 AS 'MODULE_PATHNAME','ip4_cast_from_bit' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4(bytea) RETURNS ip4 AS 'MODULE_PATHNAME','ip4_cast_from_bytea' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4(ipaddress) RETURNS ip4 AS 'MODULE_PATHNAME','ipaddr_cast_to_ip4' LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION ip6(numeric) RETURNS ip6 AS 'MODULE_PATHNAME','ip6_cast_from_numeric' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6(inet) RETURNS ip6 AS 'MODULE_PATHNAME','ip6_cast_from_inet' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6(text) RETURNS ip6 AS 'MODULE_PATHNAME','ip6_cast_from_text' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6(bit) RETURNS ip6 AS 'MODULE_PATHNAME','ip6_cast_from_bit' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6(varbit) RETURNS ip6 AS 'MODULE_PATHNAME','ip6_cast_from_bit' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6(bytea) RETURNS ip6 AS 'MODULE_PATHNAME','ip6_cast_from_bytea' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6(ipaddress) RETURNS ip6 AS 'MODULE_PATHNAME','ipaddr_cast_to_ip6' LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION ipaddress(inet) RETURNS ipaddress AS 'MODULE_PATHNAME','ipaddr_cast_from_inet' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress(ip4) RETURNS ipaddress AS 'MODULE_PATHNAME','ipaddr_cast_from_ip4' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress(ip6) RETURNS ipaddress AS 'MODULE_PATHNAME','ipaddr_cast_from_ip6' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress(text) RETURNS ipaddress AS 'MODULE_PATHNAME','ipaddr_cast_from_text' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress(bit) RETURNS ipaddress AS 'MODULE_PATHNAME','ipaddr_cast_from_bit' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress(varbit) RETURNS ipaddress AS 'MODULE_PATHNAME','ipaddr_cast_from_bit' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress(bytea) RETURNS ipaddress AS 'MODULE_PATHNAME','ipaddr_cast_from_bytea' LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION ip4r(cidr) RETURNS ip4r AS 'MODULE_PATHNAME','ip4r_cast_from_cidr' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4r(ip4) RETURNS ip4r AS 'MODULE_PATHNAME','ip4r_cast_from_ip4' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4r(text) RETURNS ip4r AS 'MODULE_PATHNAME','ip4r_cast_from_text' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4r(varbit) RETURNS ip4r AS 'MODULE_PATHNAME','ip4r_cast_from_bit' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4r(iprange) RETURNS ip4r AS 'MODULE_PATHNAME','iprange_cast_to_ip4r' LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION ip6r(cidr) RETURNS ip6r AS 'MODULE_PATHNAME','ip6r_cast_from_cidr' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6r(ip6) RETURNS ip6r AS 'MODULE_PATHNAME','ip6r_cast_from_ip6' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6r(text) RETURNS ip6r AS 'MODULE_PATHNAME','ip6r_cast_from_text' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6r(varbit) RETURNS ip6r AS 'MODULE_PATHNAME','ip6r_cast_from_bit' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6r(iprange) RETURNS ip6r AS 'MODULE_PATHNAME','iprange_cast_to_ip6r' LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION iprange(cidr) RETURNS iprange AS 'MODULE_PATHNAME','iprange_cast_from_cidr' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange(ip4) RETURNS iprange AS 'MODULE_PATHNAME','iprange_cast_from_ip4' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange(ip6) RETURNS iprange AS 'MODULE_PATHNAME','iprange_cast_from_ip6' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange(ip4r) RETURNS iprange AS 'MODULE_PATHNAME','iprange_cast_from_ip4r' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange(ip6r) RETURNS iprange AS 'MODULE_PATHNAME','iprange_cast_from_ip6r' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange(ipaddress) RETURNS iprange AS 'MODULE_PATHNAME','iprange_cast_from_ipaddr' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange(text) RETURNS iprange AS 'MODULE_PATHNAME','iprange_cast_from_text' LANGUAGE C IMMUTABLE STRICT; + +-- ---------------------------------------------------------------------- +-- Cast functions (outward) + +CREATE FUNCTION cidr(ip4) RETURNS cidr AS 'MODULE_PATHNAME','ip4_cast_to_cidr' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION cidr(ip4r) RETURNS cidr AS 'MODULE_PATHNAME','ip4r_cast_to_cidr' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION cidr(ip6) RETURNS cidr AS 'MODULE_PATHNAME','ip6_cast_to_cidr' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION cidr(ip6r) RETURNS cidr AS 'MODULE_PATHNAME','ip6r_cast_to_cidr' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION cidr(ipaddress) RETURNS cidr AS 'MODULE_PATHNAME','ipaddr_cast_to_cidr' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION cidr(iprange) RETURNS cidr AS 'MODULE_PATHNAME','iprange_cast_to_cidr' LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION text(ip4) RETURNS text AS 'MODULE_PATHNAME','ip4_cast_to_text' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION text(ip4r) RETURNS text AS 'MODULE_PATHNAME','ip4r_cast_to_text' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION text(ip6) RETURNS text AS 'MODULE_PATHNAME','ip6_cast_to_text' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION text(ip6r) RETURNS text AS 'MODULE_PATHNAME','ip6r_cast_to_text' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION text(ipaddress) RETURNS text AS 'MODULE_PATHNAME','ipaddr_cast_to_text' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION text(iprange) RETURNS text AS 'MODULE_PATHNAME','iprange_cast_to_text' LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION to_bigint(ip4) RETURNS bigint AS 'MODULE_PATHNAME','ip4_cast_to_bigint' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION to_double(ip4) RETURNS double precision AS 'MODULE_PATHNAME','ip4_cast_to_double' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION to_numeric(ip4) RETURNS numeric AS 'MODULE_PATHNAME','ip4_cast_to_numeric' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION to_numeric(ip6) RETURNS numeric AS 'MODULE_PATHNAME','ip6_cast_to_numeric' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION to_numeric(ipaddress) RETURNS numeric AS 'MODULE_PATHNAME','ipaddr_cast_to_numeric' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION to_bit(ip4) RETURNS varbit AS 'MODULE_PATHNAME','ip4_cast_to_bit' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION to_bit(ip6) RETURNS varbit AS 'MODULE_PATHNAME','ip6_cast_to_bit' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION to_bit(ipaddress) RETURNS varbit AS 'MODULE_PATHNAME','ipaddr_cast_to_bit' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION to_bit(ip4r) RETURNS varbit AS 'MODULE_PATHNAME','ip4r_cast_to_bit' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION to_bit(ip6r) RETURNS varbit AS 'MODULE_PATHNAME','ip6r_cast_to_bit' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION to_bit(iprange) RETURNS varbit AS 'MODULE_PATHNAME','iprange_cast_to_bit' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION to_bytea(ip4) RETURNS bytea AS 'MODULE_PATHNAME','ip4_cast_to_bytea' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION to_bytea(ip6) RETURNS bytea AS 'MODULE_PATHNAME','ip6_cast_to_bytea' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION to_bytea(ipaddress) RETURNS bytea AS 'MODULE_PATHNAME','ipaddr_cast_to_bytea' LANGUAGE C IMMUTABLE STRICT; + +-- ---------------------------------------------------------------------- +-- Cast definitions (outward) + +-- all these are explicit, with the exception of casts from single-address +-- types to "cidr", which we make assignment casts since they are lossless +-- and preserve general semantics. + +CREATE CAST (ip4 as bigint) WITH FUNCTION to_bigint(ip4); +CREATE CAST (ip4 as double precision) WITH FUNCTION to_double(ip4); +CREATE CAST (ip4 as numeric) WITH FUNCTION to_numeric(ip4); +CREATE CAST (ip4 as varbit) WITH FUNCTION to_bit(ip4); +CREATE CAST (ip4 as bytea) WITH FUNCTION to_bytea(ip4); +CREATE CAST (ip4 as text) WITH FUNCTION text(ip4); + +CREATE CAST (ip4 as cidr) WITH FUNCTION cidr(ip4) AS ASSIGNMENT; + +CREATE CAST (ip4r as cidr) WITH FUNCTION cidr(ip4r); +CREATE CAST (ip4r as varbit) WITH FUNCTION to_bit(ip4r); +CREATE CAST (ip4r as text) WITH FUNCTION text(ip4r); + +CREATE CAST (ip6 as numeric) WITH FUNCTION to_numeric(ip6); +CREATE CAST (ip6 as varbit) WITH FUNCTION to_bit(ip6); +CREATE CAST (ip6 as bytea) WITH FUNCTION to_bytea(ip6); +CREATE CAST (ip6 as text) WITH FUNCTION text(ip6); + +CREATE CAST (ip6 as cidr) WITH FUNCTION cidr(ip6) AS ASSIGNMENT; + +CREATE CAST (ip6r as cidr) WITH FUNCTION cidr(ip6r); +CREATE CAST (ip6r as varbit) WITH FUNCTION to_bit(ip6r); +CREATE CAST (ip6r as text) WITH FUNCTION text(ip6r); + +CREATE CAST (ipaddress as numeric) WITH FUNCTION to_numeric(ipaddress); +CREATE CAST (ipaddress as varbit) WITH FUNCTION to_bit(ipaddress); +CREATE CAST (ipaddress as bytea) WITH FUNCTION to_bytea(ipaddress); +CREATE CAST (ipaddress as text) WITH FUNCTION text(ipaddress); + +CREATE CAST (ipaddress as cidr) WITH FUNCTION cidr(ipaddress) AS ASSIGNMENT; + +CREATE CAST (iprange as cidr) WITH FUNCTION cidr(iprange); +CREATE CAST (iprange as varbit) WITH FUNCTION to_bit(iprange); +CREATE CAST (iprange as text) WITH FUNCTION text(iprange); + +-- ---------------------------------------------------------------------- +-- Cast definitions (inward) + +-- these are explicit except for casts from inet/cidr types. Even though +-- such casts are lossy for inet, since the masklen isn't preserved, the +-- semantics and common usage are enough to justify an assignment cast. + +CREATE CAST (text as ip4) WITH FUNCTION ip4(text); +CREATE CAST (text as ip4r) WITH FUNCTION ip4r(text); +CREATE CAST (text as ip6) WITH FUNCTION ip6(text); +CREATE CAST (text as ip6r) WITH FUNCTION ip6r(text); +CREATE CAST (text as ipaddress) WITH FUNCTION ipaddress(text); +CREATE CAST (text as iprange) WITH FUNCTION iprange(text); + +CREATE CAST (bigint as ip4) WITH FUNCTION ip4(bigint); +CREATE CAST (double precision as ip4) WITH FUNCTION ip4(double precision); + +CREATE CAST (numeric as ip4) WITH FUNCTION ip4(numeric); +CREATE CAST (numeric as ip6) WITH FUNCTION ip6(numeric); + +CREATE CAST (bit as ip4) WITH FUNCTION ip4(bit); +CREATE CAST (bit as ip6) WITH FUNCTION ip6(bit); +CREATE CAST (bit as ipaddress) WITH FUNCTION ipaddress(bit); + +CREATE CAST (varbit as ip4) WITH FUNCTION ip4(bit); +CREATE CAST (varbit as ip6) WITH FUNCTION ip6(bit); +CREATE CAST (varbit as ipaddress) WITH FUNCTION ipaddress(varbit); +CREATE CAST (varbit as ip4r) WITH FUNCTION ip4r(varbit); +CREATE CAST (varbit as ip6r) WITH FUNCTION ip6r(varbit); + +CREATE CAST (bytea as ip4) WITH FUNCTION ip4(bytea); +CREATE CAST (bytea as ip6) WITH FUNCTION ip6(bytea); +CREATE CAST (bytea as ipaddress) WITH FUNCTION ipaddress(bytea); + +CREATE CAST (cidr as ip4r) WITH FUNCTION ip4r(cidr) AS ASSIGNMENT; +CREATE CAST (cidr as ip6r) WITH FUNCTION ip6r(cidr) AS ASSIGNMENT; +CREATE CAST (cidr as iprange) WITH FUNCTION iprange(cidr) AS ASSIGNMENT; + +CREATE CAST (inet as ip4) WITH FUNCTION ip4(inet) AS ASSIGNMENT; +CREATE CAST (inet as ip6) WITH FUNCTION ip6(inet) AS ASSIGNMENT; +CREATE CAST (inet as ipaddress) WITH FUNCTION ipaddress(inet) AS ASSIGNMENT; + +-- ---------------------------------------------------------------------- +-- Cast definitions (cross-type) + +-- the lossless "upward" casts are made implict. Downward casts are now +-- assignment casts. + +CREATE CAST (ip4 as ip4r) WITH FUNCTION ip4r(ip4) AS IMPLICIT; +CREATE CAST (ip4 as ipaddress) WITH FUNCTION ipaddress(ip4) AS IMPLICIT; +CREATE CAST (ip4 as iprange) WITH FUNCTION iprange(ip4) AS IMPLICIT; +CREATE CAST (ip4r as iprange) WITH FUNCTION iprange(ip4r) AS IMPLICIT; + +CREATE CAST (ip6 as ip6r) WITH FUNCTION ip6r(ip6) AS IMPLICIT; +CREATE CAST (ip6 as ipaddress) WITH FUNCTION ipaddress(ip6) AS IMPLICIT; +CREATE CAST (ip6 as iprange) WITH FUNCTION iprange(ip6) AS IMPLICIT; +CREATE CAST (ip6r as iprange) WITH FUNCTION iprange(ip6r) AS IMPLICIT; + +CREATE CAST (ipaddress as iprange) WITH FUNCTION iprange(ipaddress) AS IMPLICIT; + +CREATE CAST (ipaddress as ip4) WITH FUNCTION ip4(ipaddress) AS ASSIGNMENT; +CREATE CAST (ipaddress as ip6) WITH FUNCTION ip6(ipaddress) AS ASSIGNMENT; + +CREATE CAST (iprange as ip4r) WITH FUNCTION ip4r(iprange) AS ASSIGNMENT; +CREATE CAST (iprange as ip6r) WITH FUNCTION ip6r(iprange) AS ASSIGNMENT; + +-- ---------------------------------------------------------------------- +-- Constructor functions + +CREATE FUNCTION ip4r(ip4,ip4) RETURNS ip4r AS 'MODULE_PATHNAME', 'ip4r_from_ip4s' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6r(ip6,ip6) RETURNS ip6r AS 'MODULE_PATHNAME', 'ip6r_from_ip6s' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange(ip4,ip4) RETURNS iprange AS 'MODULE_PATHNAME', 'iprange_from_ip4s' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange(ip6,ip6) RETURNS iprange AS 'MODULE_PATHNAME', 'iprange_from_ip6s' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange(ipaddress,ipaddress) RETURNS iprange AS 'MODULE_PATHNAME', 'iprange_from_ipaddrs' LANGUAGE C IMMUTABLE STRICT; + +-- ---------------------------------------------------------------------- +-- Utility functions (no operator equivalent) + +CREATE FUNCTION family(ip4) RETURNS integer AS $f$ select 4; $f$ LANGUAGE SQL IMMUTABLE; +CREATE FUNCTION family(ip4r) RETURNS integer AS $f$ select 4; $f$ LANGUAGE SQL IMMUTABLE; +CREATE FUNCTION family(ip6) RETURNS integer AS $f$ select 6; $f$ LANGUAGE SQL IMMUTABLE; +CREATE FUNCTION family(ip6r) RETURNS integer AS $f$ select 6; $f$ LANGUAGE SQL IMMUTABLE; +CREATE FUNCTION family(ipaddress) RETURNS integer AS 'MODULE_PATHNAME', 'ipaddr_family' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION family(iprange) RETURNS integer AS 'MODULE_PATHNAME', 'iprange_family' LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION ip4_netmask(integer) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_netmask' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6_netmask(integer) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_netmask' LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION is_cidr(ip4r) RETURNS boolean AS 'MODULE_PATHNAME', 'ip4r_is_cidr' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION is_cidr(ip6r) RETURNS boolean AS 'MODULE_PATHNAME', 'ip6r_is_cidr' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION is_cidr(iprange) RETURNS boolean AS 'MODULE_PATHNAME', 'iprange_is_cidr' LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION masklen(ip4r) RETURNS integer AS 'MODULE_PATHNAME','ip4r_prefixlen' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION masklen(ip6r) RETURNS integer AS 'MODULE_PATHNAME','ip6r_prefixlen' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION masklen(iprange) RETURNS integer AS 'MODULE_PATHNAME','iprange_prefixlen' LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION lower(ip4r) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4r_lower' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION lower(ip6r) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6r_lower' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION lower(iprange) RETURNS ipaddress AS 'MODULE_PATHNAME', 'iprange_lower' LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION upper(ip4r) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4r_upper' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION upper(ip6r) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6r_upper' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION upper(iprange) RETURNS ipaddress AS 'MODULE_PATHNAME', 'iprange_upper' LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION ip4_net_lower(ip4,integer) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_net_lower' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6_net_lower(ip6,integer) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_net_lower' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress_net_lower(ipaddress,integer) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_net_lower' LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION ip4_net_upper(ip4,integer) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_net_upper' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6_net_upper(ip6,integer) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_net_upper' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress_net_upper(ipaddress,integer) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_net_upper' LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION ip4r_union(ip4r, ip4r) RETURNS ip4r AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6r_union(ip6r, ip6r) RETURNS ip6r AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange_union(iprange, iprange) RETURNS iprange AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION ip4r_inter(ip4r,ip4r) RETURNS ip4r AS 'MODULE_PATHNAME','ip4r_inter' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6r_inter(ip6r,ip6r) RETURNS ip6r AS 'MODULE_PATHNAME','ip6r_inter' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange_inter(iprange,iprange) RETURNS iprange AS 'MODULE_PATHNAME','iprange_inter' LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION cidr_split(ip4r) RETURNS SETOF ip4r AS 'MODULE_PATHNAME','ip4r_cidr_split' LANGUAGE C IMMUTABLE STRICT ROWS 10; +CREATE FUNCTION cidr_split(ip6r) RETURNS SETOF ip6r AS 'MODULE_PATHNAME','ip6r_cidr_split' LANGUAGE C IMMUTABLE STRICT ROWS 50; +CREATE FUNCTION cidr_split(iprange) RETURNS SETOF iprange AS 'MODULE_PATHNAME','iprange_cidr_split' LANGUAGE C IMMUTABLE STRICT ROWS 30; + +-- ---------------------------------------------------------------------- +-- Functions with operator equivalents + +-- it's intended that either the function form or the operator form be used, +-- as desired. + +-- (ip / len) or (ip / mask) + +CREATE FUNCTION ip4r_net_mask(ip4,ip4) RETURNS ip4r AS 'MODULE_PATHNAME','ip4r_net_mask' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6r_net_mask(ip6,ip6) RETURNS ip6r AS 'MODULE_PATHNAME','ip6r_net_mask' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange_net_mask(ip4,ip4) RETURNS iprange AS 'MODULE_PATHNAME','iprange_net_mask_ip4' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange_net_mask(ip6,ip6) RETURNS iprange AS 'MODULE_PATHNAME','iprange_net_mask_ip6' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange_net_mask(ipaddress,ipaddress) RETURNS iprange AS 'MODULE_PATHNAME','iprange_net_mask' LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION ip4r_net_prefix(ip4,integer) RETURNS ip4r AS 'MODULE_PATHNAME','ip4r_net_prefix' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6r_net_prefix(ip6,integer) RETURNS ip6r AS 'MODULE_PATHNAME','ip6r_net_prefix' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange_net_prefix(ip4,integer) RETURNS iprange AS 'MODULE_PATHNAME','iprange_net_prefix_ip4' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange_net_prefix(ip6,integer) RETURNS iprange AS 'MODULE_PATHNAME','iprange_net_prefix_ip6' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange_net_prefix(ipaddress,integer) RETURNS iprange AS 'MODULE_PATHNAME','iprange_net_prefix' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR / ( LEFTARG = ip4, RIGHTARG = ip4, PROCEDURE = ip4r_net_mask ); +CREATE OPERATOR / ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6r_net_mask ); +CREATE OPERATOR / ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = iprange_net_mask ); +CREATE OPERATOR / ( LEFTARG = ip4, RIGHTARG = integer, PROCEDURE = ip4r_net_prefix ); +CREATE OPERATOR / ( LEFTARG = ip6, RIGHTARG = integer, PROCEDURE = ip6r_net_prefix ); +CREATE OPERATOR / ( LEFTARG = ipaddress, RIGHTARG = integer, PROCEDURE = iprange_net_prefix ); + +-- @ ipr (approximate size) or @@ ipr (exact size) + +CREATE FUNCTION ip4r_size(ip4r) RETURNS double precision AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6r_size(ip6r) RETURNS double precision AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange_size(iprange) RETURNS double precision AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION ip4r_size_exact(ip4r) RETURNS numeric AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6r_size_exact(ip6r) RETURNS numeric AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange_size_exact(iprange) RETURNS numeric AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR @ ( RIGHTARG = ip4r, PROCEDURE = ip4r_size ); +CREATE OPERATOR @ ( RIGHTARG = ip6r, PROCEDURE = ip6r_size ); +CREATE OPERATOR @ ( RIGHTARG = iprange, PROCEDURE = iprange_size ); + +CREATE OPERATOR @@ ( RIGHTARG = ip4r, PROCEDURE = ip4r_size_exact ); +CREATE OPERATOR @@ ( RIGHTARG = ip6r, PROCEDURE = ip6r_size_exact ); +CREATE OPERATOR @@ ( RIGHTARG = iprange, PROCEDURE = iprange_size_exact ); + +-- ---------------------------------------------------------------------- +-- Operators + +-- the function forms of these aren't intended for general use + +-- bitwise ops: and (a & b), or (a | b), xor (a # b), not (~a) + +CREATE FUNCTION ip4_and(ip4,ip4) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_and' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6_and(ip6,ip6) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_and' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress_and(ipaddress,ipaddress) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_and' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR & ( LEFTARG = ip4, RIGHTARG = ip4, PROCEDURE = ip4_and ); +CREATE OPERATOR & ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_and ); +CREATE OPERATOR & ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_and ); + +CREATE FUNCTION ip4_or(ip4,ip4) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_or' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6_or(ip6,ip6) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_or' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress_or(ipaddress,ipaddress) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_or' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR | ( LEFTARG = ip4, RIGHTARG = ip4, PROCEDURE = ip4_or ); +CREATE OPERATOR | ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_or ); +CREATE OPERATOR | ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_or ); + +CREATE FUNCTION ip4_not(ip4) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_not' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6_not(ip6) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_not' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress_not(ipaddress) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_not' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR ~ ( RIGHTARG = ip4, PROCEDURE = ip4_not ); +CREATE OPERATOR ~ ( RIGHTARG = ip6, PROCEDURE = ip6_not ); +CREATE OPERATOR ~ ( RIGHTARG = ipaddress, PROCEDURE = ipaddress_not ); + +CREATE FUNCTION ip4_xor(ip4,ip4) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_xor' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6_xor(ip6,ip6) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_xor' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress_xor(ipaddress,ipaddress) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_xor' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR # ( LEFTARG = ip4, RIGHTARG = ip4, PROCEDURE = ip4_xor ); +CREATE OPERATOR # ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_xor ); +CREATE OPERATOR # ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_xor ); + +-- arithmetic ops: (ip + n), (ip - n), (ip - ip) where n is a numeric or integer type + +CREATE FUNCTION ip4_plus_bigint(ip4,bigint) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_plus_bigint' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4_plus_int(ip4,integer) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_plus_int' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4_plus_numeric(ip4,numeric) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_plus_numeric' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR + ( LEFTARG = ip4, RIGHTARG = bigint, PROCEDURE = ip4_plus_bigint ); +CREATE OPERATOR + ( LEFTARG = ip4, RIGHTARG = integer, PROCEDURE = ip4_plus_int ); +CREATE OPERATOR + ( LEFTARG = ip4, RIGHTARG = numeric, PROCEDURE = ip4_plus_numeric ); + +CREATE FUNCTION ip6_plus_bigint(ip6,bigint) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_plus_bigint' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6_plus_int(ip6,integer) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_plus_int' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6_plus_numeric(ip6,numeric) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_plus_numeric' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR + ( LEFTARG = ip6, RIGHTARG = bigint, PROCEDURE = ip6_plus_bigint ); +CREATE OPERATOR + ( LEFTARG = ip6, RIGHTARG = integer, PROCEDURE = ip6_plus_int ); +CREATE OPERATOR + ( LEFTARG = ip6, RIGHTARG = numeric, PROCEDURE = ip6_plus_numeric ); + +CREATE FUNCTION ipaddress_plus_bigint(ipaddress,bigint) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_plus_bigint' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress_plus_int(ipaddress,integer) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_plus_int' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress_plus_numeric(ipaddress,numeric) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_plus_numeric' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR + ( LEFTARG = ipaddress, RIGHTARG = bigint, PROCEDURE = ipaddress_plus_bigint ); +CREATE OPERATOR + ( LEFTARG = ipaddress, RIGHTARG = integer, PROCEDURE = ipaddress_plus_int ); +CREATE OPERATOR + ( LEFTARG = ipaddress, RIGHTARG = numeric, PROCEDURE = ipaddress_plus_numeric ); + +CREATE FUNCTION ip4_minus_bigint(ip4,bigint) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_minus_bigint' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4_minus_int(ip4,integer) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_minus_int' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4_minus_numeric(ip4,numeric) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_minus_numeric' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR - ( LEFTARG = ip4, RIGHTARG = bigint, PROCEDURE = ip4_minus_bigint ); +CREATE OPERATOR - ( LEFTARG = ip4, RIGHTARG = integer, PROCEDURE = ip4_minus_int ); +CREATE OPERATOR - ( LEFTARG = ip4, RIGHTARG = numeric, PROCEDURE = ip4_minus_numeric ); + +CREATE FUNCTION ip6_minus_bigint(ip6,bigint) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_minus_bigint' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6_minus_int(ip6,integer) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_minus_int' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6_minus_numeric(ip6,numeric) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_minus_numeric' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR - ( LEFTARG = ip6, RIGHTARG = bigint, PROCEDURE = ip6_minus_bigint ); +CREATE OPERATOR - ( LEFTARG = ip6, RIGHTARG = integer, PROCEDURE = ip6_minus_int ); +CREATE OPERATOR - ( LEFTARG = ip6, RIGHTARG = numeric, PROCEDURE = ip6_minus_numeric ); + +CREATE FUNCTION ipaddress_minus_bigint(ipaddress,bigint) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_minus_bigint' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress_minus_int(ipaddress,integer) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_minus_int' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress_minus_numeric(ipaddress,numeric) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_minus_numeric' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR - ( LEFTARG = ipaddress, RIGHTARG = bigint, PROCEDURE = ipaddress_minus_bigint ); +CREATE OPERATOR - ( LEFTARG = ipaddress, RIGHTARG = integer, PROCEDURE = ipaddress_minus_int ); +CREATE OPERATOR - ( LEFTARG = ipaddress, RIGHTARG = numeric, PROCEDURE = ipaddress_minus_numeric ); + +CREATE FUNCTION ip4_minus_ip4(ip4,ip4) RETURNS bigint AS 'MODULE_PATHNAME', 'ip4_minus_ip4' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6_minus_ip6(ip6,ip6) RETURNS numeric AS 'MODULE_PATHNAME', 'ip6_minus_ip6' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress_minus_ipaddress(ipaddress,ipaddress) RETURNS numeric AS 'MODULE_PATHNAME', 'ipaddr_minus_ipaddr' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR - ( LEFTARG = ip4, RIGHTARG = ip4, PROCEDURE = ip4_minus_ip4 ); +CREATE OPERATOR - ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_minus_ip6 ); +CREATE OPERATOR - ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_minus_ipaddress ); + +-- containment predicates: (a >>= b), (a >> b), (a <<= b), (a << b), (a && b) + +CREATE FUNCTION ip4r_contained_by(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6r_contained_by(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange_contained_by(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR <<= ( LEFTARG = ip4r, RIGHTARG = ip4r, PROCEDURE = ip4r_contained_by, COMMUTATOR = '>>=', RESTRICT = contsel, JOIN = contjoinsel ); +CREATE OPERATOR <<= ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_contained_by, COMMUTATOR = '>>=', RESTRICT = contsel, JOIN = contjoinsel ); +CREATE OPERATOR <<= ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_contained_by, COMMUTATOR = '>>=', RESTRICT = contsel, JOIN = contjoinsel ); + +CREATE FUNCTION ip4r_contained_by_strict(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6r_contained_by_strict(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange_contained_by_strict(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR << ( LEFTARG = ip4r, RIGHTARG = ip4r, PROCEDURE = ip4r_contained_by_strict, COMMUTATOR = '>>', RESTRICT = contsel, JOIN = contjoinsel ); +CREATE OPERATOR << ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_contained_by_strict, COMMUTATOR = '>>', RESTRICT = contsel, JOIN = contjoinsel ); +CREATE OPERATOR << ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_contained_by_strict, COMMUTATOR = '>>', RESTRICT = contsel, JOIN = contjoinsel ); + +CREATE FUNCTION ip4r_contains(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6r_contains(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange_contains(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR >>= ( LEFTARG = ip4r, RIGHTARG = ip4r, PROCEDURE = ip4r_contains, COMMUTATOR = '<<=', RESTRICT = contsel, JOIN = contjoinsel ); +CREATE OPERATOR >>= ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_contains, COMMUTATOR = '<<=', RESTRICT = contsel, JOIN = contjoinsel ); +CREATE OPERATOR >>= ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_contains, COMMUTATOR = '<<=', RESTRICT = contsel, JOIN = contjoinsel ); + +CREATE FUNCTION ip4r_contains_strict(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6r_contains_strict(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange_contains_strict(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR >> ( LEFTARG = ip4r, RIGHTARG = ip4r, PROCEDURE = ip4r_contains_strict, COMMUTATOR = '<<', RESTRICT = contsel, JOIN = contjoinsel ); +CREATE OPERATOR >> ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_contains_strict, COMMUTATOR = '<<', RESTRICT = contsel, JOIN = contjoinsel ); +CREATE OPERATOR >> ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_contains_strict, COMMUTATOR = '<<', RESTRICT = contsel, JOIN = contjoinsel ); + +CREATE FUNCTION ip4r_overlaps(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6r_overlaps(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange_overlaps(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR && ( LEFTARG = ip4r, RIGHTARG = ip4r, PROCEDURE = ip4r_overlaps, COMMUTATOR = '&&', RESTRICT = areasel, JOIN = areajoinsel ); +CREATE OPERATOR && ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_overlaps, COMMUTATOR = '&&', RESTRICT = areasel, JOIN = areajoinsel ); +CREATE OPERATOR && ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_overlaps, COMMUTATOR = '&&', RESTRICT = areasel, JOIN = areajoinsel ); + +-- cross-type containment +-- no operators for these since they seem to do more harm than good. These cases +-- are handled by implicit casts instead. + +CREATE FUNCTION ip4_contained_by(ip4,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4_contained_by(ip4,iprange) RETURNS bool AS 'MODULE_PATHNAME','iprange_ip4_contained_by' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6_contained_by(ip6,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6_contained_by(ip6,iprange) RETURNS bool AS 'MODULE_PATHNAME','iprange_ip6_contained_by' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress_contained_by(ipaddress,iprange) RETURNS bool AS 'MODULE_PATHNAME','iprange_ip_contained_by' LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION ip4_contains(ip4r,ip4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6_contains(ip6r,ip6) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4_contains(iprange,ip4) RETURNS bool AS 'MODULE_PATHNAME','iprange_contains_ip4' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6_contains(iprange,ip6) RETURNS bool AS 'MODULE_PATHNAME','iprange_contains_ip6' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress_contains(iprange,ipaddress) RETURNS bool AS 'MODULE_PATHNAME','iprange_contains_ip' LANGUAGE C IMMUTABLE STRICT; + +-- btree (strict weak) ordering operators +-- meaning of < > for ip4 and ip6 is obvious. +-- for ipaddress, all ip4 addresses are less than all ip6 addresses +-- for ip4r/ip6r, the order is lexicographic on (lower,upper) +-- for iprange, the universal range is lowest, then all ip4 ranges, then ip6 + +CREATE FUNCTION ip4_eq(ip4,ip4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4r_eq(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6_eq(ip6,ip6) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6r_eq(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress_eq(ipaddress,ipaddress) RETURNS bool AS 'MODULE_PATHNAME','ipaddr_eq' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange_eq(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR = ( LEFTARG = ip4, RIGHTARG = ip4, PROCEDURE = ip4_eq, COMMUTATOR = '=', NEGATOR = '<>', RESTRICT = eqsel, JOIN = eqjoinsel, SORT1 = '<', SORT2 = '<', HASHES ); +CREATE OPERATOR = ( LEFTARG = ip4r, RIGHTARG = ip4r, PROCEDURE = ip4r_eq, COMMUTATOR = '=', NEGATOR = '<>', RESTRICT = eqsel, JOIN = eqjoinsel, SORT1 = '<', SORT2 = '<', HASHES ); +CREATE OPERATOR = ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_eq, COMMUTATOR = '=', NEGATOR = '<>', RESTRICT = eqsel, JOIN = eqjoinsel, SORT1 = '<', SORT2 = '<', HASHES ); +CREATE OPERATOR = ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_eq, COMMUTATOR = '=', NEGATOR = '<>', RESTRICT = eqsel, JOIN = eqjoinsel, SORT1 = '<', SORT2 = '<', HASHES ); +CREATE OPERATOR = ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_eq, COMMUTATOR = '=', NEGATOR = '<>', RESTRICT = eqsel, JOIN = eqjoinsel, SORT1 = '<', SORT2 = '<', HASHES ); +CREATE OPERATOR = ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_eq, COMMUTATOR = '=', NEGATOR = '<>', RESTRICT = eqsel, JOIN = eqjoinsel, SORT1 = '<', SORT2 = '<', HASHES ); + +CREATE FUNCTION ip4_ge(ip4,ip4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4r_ge(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6_ge(ip6,ip6) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6r_ge(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress_ge(ipaddress,ipaddress) RETURNS bool AS 'MODULE_PATHNAME','ipaddr_ge' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange_ge(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR >= ( LEFTARG = ip4, RIGHTARG = ip4, PROCEDURE = ip4_ge, COMMUTATOR = '<=', NEGATOR = '<', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); +CREATE OPERATOR >= ( LEFTARG = ip4r, RIGHTARG = ip4r, PROCEDURE = ip4r_ge, COMMUTATOR = '<=', NEGATOR = '<', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); +CREATE OPERATOR >= ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_ge, COMMUTATOR = '<=', NEGATOR = '<', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); +CREATE OPERATOR >= ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_ge, COMMUTATOR = '<=', NEGATOR = '<', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); +CREATE OPERATOR >= ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_ge, COMMUTATOR = '<=', NEGATOR = '<', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); +CREATE OPERATOR >= ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_ge, COMMUTATOR = '<=', NEGATOR = '<', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); + +CREATE FUNCTION ip4_gt(ip4,ip4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4r_gt(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6_gt(ip6,ip6) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6r_gt(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress_gt(ipaddress,ipaddress) RETURNS bool AS 'MODULE_PATHNAME','ipaddr_gt' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange_gt(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR > ( LEFTARG = ip4, RIGHTARG = ip4, PROCEDURE = ip4_gt, COMMUTATOR = '<', NEGATOR = '<=', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); +CREATE OPERATOR > ( LEFTARG = ip4r, RIGHTARG = ip4r, PROCEDURE = ip4r_gt, COMMUTATOR = '<', NEGATOR = '<=', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); +CREATE OPERATOR > ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_gt, COMMUTATOR = '<', NEGATOR = '<=', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); +CREATE OPERATOR > ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_gt, COMMUTATOR = '<', NEGATOR = '<=', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); +CREATE OPERATOR > ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_gt, COMMUTATOR = '<', NEGATOR = '<=', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); +CREATE OPERATOR > ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_gt, COMMUTATOR = '<', NEGATOR = '<=', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); + +CREATE FUNCTION ip4_le(ip4,ip4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4r_le(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6_le(ip6,ip6) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6r_le(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress_le(ipaddress,ipaddress) RETURNS bool AS 'MODULE_PATHNAME','ipaddr_le' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange_le(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR <= ( LEFTARG = ip4, RIGHTARG = ip4, PROCEDURE = ip4_le, COMMUTATOR = '>=', NEGATOR = '>', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); +CREATE OPERATOR <= ( LEFTARG = ip4r, RIGHTARG = ip4r, PROCEDURE = ip4r_le, COMMUTATOR = '>=', NEGATOR = '>', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); +CREATE OPERATOR <= ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_le, COMMUTATOR = '>=', NEGATOR = '>', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); +CREATE OPERATOR <= ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_le, COMMUTATOR = '>=', NEGATOR = '>', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); +CREATE OPERATOR <= ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_le, COMMUTATOR = '>=', NEGATOR = '>', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); +CREATE OPERATOR <= ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_le, COMMUTATOR = '>=', NEGATOR = '>', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); + +CREATE FUNCTION ip4_lt(ip4,ip4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4r_lt(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6_lt(ip6,ip6) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6r_lt(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress_lt(ipaddress,ipaddress) RETURNS bool AS 'MODULE_PATHNAME','ipaddr_lt' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange_lt(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR < ( LEFTARG = ip4, RIGHTARG = ip4, PROCEDURE = ip4_lt, COMMUTATOR = '>', NEGATOR = '>=', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); +CREATE OPERATOR < ( LEFTARG = ip4r, RIGHTARG = ip4r, PROCEDURE = ip4r_lt, COMMUTATOR = '>', NEGATOR = '>=', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); +CREATE OPERATOR < ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_lt, COMMUTATOR = '>', NEGATOR = '>=', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); +CREATE OPERATOR < ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_lt, COMMUTATOR = '>', NEGATOR = '>=', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); +CREATE OPERATOR < ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_lt, COMMUTATOR = '>', NEGATOR = '>=', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); +CREATE OPERATOR < ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_lt, COMMUTATOR = '>', NEGATOR = '>=', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); + +CREATE FUNCTION ip4_neq(ip4,ip4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4r_neq(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6_neq(ip6,ip6) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6r_neq(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress_neq(ipaddress,ipaddress) RETURNS bool AS 'MODULE_PATHNAME','ipaddr_neq' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange_neq(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR <> ( LEFTARG = ip4, RIGHTARG = ip4, PROCEDURE = ip4_neq, COMMUTATOR = '<>', NEGATOR = '=', RESTRICT = neqsel, JOIN = neqjoinsel ); +CREATE OPERATOR <> ( LEFTARG = ip4r, RIGHTARG = ip4r, PROCEDURE = ip4r_neq, COMMUTATOR = '<>', NEGATOR = '=', RESTRICT = neqsel, JOIN = neqjoinsel ); +CREATE OPERATOR <> ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_neq, COMMUTATOR = '<>', NEGATOR = '=', RESTRICT = neqsel, JOIN = neqjoinsel ); +CREATE OPERATOR <> ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_neq, COMMUTATOR = '<>', NEGATOR = '=', RESTRICT = neqsel, JOIN = neqjoinsel ); +CREATE OPERATOR <> ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_neq, COMMUTATOR = '<>', NEGATOR = '=', RESTRICT = neqsel, JOIN = neqjoinsel ); +CREATE OPERATOR <> ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_neq, COMMUTATOR = '<>', NEGATOR = '=', RESTRICT = neqsel, JOIN = neqjoinsel ); + +-- ---------------------------------------------------------------------- +-- Btree index + +CREATE FUNCTION ip4_cmp(ip4,ip4) RETURNS integer AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4r_cmp(ip4r,ip4r) RETURNS integer AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6_cmp(ip6,ip6) RETURNS integer AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6r_cmp(ip6r,ip6r) RETURNS integer AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress_cmp(ipaddress,ipaddress) RETURNS integer AS 'MODULE_PATHNAME','ipaddr_cmp' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange_cmp(iprange,iprange) RETURNS integer AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION in_range(ip4,ip4,bigint,boolean,boolean) RETURNS boolean AS 'MODULE_PATHNAME','ip4_in_range_bigint' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION in_range(ip4,ip4,ip4,boolean,boolean) RETURNS boolean AS 'MODULE_PATHNAME','ip4_in_range_ip4' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION in_range(ip6,ip6,bigint,boolean,boolean) RETURNS boolean AS 'MODULE_PATHNAME','ip6_in_range_bigint' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION in_range(ip6,ip6,ip6,boolean,boolean) RETURNS boolean AS 'MODULE_PATHNAME','ip6_in_range_ip6' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR CLASS btree_ip4_ops DEFAULT FOR TYPE ip4 USING btree AS + OPERATOR 1 < , + OPERATOR 2 <= , + OPERATOR 3 = , + OPERATOR 4 >= , + OPERATOR 5 > , + FUNCTION 1 ip4_cmp(ip4, ip4); + +CREATE OPERATOR CLASS btree_ip4r_ops DEFAULT FOR TYPE ip4r USING btree AS + OPERATOR 1 < , + OPERATOR 2 <= , + OPERATOR 3 = , + OPERATOR 4 >= , + OPERATOR 5 > , + FUNCTION 1 ip4r_cmp(ip4r, ip4r); + +CREATE OPERATOR CLASS btree_ip6_ops DEFAULT FOR TYPE ip6 USING btree AS + OPERATOR 1 < , + OPERATOR 2 <= , + OPERATOR 3 = , + OPERATOR 4 >= , + OPERATOR 5 > , + FUNCTION 1 ip6_cmp(ip6, ip6); + +CREATE OPERATOR CLASS btree_ip6r_ops DEFAULT FOR TYPE ip6r USING btree AS + OPERATOR 1 < , + OPERATOR 2 <= , + OPERATOR 3 = , + OPERATOR 4 >= , + OPERATOR 5 > , + FUNCTION 1 ip6r_cmp(ip6r, ip6r); + +CREATE OPERATOR CLASS btree_ipaddress_ops DEFAULT FOR TYPE ipaddress USING btree AS + OPERATOR 1 < , + OPERATOR 2 <= , + OPERATOR 3 = , + OPERATOR 4 >= , + OPERATOR 5 > , + FUNCTION 1 ipaddress_cmp(ipaddress, ipaddress); + +CREATE OPERATOR CLASS btree_iprange_ops DEFAULT FOR TYPE iprange USING btree AS + OPERATOR 1 < , + OPERATOR 2 <= , + OPERATOR 3 = , + OPERATOR 4 >= , + OPERATOR 5 > , + FUNCTION 1 iprange_cmp(iprange, iprange); + +-- ---------------------------------------------------------------------- +-- Hash index + +-- the hash index definitions are needed for hashagg, hashjoin, hash-distinct, hashsetop +-- etc. even if no actual hash indexes are used. + +CREATE FUNCTION ip4hash(ip4) RETURNS integer AS 'MODULE_PATHNAME', 'ip4hash' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6hash(ip6) RETURNS integer AS 'MODULE_PATHNAME', 'ip6hash' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddresshash(ipaddress) RETURNS integer AS 'MODULE_PATHNAME', 'ipaddr_hash' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4rhash(ip4r) RETURNS integer AS 'MODULE_PATHNAME', 'ip4rhash' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6rhash(ip6r) RETURNS integer AS 'MODULE_PATHNAME', 'ip6rhash' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprangehash(iprange) RETURNS integer AS 'MODULE_PATHNAME', 'iprange_hash' LANGUAGE C IMMUTABLE STRICT; +COMMENT ON FUNCTION iprangehash(iprange) IS 'deprecated, obsolete'; +CREATE FUNCTION iprange_hash(iprange) RETURNS integer AS 'MODULE_PATHNAME', 'iprange_hash_new' LANGUAGE C IMMUTABLE STRICT; + +CREATE FUNCTION ip4_hash_extended(ip4,bigint) RETURNS bigint AS 'MODULE_PATHNAME', 'ip4_hash_extended' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6_hash_extended(ip6,bigint) RETURNS bigint AS 'MODULE_PATHNAME', 'ip6_hash_extended' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ipaddress_hash_extended(ipaddress,bigint) RETURNS bigint AS 'MODULE_PATHNAME', 'ipaddr_hash_extended' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip4r_hash_extended(ip4r,bigint) RETURNS bigint AS 'MODULE_PATHNAME', 'ip4r_hash_extended' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION ip6r_hash_extended(ip6r,bigint) RETURNS bigint AS 'MODULE_PATHNAME', 'ip6r_hash_extended' LANGUAGE C IMMUTABLE STRICT; +CREATE FUNCTION iprange_hash_extended(iprange,bigint) RETURNS bigint AS 'MODULE_PATHNAME', 'iprange_hash_extended' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR CLASS hash_ip4_ops DEFAULT FOR TYPE ip4 USING hash AS + OPERATOR 1 = , + FUNCTION 1 ip4hash(ip4); + +CREATE OPERATOR CLASS hash_ip4r_ops DEFAULT FOR TYPE ip4r USING hash AS + OPERATOR 1 = , + FUNCTION 1 ip4rhash(ip4r); + +CREATE OPERATOR CLASS hash_ip6_ops DEFAULT FOR TYPE ip6 USING hash AS + OPERATOR 1 = , + FUNCTION 1 ip6hash(ip6); + +CREATE OPERATOR CLASS hash_ip6r_ops DEFAULT FOR TYPE ip6r USING hash AS + OPERATOR 1 = , + FUNCTION 1 ip6rhash(ip6r); + +CREATE OPERATOR CLASS hash_ipaddress_ops DEFAULT FOR TYPE ipaddress USING hash AS + OPERATOR 1 = , + FUNCTION 1 ipaddresshash(ipaddress); + +CREATE OPERATOR CLASS hash_iprange_ops DEFAULT FOR TYPE iprange USING hash AS + OPERATOR 1 = , + FUNCTION 1 iprange_hash(iprange); + +-- ---------------------------------------------------------------------- +-- GiST + +CREATE FUNCTION gip4r_consistent(internal,ip4r,int2,oid,internal) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE FUNCTION gip4r_compress(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE FUNCTION gip4r_decompress(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE FUNCTION gip4r_penalty(internal,internal,internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C STRICT; +CREATE FUNCTION gip4r_picksplit(internal, internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE FUNCTION gip4r_union(internal, internal) RETURNS ip4r AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE FUNCTION gip4r_same(ip4r, ip4r, internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE FUNCTION gip4r_fetch(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; + +CREATE FUNCTION gip6r_consistent(internal,ip6r,int2,oid,internal) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE FUNCTION gip6r_compress(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE FUNCTION gip6r_decompress(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE FUNCTION gip6r_penalty(internal,internal,internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C STRICT; +CREATE FUNCTION gip6r_picksplit(internal, internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE FUNCTION gip6r_union(internal, internal) RETURNS ip6r AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE FUNCTION gip6r_same(ip6r, ip6r, internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE FUNCTION gip6r_fetch(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; + +CREATE FUNCTION gipr_consistent(internal,iprange,int2,oid,internal) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE FUNCTION gipr_compress(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE FUNCTION gipr_decompress(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE FUNCTION gipr_penalty(internal,internal,internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C STRICT; +CREATE FUNCTION gipr_picksplit(internal, internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE FUNCTION gipr_union(internal, internal) RETURNS iprange AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE FUNCTION gipr_same(iprange, iprange, internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE FUNCTION gipr_fetch(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; + +CREATE OPERATOR CLASS gist_ip4r_ops DEFAULT FOR TYPE ip4r USING gist AS + OPERATOR 1 >>= , + OPERATOR 2 <<= , + OPERATOR 3 >> , + OPERATOR 4 << , + OPERATOR 5 && , + OPERATOR 6 = , + FUNCTION 1 gip4r_consistent (internal, ip4r, int2, oid, internal), + FUNCTION 2 gip4r_union (internal, internal), + FUNCTION 3 gip4r_compress (internal), + FUNCTION 4 gip4r_decompress (internal), + FUNCTION 5 gip4r_penalty (internal, internal, internal), + FUNCTION 6 gip4r_picksplit (internal, internal), + FUNCTION 7 gip4r_same (ip4r, ip4r, internal); + +CREATE OPERATOR CLASS gist_ip6r_ops DEFAULT FOR TYPE ip6r USING gist AS + OPERATOR 1 >>= , + OPERATOR 2 <<= , + OPERATOR 3 >> , + OPERATOR 4 << , + OPERATOR 5 && , + OPERATOR 6 = , + FUNCTION 1 gip6r_consistent (internal, ip6r, int2, oid, internal), + FUNCTION 2 gip6r_union (internal, internal), + FUNCTION 3 gip6r_compress (internal), + FUNCTION 4 gip6r_decompress (internal), + FUNCTION 5 gip6r_penalty (internal, internal, internal), + FUNCTION 6 gip6r_picksplit (internal, internal), + FUNCTION 7 gip6r_same (ip6r, ip6r, internal); + +CREATE OPERATOR CLASS gist_iprange_ops DEFAULT FOR TYPE iprange USING gist AS + OPERATOR 1 >>= , + OPERATOR 2 <<= , + OPERATOR 3 >> , + OPERATOR 4 << , + OPERATOR 5 && , + OPERATOR 6 = , + FUNCTION 1 gipr_consistent (internal, iprange, int2, oid, internal), + FUNCTION 2 gipr_union (internal, internal), + FUNCTION 3 gipr_compress (internal), + FUNCTION 4 gipr_decompress (internal), + FUNCTION 5 gipr_penalty (internal, internal, internal), + FUNCTION 6 gipr_picksplit (internal, internal), + FUNCTION 7 gipr_same (iprange, iprange, internal); + +DO $s$ + DECLARE + pg_ver integer := current_setting('server_version_num')::integer; + r record; + BEGIN + IF pg_ver >= 90500 THEN + ALTER OPERATOR FAMILY gist_ip4r_ops USING gist ADD + FUNCTION 9 (ip4r,ip4r) gip4r_fetch (internal); + ALTER OPERATOR FAMILY gist_ip6r_ops USING gist ADD + FUNCTION 9 (ip6r,ip6r) gip6r_fetch (internal); + ALTER OPERATOR FAMILY gist_iprange_ops USING gist ADD + FUNCTION 9 (iprange,iprange) gipr_fetch (internal); + END IF; + IF pg_ver >= 90600 THEN + FOR r IN SELECT oid::regprocedure as fsig + FROM pg_catalog.pg_proc + WHERE (probin = 'MODULE_PATHNAME' + AND prolang = (SELECT oid FROM pg_catalog.pg_language l WHERE l.lanname='c')) + OR (oid in ('family(ip4)'::regprocedure, + 'family(ip6)'::regprocedure, + 'family(ip4r)'::regprocedure, + 'family(ip6r)'::regprocedure)) + LOOP + EXECUTE format('ALTER FUNCTION %s PARALLEL SAFE', r.fsig); + END LOOP; + END IF; + IF pg_ver >= 110000 THEN + FOR r IN SELECT tname + FROM UNNEST(ARRAY['ip4','ip4r', + 'ip6','ip6r', + 'ipaddress','iprange']) u(tname) + LOOP + EXECUTE format('ALTER OPERATOR FAMILY %I USING hash' + ' ADD FUNCTION 2 %I(%I,bigint)', + format('hash_%s_ops', r.tname), + format('%s_hash_extended', r.tname), + r.tname); + END LOOP; + ALTER OPERATOR FAMILY btree_ip4_ops USING btree + ADD FUNCTION 3 (ip4,bigint) in_range(ip4,ip4,bigint,boolean,boolean); + ALTER OPERATOR FAMILY btree_ip4_ops USING btree + ADD FUNCTION 3 (ip4,ip4) in_range(ip4,ip4,ip4,boolean,boolean); + ALTER OPERATOR FAMILY btree_ip6_ops USING btree + ADD FUNCTION 3 (ip6,bigint) in_range(ip6,ip6,bigint,boolean,boolean); + ALTER OPERATOR FAMILY btree_ip6_ops USING btree + ADD FUNCTION 3 (ip6,ip6) in_range(ip6,ip6,ip6,boolean,boolean); + END IF; + END; +$s$; + +-- end diff -Nru ip4r-2.3/scripts/ip4r--unpackaged1--2.0.sql ip4r-2.4/scripts/ip4r--unpackaged1--2.0.sql --- ip4r-2.3/scripts/ip4r--unpackaged1--2.0.sql 1970-01-01 00:00:00.000000000 +0000 +++ ip4r-2.4/scripts/ip4r--unpackaged1--2.0.sql 2018-11-21 06:35:30.000000000 +0000 @@ -0,0 +1,753 @@ +-- ip4r extension + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION ip4r" to load this file. \quit + +-- ---------------------------------------------------------------------- +-- Type definitions + +--CREATE TYPE ip4; + +CREATE OR REPLACE FUNCTION ip4_in(cstring) RETURNS ip4 AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip4_out(ip4) RETURNS cstring AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip4_recv(internal) RETURNS ip4 AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip4_send(ip4) RETURNS bytea AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +/* +CREATE TYPE ip4 ( + INPUT = ip4_in, OUTPUT = ip4_out, + RECEIVE = ip4_recv, SEND = ip4_send, + INTERNALLENGTH = 4, ALIGNMENT = int4, PASSEDBYVALUE +); +*/ + +ALTER EXTENSION ip4r ADD TYPE ip4; + +COMMENT ON TYPE ip4 IS 'IPv4 address ''#.#.#.#'''; + +--CREATE TYPE ip4r; + +CREATE OR REPLACE FUNCTION ip4r_in(cstring) RETURNS ip4r AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip4r_out(ip4r) RETURNS cstring AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip4r_recv(internal) RETURNS ip4r AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip4r_send(ip4r) RETURNS bytea AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +/* +CREATE TYPE ip4r ( + INPUT = ip4r_in, OUTPUT = ip4r_out, + RECEIVE = ip4r_recv, SEND = ip4r_send, + INTERNALLENGTH = 8, ALIGNMENT = int4 +); +*/ + +ALTER EXTENSION ip4r ADD TYPE ip4r; + +COMMENT ON TYPE ip4r IS 'IPv4 range ''#.#.#.#-#.#.#.#'' or ''#.#.#.#/#'' or ''#.#.#.#'''; + +CREATE TYPE ip6; + +CREATE OR REPLACE FUNCTION ip6_in(cstring) RETURNS ip6 AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6_out(ip6) RETURNS cstring AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6_recv(internal) RETURNS ip6 AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6_send(ip6) RETURNS bytea AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +CREATE TYPE ip6 ( + INPUT = ip6_in, OUTPUT = ip6_out, + RECEIVE = ip6_recv, SEND = ip6_send, + INTERNALLENGTH = 16, ALIGNMENT = double +); + +COMMENT ON TYPE ip6 IS 'IPv6 address ''xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx:xxxx'''; + +CREATE TYPE ip6r; + +CREATE OR REPLACE FUNCTION ip6r_in(cstring) RETURNS ip6r AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6r_out(ip6r) RETURNS cstring AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6r_recv(internal) RETURNS ip6r AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6r_send(ip6r) RETURNS bytea AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +CREATE TYPE ip6r ( + INPUT = ip6r_in, OUTPUT = ip6r_out, + RECEIVE = ip6r_recv, SEND = ip6r_send, + INTERNALLENGTH = 32, ALIGNMENT = double +); + +COMMENT ON TYPE ip6r IS 'IPv6 range ''#-#'' or ''#/#'' or ''#'''; + +CREATE TYPE ipaddress; + +CREATE OR REPLACE FUNCTION ipaddress_in(cstring) RETURNS ipaddress AS 'MODULE_PATHNAME','ipaddr_in' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ipaddress_out(ipaddress) RETURNS cstring AS 'MODULE_PATHNAME','ipaddr_out' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ipaddress_recv(internal) RETURNS ipaddress AS 'MODULE_PATHNAME','ipaddr_recv' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ipaddress_send(ipaddress) RETURNS bytea AS 'MODULE_PATHNAME','ipaddr_send' LANGUAGE C IMMUTABLE STRICT; + +CREATE TYPE ipaddress ( + INPUT = ipaddress_in, OUTPUT = ipaddress_out, + RECEIVE = ipaddress_recv, SEND = ipaddress_send, + INTERNALLENGTH = VARIABLE, ALIGNMENT = int4, STORAGE = main +); + +COMMENT ON TYPE ipaddress IS 'IPv4 or IPv6 address'; + +CREATE TYPE iprange; + +CREATE OR REPLACE FUNCTION iprange_in(cstring) RETURNS iprange AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange_out(iprange) RETURNS cstring AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange_recv(internal) RETURNS iprange AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange_send(iprange) RETURNS bytea AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +CREATE TYPE iprange ( + INPUT = iprange_in, OUTPUT = iprange_out, + RECEIVE = iprange_recv, SEND = iprange_send, + INTERNALLENGTH = VARIABLE, ALIGNMENT = int4, STORAGE = main +); + +COMMENT ON TYPE iprange IS 'IPv4 or IPv6 range'; + +-- ---------------------------------------------------------------------- +-- Cast functions (inward) + +CREATE OR REPLACE FUNCTION ip4(bigint) RETURNS ip4 AS 'MODULE_PATHNAME','ip4_cast_from_bigint' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip4(double precision) RETURNS ip4 AS 'MODULE_PATHNAME','ip4_cast_from_double' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip4(numeric) RETURNS ip4 AS 'MODULE_PATHNAME','ip4_cast_from_numeric' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip4(inet) RETURNS ip4 AS 'MODULE_PATHNAME','ip4_cast_from_inet' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip4(text) RETURNS ip4 AS 'MODULE_PATHNAME','ip4_cast_from_text' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip4(ipaddress) RETURNS ip4 AS 'MODULE_PATHNAME','ipaddr_cast_to_ip4' LANGUAGE C IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION ip6(numeric) RETURNS ip6 AS 'MODULE_PATHNAME','ip6_cast_from_numeric' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6(inet) RETURNS ip6 AS 'MODULE_PATHNAME','ip6_cast_from_inet' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6(text) RETURNS ip6 AS 'MODULE_PATHNAME','ip6_cast_from_text' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6(ipaddress) RETURNS ip6 AS 'MODULE_PATHNAME','ipaddr_cast_to_ip6' LANGUAGE C IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION ipaddress(inet) RETURNS ipaddress AS 'MODULE_PATHNAME','ipaddr_cast_from_inet' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ipaddress(ip4) RETURNS ipaddress AS 'MODULE_PATHNAME','ipaddr_cast_from_ip4' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ipaddress(ip6) RETURNS ipaddress AS 'MODULE_PATHNAME','ipaddr_cast_from_ip6' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ipaddress(text) RETURNS ipaddress AS 'MODULE_PATHNAME','ipaddr_cast_from_text' LANGUAGE C IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION ip4r(cidr) RETURNS ip4r AS 'MODULE_PATHNAME','ip4r_cast_from_cidr' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip4r(ip4) RETURNS ip4r AS 'MODULE_PATHNAME','ip4r_cast_from_ip4' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip4r(text) RETURNS ip4r AS 'MODULE_PATHNAME','ip4r_cast_from_text' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip4r(iprange) RETURNS ip4r AS 'MODULE_PATHNAME','iprange_cast_to_ip4r' LANGUAGE C IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION ip6r(cidr) RETURNS ip6r AS 'MODULE_PATHNAME','ip6r_cast_from_cidr' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6r(ip6) RETURNS ip6r AS 'MODULE_PATHNAME','ip6r_cast_from_ip6' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6r(text) RETURNS ip6r AS 'MODULE_PATHNAME','ip6r_cast_from_text' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6r(iprange) RETURNS ip6r AS 'MODULE_PATHNAME','iprange_cast_to_ip6r' LANGUAGE C IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION iprange(cidr) RETURNS iprange AS 'MODULE_PATHNAME','iprange_cast_from_cidr' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange(ip4) RETURNS iprange AS 'MODULE_PATHNAME','iprange_cast_from_ip4' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange(ip6) RETURNS iprange AS 'MODULE_PATHNAME','iprange_cast_from_ip6' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange(ip4r) RETURNS iprange AS 'MODULE_PATHNAME','iprange_cast_from_ip4r' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange(ip6r) RETURNS iprange AS 'MODULE_PATHNAME','iprange_cast_from_ip6r' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange(ipaddress) RETURNS iprange AS 'MODULE_PATHNAME','iprange_cast_from_ipaddr' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange(text) RETURNS iprange AS 'MODULE_PATHNAME','iprange_cast_from_text' LANGUAGE C IMMUTABLE STRICT; + +-- ---------------------------------------------------------------------- +-- Cast functions (outward) + +CREATE OR REPLACE FUNCTION cidr(ip4) RETURNS cidr AS 'MODULE_PATHNAME','ip4_cast_to_cidr' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION cidr(ip4r) RETURNS cidr AS 'MODULE_PATHNAME','ip4r_cast_to_cidr' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION cidr(ip6) RETURNS cidr AS 'MODULE_PATHNAME','ip6_cast_to_cidr' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION cidr(ip6r) RETURNS cidr AS 'MODULE_PATHNAME','ip6r_cast_to_cidr' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION cidr(ipaddress) RETURNS cidr AS 'MODULE_PATHNAME','ipaddr_cast_to_cidr' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION cidr(iprange) RETURNS cidr AS 'MODULE_PATHNAME','iprange_cast_to_cidr' LANGUAGE C IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION text(ip4) RETURNS text AS 'MODULE_PATHNAME','ip4_cast_to_text' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION text(ip4r) RETURNS text AS 'MODULE_PATHNAME','ip4r_cast_to_text' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION text(ip6) RETURNS text AS 'MODULE_PATHNAME','ip6_cast_to_text' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION text(ip6r) RETURNS text AS 'MODULE_PATHNAME','ip6r_cast_to_text' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION text(ipaddress) RETURNS text AS 'MODULE_PATHNAME','ipaddr_cast_to_text' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION text(iprange) RETURNS text AS 'MODULE_PATHNAME','iprange_cast_to_text' LANGUAGE C IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION to_bigint(ip4) RETURNS bigint AS 'MODULE_PATHNAME','ip4_cast_to_bigint' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION to_double(ip4) RETURNS double precision AS 'MODULE_PATHNAME','ip4_cast_to_double' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION to_numeric(ip4) RETURNS numeric AS 'MODULE_PATHNAME','ip4_cast_to_numeric' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION to_numeric(ip6) RETURNS numeric AS 'MODULE_PATHNAME','ip6_cast_to_numeric' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION to_numeric(ipaddress) RETURNS numeric AS 'MODULE_PATHNAME','ipaddr_cast_to_numeric' LANGUAGE C IMMUTABLE STRICT; + +-- ---------------------------------------------------------------------- +-- Cast definitions (outward) + +-- all these are explicit, with the exception of casts from single-address +-- types to "cidr", which we make assignment casts since they are lossless +-- and preserve general semantics. + +ALTER EXTENSION ip4r ADD CAST (ip4 as bigint); +ALTER EXTENSION ip4r ADD CAST (ip4 as double precision); +CREATE CAST (ip4 as numeric) WITH FUNCTION to_numeric(ip4); +ALTER EXTENSION ip4r ADD CAST (ip4 as text); + +ALTER EXTENSION ip4r ADD CAST (ip4 as cidr); + +ALTER EXTENSION ip4r ADD CAST (ip4r as cidr); +ALTER EXTENSION ip4r ADD CAST (ip4r as text); + +CREATE CAST (ip6 as numeric) WITH FUNCTION to_numeric(ip6); +CREATE CAST (ip6 as text) WITH FUNCTION text(ip6); + +CREATE CAST (ip6 as cidr) WITH FUNCTION cidr(ip6) AS ASSIGNMENT; + +CREATE CAST (ip6r as cidr) WITH FUNCTION cidr(ip6r); +CREATE CAST (ip6r as text) WITH FUNCTION text(ip6r); + +CREATE CAST (ipaddress as numeric) WITH FUNCTION to_numeric(ipaddress); +CREATE CAST (ipaddress as text) WITH FUNCTION text(ipaddress); + +CREATE CAST (ipaddress as cidr) WITH FUNCTION cidr(ipaddress) AS ASSIGNMENT; + +CREATE CAST (iprange as cidr) WITH FUNCTION cidr(iprange); +CREATE CAST (iprange as text) WITH FUNCTION text(iprange); + +-- ---------------------------------------------------------------------- +-- Cast definitions (inward) + +-- these are explicit except for casts from inet/cidr types. Even though +-- such casts are lossy for inet, since the masklen isn't preserved, the +-- semantics and common usage are enough to justify an assignment cast. + +ALTER EXTENSION ip4r ADD CAST (text as ip4); +ALTER EXTENSION ip4r ADD CAST (text as ip4r); +CREATE CAST (text as ip6) WITH FUNCTION ip6(text); +CREATE CAST (text as ip6r) WITH FUNCTION ip6r(text); +CREATE CAST (text as ipaddress) WITH FUNCTION ipaddress(text); +CREATE CAST (text as iprange) WITH FUNCTION iprange(text); + +ALTER EXTENSION ip4r ADD CAST (bigint as ip4); +ALTER EXTENSION ip4r ADD CAST (double precision as ip4); + +CREATE CAST (numeric as ip4) WITH FUNCTION ip4(numeric); +CREATE CAST (numeric as ip6) WITH FUNCTION ip6(numeric); + +ALTER EXTENSION ip4r ADD CAST (cidr as ip4r); +CREATE CAST (cidr as ip6r) WITH FUNCTION ip6r(cidr) AS ASSIGNMENT; +CREATE CAST (cidr as iprange) WITH FUNCTION iprange(cidr) AS ASSIGNMENT; + +ALTER EXTENSION ip4r ADD CAST (inet as ip4); +CREATE CAST (inet as ip6) WITH FUNCTION ip6(inet) AS ASSIGNMENT; +CREATE CAST (inet as ipaddress) WITH FUNCTION ipaddress(inet) AS ASSIGNMENT; + +-- ---------------------------------------------------------------------- +-- Cast definitions (cross-type) + +-- the lossless "upward" casts are made implict. + +ALTER EXTENSION ip4r ADD CAST (ip4 as ip4r); +CREATE CAST (ip4 as ipaddress) WITH FUNCTION ipaddress(ip4) AS IMPLICIT; +CREATE CAST (ip4 as iprange) WITH FUNCTION iprange(ip4) AS IMPLICIT; +CREATE CAST (ip4r as iprange) WITH FUNCTION iprange(ip4r) AS IMPLICIT; + +CREATE CAST (ip6 as ip6r) WITH FUNCTION ip6r(ip6) AS IMPLICIT; +CREATE CAST (ip6 as ipaddress) WITH FUNCTION ipaddress(ip6) AS IMPLICIT; +CREATE CAST (ip6 as iprange) WITH FUNCTION iprange(ip6) AS IMPLICIT; +CREATE CAST (ip6r as iprange) WITH FUNCTION iprange(ip6r) AS IMPLICIT; + +CREATE CAST (ipaddress as iprange) WITH FUNCTION iprange(ipaddress) AS IMPLICIT; + +CREATE CAST (ipaddress as ip4) WITH FUNCTION ip4(ipaddress); +CREATE CAST (ipaddress as ip6) WITH FUNCTION ip6(ipaddress); + +CREATE CAST (iprange as ip4r) WITH FUNCTION ip4r(iprange); +CREATE CAST (iprange as ip6r) WITH FUNCTION ip6r(iprange); + +-- ---------------------------------------------------------------------- +-- Constructor functions + +CREATE OR REPLACE FUNCTION ip4r(ip4,ip4) RETURNS ip4r AS 'MODULE_PATHNAME', 'ip4r_from_ip4s' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6r(ip6,ip6) RETURNS ip6r AS 'MODULE_PATHNAME', 'ip6r_from_ip6s' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange(ip4,ip4) RETURNS iprange AS 'MODULE_PATHNAME', 'iprange_from_ip4s' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange(ip6,ip6) RETURNS iprange AS 'MODULE_PATHNAME', 'iprange_from_ip6s' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange(ipaddress,ipaddress) RETURNS iprange AS 'MODULE_PATHNAME', 'iprange_from_ipaddrs' LANGUAGE C IMMUTABLE STRICT; + +-- ---------------------------------------------------------------------- +-- Utility functions (no operator equivalent) + +CREATE OR REPLACE FUNCTION family(ip4) RETURNS integer AS $f$ select 4; $f$ LANGUAGE SQL IMMUTABLE; +CREATE OR REPLACE FUNCTION family(ip4r) RETURNS integer AS $f$ select 4; $f$ LANGUAGE SQL IMMUTABLE; +CREATE OR REPLACE FUNCTION family(ip6) RETURNS integer AS $f$ select 6; $f$ LANGUAGE SQL IMMUTABLE; +CREATE OR REPLACE FUNCTION family(ip6r) RETURNS integer AS $f$ select 6; $f$ LANGUAGE SQL IMMUTABLE; +CREATE OR REPLACE FUNCTION family(ipaddress) RETURNS integer AS 'MODULE_PATHNAME', 'ipaddr_family' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION family(iprange) RETURNS integer AS 'MODULE_PATHNAME', 'iprange_family' LANGUAGE C IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION ip4_netmask(integer) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_netmask' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6_netmask(integer) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_netmask' LANGUAGE C IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION is_cidr(ip4r) RETURNS boolean AS 'MODULE_PATHNAME', 'ip4r_is_cidr' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION is_cidr(ip6r) RETURNS boolean AS 'MODULE_PATHNAME', 'ip6r_is_cidr' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION is_cidr(iprange) RETURNS boolean AS 'MODULE_PATHNAME', 'iprange_is_cidr' LANGUAGE C IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION masklen(ip4r) RETURNS integer AS 'MODULE_PATHNAME','ip4r_prefixlen' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION masklen(ip6r) RETURNS integer AS 'MODULE_PATHNAME','ip6r_prefixlen' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION masklen(iprange) RETURNS integer AS 'MODULE_PATHNAME','iprange_prefixlen' LANGUAGE C IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION lower(ip4r) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4r_lower' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION lower(ip6r) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6r_lower' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION lower(iprange) RETURNS ipaddress AS 'MODULE_PATHNAME', 'iprange_lower' LANGUAGE C IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION upper(ip4r) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4r_upper' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION upper(ip6r) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6r_upper' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION upper(iprange) RETURNS ipaddress AS 'MODULE_PATHNAME', 'iprange_upper' LANGUAGE C IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION ip4_net_lower(ip4,integer) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_net_lower' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6_net_lower(ip6,integer) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_net_lower' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ipaddress_net_lower(ipaddress,integer) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_net_lower' LANGUAGE C IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION ip4_net_upper(ip4,integer) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_net_upper' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6_net_upper(ip6,integer) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_net_upper' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ipaddress_net_upper(ipaddress,integer) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_net_upper' LANGUAGE C IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION ip4r_union(ip4r, ip4r) RETURNS ip4r AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6r_union(ip6r, ip6r) RETURNS ip6r AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange_union(iprange, iprange) RETURNS iprange AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION ip4r_inter(ip4r,ip4r) RETURNS ip4r AS 'MODULE_PATHNAME','ip4r_inter' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6r_inter(ip6r,ip6r) RETURNS ip6r AS 'MODULE_PATHNAME','ip6r_inter' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange_inter(iprange,iprange) RETURNS iprange AS 'MODULE_PATHNAME','iprange_inter' LANGUAGE C IMMUTABLE STRICT; + +-- ---------------------------------------------------------------------- +-- Functions with operator equivalents + +-- it's intended that either the function form or the operator form be used, +-- as desired. + +-- (ip / len) or (ip / mask) + +CREATE OR REPLACE FUNCTION ip4r_net_mask(ip4,ip4) RETURNS ip4r AS 'MODULE_PATHNAME','ip4r_net_mask' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6r_net_mask(ip6,ip6) RETURNS ip6r AS 'MODULE_PATHNAME','ip6r_net_mask' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange_net_mask(ip4,ip4) RETURNS iprange AS 'MODULE_PATHNAME','iprange_net_mask_ip4' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange_net_mask(ip6,ip6) RETURNS iprange AS 'MODULE_PATHNAME','iprange_net_mask_ip6' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange_net_mask(ipaddress,ipaddress) RETURNS iprange AS 'MODULE_PATHNAME','iprange_net_mask' LANGUAGE C IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION ip4r_net_prefix(ip4,integer) RETURNS ip4r AS 'MODULE_PATHNAME','ip4r_net_prefix' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6r_net_prefix(ip6,integer) RETURNS ip6r AS 'MODULE_PATHNAME','ip6r_net_prefix' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange_net_prefix(ip4,integer) RETURNS iprange AS 'MODULE_PATHNAME','iprange_net_prefix_ip4' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange_net_prefix(ip6,integer) RETURNS iprange AS 'MODULE_PATHNAME','iprange_net_prefix_ip6' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange_net_prefix(ipaddress,integer) RETURNS iprange AS 'MODULE_PATHNAME','iprange_net_prefix' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR / ( LEFTARG = ip4, RIGHTARG = ip4, PROCEDURE = ip4r_net_mask ); +CREATE OPERATOR / ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6r_net_mask ); +CREATE OPERATOR / ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = iprange_net_mask ); +CREATE OPERATOR / ( LEFTARG = ip4, RIGHTARG = integer, PROCEDURE = ip4r_net_prefix ); +CREATE OPERATOR / ( LEFTARG = ip6, RIGHTARG = integer, PROCEDURE = ip6r_net_prefix ); +CREATE OPERATOR / ( LEFTARG = ipaddress, RIGHTARG = integer, PROCEDURE = iprange_net_prefix ); + +-- @ ipr (approximate size) or @@ ipr (exact size) + +CREATE OR REPLACE FUNCTION ip4r_size(ip4r) RETURNS double precision AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6r_size(ip6r) RETURNS double precision AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange_size(iprange) RETURNS double precision AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION ip4r_size_exact(ip4r) RETURNS numeric AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6r_size_exact(ip6r) RETURNS numeric AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange_size_exact(iprange) RETURNS numeric AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR @ ( RIGHTARG = ip4r, PROCEDURE = ip4r_size ); +CREATE OPERATOR @ ( RIGHTARG = ip6r, PROCEDURE = ip6r_size ); +CREATE OPERATOR @ ( RIGHTARG = iprange, PROCEDURE = iprange_size ); + +CREATE OPERATOR @@ ( RIGHTARG = ip4r, PROCEDURE = ip4r_size_exact ); +CREATE OPERATOR @@ ( RIGHTARG = ip6r, PROCEDURE = ip6r_size_exact ); +CREATE OPERATOR @@ ( RIGHTARG = iprange, PROCEDURE = iprange_size_exact ); + +-- ---------------------------------------------------------------------- +-- Operators + +-- the function forms of these aren't intended for general use + +-- bitwise ops: and (a & b), or (a | b), xor (a # b), not (~a) + +CREATE OR REPLACE FUNCTION ip4_and(ip4,ip4) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_and' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6_and(ip6,ip6) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_and' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ipaddress_and(ipaddress,ipaddress) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_and' LANGUAGE C IMMUTABLE STRICT; + +ALTER EXTENSION ip4r ADD OPERATOR &(ip4,ip4); +CREATE OPERATOR & ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_and ); +CREATE OPERATOR & ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_and ); + +CREATE OR REPLACE FUNCTION ip4_or(ip4,ip4) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_or' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6_or(ip6,ip6) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_or' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ipaddress_or(ipaddress,ipaddress) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_or' LANGUAGE C IMMUTABLE STRICT; + +ALTER EXTENSION ip4r ADD OPERATOR |(ip4,ip4); +CREATE OPERATOR | ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_or ); +CREATE OPERATOR | ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_or ); + +CREATE OR REPLACE FUNCTION ip4_not(ip4) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_not' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6_not(ip6) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_not' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ipaddress_not(ipaddress) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_not' LANGUAGE C IMMUTABLE STRICT; + +ALTER EXTENSION ip4r ADD OPERATOR ~(NONE,ip4); +CREATE OPERATOR ~ ( RIGHTARG = ip6, PROCEDURE = ip6_not ); +CREATE OPERATOR ~ ( RIGHTARG = ipaddress, PROCEDURE = ipaddress_not ); + +CREATE OR REPLACE FUNCTION ip4_xor(ip4,ip4) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_xor' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6_xor(ip6,ip6) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_xor' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ipaddress_xor(ipaddress,ipaddress) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_xor' LANGUAGE C IMMUTABLE STRICT; + +ALTER EXTENSION ip4r ADD OPERATOR #(ip4,ip4); +CREATE OPERATOR # ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_xor ); +CREATE OPERATOR # ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_xor ); + +-- arithmetic ops: (ip + n), (ip - n), (ip - ip) where n is a numeric or integer type + +CREATE OR REPLACE FUNCTION ip4_plus_bigint(ip4,bigint) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_plus_bigint' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip4_plus_int(ip4,integer) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_plus_int' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip4_plus_numeric(ip4,numeric) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_plus_numeric' LANGUAGE C IMMUTABLE STRICT; + +ALTER EXTENSION ip4r ADD OPERATOR +(ip4,bigint); +ALTER EXTENSION ip4r ADD OPERATOR +(ip4,integer); +CREATE OPERATOR + ( LEFTARG = ip4, RIGHTARG = numeric, PROCEDURE = ip4_plus_numeric ); + +CREATE OR REPLACE FUNCTION ip6_plus_bigint(ip6,bigint) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_plus_bigint' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6_plus_int(ip6,integer) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_plus_int' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6_plus_numeric(ip6,numeric) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_plus_numeric' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR + ( LEFTARG = ip6, RIGHTARG = bigint, PROCEDURE = ip6_plus_bigint ); +CREATE OPERATOR + ( LEFTARG = ip6, RIGHTARG = integer, PROCEDURE = ip6_plus_int ); +CREATE OPERATOR + ( LEFTARG = ip6, RIGHTARG = numeric, PROCEDURE = ip6_plus_numeric ); + +CREATE OR REPLACE FUNCTION ipaddress_plus_bigint(ipaddress,bigint) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_plus_bigint' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ipaddress_plus_int(ipaddress,integer) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_plus_int' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ipaddress_plus_numeric(ipaddress,numeric) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_plus_numeric' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR + ( LEFTARG = ipaddress, RIGHTARG = bigint, PROCEDURE = ipaddress_plus_bigint ); +CREATE OPERATOR + ( LEFTARG = ipaddress, RIGHTARG = integer, PROCEDURE = ipaddress_plus_int ); +CREATE OPERATOR + ( LEFTARG = ipaddress, RIGHTARG = numeric, PROCEDURE = ipaddress_plus_numeric ); + +CREATE OR REPLACE FUNCTION ip4_minus_bigint(ip4,bigint) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_minus_bigint' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip4_minus_int(ip4,integer) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_minus_int' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip4_minus_numeric(ip4,numeric) RETURNS ip4 AS 'MODULE_PATHNAME', 'ip4_minus_numeric' LANGUAGE C IMMUTABLE STRICT; + +ALTER EXTENSION ip4r ADD OPERATOR -(ip4,bigint); +ALTER EXTENSION ip4r ADD OPERATOR -(ip4,integer); +CREATE OPERATOR - ( LEFTARG = ip4, RIGHTARG = numeric, PROCEDURE = ip4_minus_numeric ); + +CREATE OR REPLACE FUNCTION ip6_minus_bigint(ip6,bigint) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_minus_bigint' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6_minus_int(ip6,integer) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_minus_int' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6_minus_numeric(ip6,numeric) RETURNS ip6 AS 'MODULE_PATHNAME', 'ip6_minus_numeric' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR - ( LEFTARG = ip6, RIGHTARG = bigint, PROCEDURE = ip6_minus_bigint ); +CREATE OPERATOR - ( LEFTARG = ip6, RIGHTARG = integer, PROCEDURE = ip6_minus_int ); +CREATE OPERATOR - ( LEFTARG = ip6, RIGHTARG = numeric, PROCEDURE = ip6_minus_numeric ); + +CREATE OR REPLACE FUNCTION ipaddress_minus_bigint(ipaddress,bigint) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_minus_bigint' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ipaddress_minus_int(ipaddress,integer) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_minus_int' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ipaddress_minus_numeric(ipaddress,numeric) RETURNS ipaddress AS 'MODULE_PATHNAME', 'ipaddr_minus_numeric' LANGUAGE C IMMUTABLE STRICT; + +CREATE OPERATOR - ( LEFTARG = ipaddress, RIGHTARG = bigint, PROCEDURE = ipaddress_minus_bigint ); +CREATE OPERATOR - ( LEFTARG = ipaddress, RIGHTARG = integer, PROCEDURE = ipaddress_minus_int ); +CREATE OPERATOR - ( LEFTARG = ipaddress, RIGHTARG = numeric, PROCEDURE = ipaddress_minus_numeric ); + +CREATE OR REPLACE FUNCTION ip4_minus_ip4(ip4,ip4) RETURNS bigint AS 'MODULE_PATHNAME', 'ip4_minus_ip4' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6_minus_ip6(ip6,ip6) RETURNS numeric AS 'MODULE_PATHNAME', 'ip6_minus_ip6' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ipaddress_minus_ipaddress(ipaddress,ipaddress) RETURNS numeric AS 'MODULE_PATHNAME', 'ipaddr_minus_ipaddr' LANGUAGE C IMMUTABLE STRICT; + +ALTER EXTENSION ip4r ADD OPERATOR -(ip4,ip4); +CREATE OPERATOR - ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_minus_ip6 ); +CREATE OPERATOR - ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_minus_ipaddress ); + +-- containment predicates: (a >>= b), (a >> b), (a <<= b), (a << b), (a && b) + +CREATE OR REPLACE FUNCTION ip4r_contained_by(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6r_contained_by(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange_contained_by(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +ALTER EXTENSION ip4r ADD OPERATOR <<=(ip4r,ip4r); +CREATE OPERATOR <<= ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_contained_by, COMMUTATOR = '>>=', RESTRICT = contsel, JOIN = contjoinsel ); +CREATE OPERATOR <<= ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_contained_by, COMMUTATOR = '>>=', RESTRICT = contsel, JOIN = contjoinsel ); + +CREATE OR REPLACE FUNCTION ip4r_contained_by_strict(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6r_contained_by_strict(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange_contained_by_strict(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +ALTER EXTENSION ip4r ADD OPERATOR <<(ip4r,ip4r); +CREATE OPERATOR << ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_contained_by_strict, COMMUTATOR = '>>', RESTRICT = contsel, JOIN = contjoinsel ); +CREATE OPERATOR << ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_contained_by_strict, COMMUTATOR = '>>', RESTRICT = contsel, JOIN = contjoinsel ); + +CREATE OR REPLACE FUNCTION ip4r_contains(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6r_contains(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange_contains(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +ALTER EXTENSION ip4r ADD OPERATOR >>=(ip4r,ip4r); +CREATE OPERATOR >>= ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_contains, COMMUTATOR = '<<=', RESTRICT = contsel, JOIN = contjoinsel ); +CREATE OPERATOR >>= ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_contains, COMMUTATOR = '<<=', RESTRICT = contsel, JOIN = contjoinsel ); + +CREATE OR REPLACE FUNCTION ip4r_contains_strict(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6r_contains_strict(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange_contains_strict(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +ALTER EXTENSION ip4r ADD OPERATOR >>(ip4r,ip4r); +CREATE OPERATOR >> ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_contains_strict, COMMUTATOR = '<<', RESTRICT = contsel, JOIN = contjoinsel ); +CREATE OPERATOR >> ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_contains_strict, COMMUTATOR = '<<', RESTRICT = contsel, JOIN = contjoinsel ); + +CREATE OR REPLACE FUNCTION ip4r_overlaps(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6r_overlaps(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange_overlaps(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +ALTER EXTENSION ip4r ADD OPERATOR &&(ip4r,ip4r); +CREATE OPERATOR && ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_overlaps, COMMUTATOR = '&&', RESTRICT = areasel, JOIN = areajoinsel ); +CREATE OPERATOR && ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_overlaps, COMMUTATOR = '&&', RESTRICT = areasel, JOIN = areajoinsel ); + +-- cross-type containment +-- no operators for these since they seem to do more harm than good. These cases +-- are handled by implicit casts instead. + +CREATE OR REPLACE FUNCTION ip4_contained_by(ip4,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip4_contained_by(ip4,iprange) RETURNS bool AS 'MODULE_PATHNAME','iprange_ip4_contained_by' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6_contained_by(ip6,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6_contained_by(ip6,iprange) RETURNS bool AS 'MODULE_PATHNAME','iprange_ip6_contained_by' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ipaddress_contained_by(ipaddress,iprange) RETURNS bool AS 'MODULE_PATHNAME','iprange_ip_contained_by' LANGUAGE C IMMUTABLE STRICT; + +CREATE OR REPLACE FUNCTION ip4_contains(ip4r,ip4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6_contains(ip6r,ip6) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip4_contains(iprange,ip4) RETURNS bool AS 'MODULE_PATHNAME','iprange_contains_ip4' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6_contains(iprange,ip6) RETURNS bool AS 'MODULE_PATHNAME','iprange_contains_ip6' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ipaddress_contains(iprange,ipaddress) RETURNS bool AS 'MODULE_PATHNAME','iprange_contains_ip' LANGUAGE C IMMUTABLE STRICT; + +-- btree (strict weak) ordering operators +-- meaning of < > for ip4 and ip6 is obvious. +-- for ipaddress, all ip4 addresses are less than all ip6 addresses +-- for ip4r/ip6r, the order is lexicographic on (lower,upper) +-- for iprange, the universal range is lowest, then all ip4 ranges, then ip6 + +CREATE OR REPLACE FUNCTION ip4_eq(ip4,ip4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip4r_eq(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6_eq(ip6,ip6) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6r_eq(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ipaddress_eq(ipaddress,ipaddress) RETURNS bool AS 'MODULE_PATHNAME','ipaddr_eq' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange_eq(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +ALTER EXTENSION ip4r ADD OPERATOR =(ip4,ip4); +ALTER EXTENSION ip4r ADD OPERATOR =(ip4r,ip4r); +CREATE OPERATOR = ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_eq, COMMUTATOR = '=', NEGATOR = '<>', RESTRICT = eqsel, JOIN = eqjoinsel, SORT1 = '<', SORT2 = '<', HASHES ); +CREATE OPERATOR = ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_eq, COMMUTATOR = '=', NEGATOR = '<>', RESTRICT = eqsel, JOIN = eqjoinsel, SORT1 = '<', SORT2 = '<', HASHES ); +CREATE OPERATOR = ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_eq, COMMUTATOR = '=', NEGATOR = '<>', RESTRICT = eqsel, JOIN = eqjoinsel, SORT1 = '<', SORT2 = '<', HASHES ); +CREATE OPERATOR = ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_eq, COMMUTATOR = '=', NEGATOR = '<>', RESTRICT = eqsel, JOIN = eqjoinsel, SORT1 = '<', SORT2 = '<', HASHES ); + +CREATE OR REPLACE FUNCTION ip4_ge(ip4,ip4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip4r_ge(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6_ge(ip6,ip6) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6r_ge(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ipaddress_ge(ipaddress,ipaddress) RETURNS bool AS 'MODULE_PATHNAME','ipaddr_ge' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange_ge(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +ALTER EXTENSION ip4r ADD OPERATOR >=(ip4,ip4); +ALTER EXTENSION ip4r ADD OPERATOR >=(ip4r,ip4r); +CREATE OPERATOR >= ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_ge, COMMUTATOR = '<=', NEGATOR = '<', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); +CREATE OPERATOR >= ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_ge, COMMUTATOR = '<=', NEGATOR = '<', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); +CREATE OPERATOR >= ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_ge, COMMUTATOR = '<=', NEGATOR = '<', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); +CREATE OPERATOR >= ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_ge, COMMUTATOR = '<=', NEGATOR = '<', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); + +CREATE OR REPLACE FUNCTION ip4_gt(ip4,ip4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip4r_gt(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6_gt(ip6,ip6) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6r_gt(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ipaddress_gt(ipaddress,ipaddress) RETURNS bool AS 'MODULE_PATHNAME','ipaddr_gt' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange_gt(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +ALTER EXTENSION ip4r ADD OPERATOR >(ip4,ip4); +ALTER EXTENSION ip4r ADD OPERATOR >(ip4r,ip4r); +CREATE OPERATOR > ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_gt, COMMUTATOR = '<', NEGATOR = '<=', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); +CREATE OPERATOR > ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_gt, COMMUTATOR = '<', NEGATOR = '<=', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); +CREATE OPERATOR > ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_gt, COMMUTATOR = '<', NEGATOR = '<=', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); +CREATE OPERATOR > ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_gt, COMMUTATOR = '<', NEGATOR = '<=', RESTRICT = scalargtsel, JOIN = scalargtjoinsel ); + +CREATE OR REPLACE FUNCTION ip4_le(ip4,ip4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip4r_le(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6_le(ip6,ip6) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6r_le(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ipaddress_le(ipaddress,ipaddress) RETURNS bool AS 'MODULE_PATHNAME','ipaddr_le' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange_le(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +ALTER EXTENSION ip4r ADD OPERATOR <=(ip4,ip4); +ALTER EXTENSION ip4r ADD OPERATOR <=(ip4r,ip4r); +CREATE OPERATOR <= ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_le, COMMUTATOR = '>=', NEGATOR = '>', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); +CREATE OPERATOR <= ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_le, COMMUTATOR = '>=', NEGATOR = '>', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); +CREATE OPERATOR <= ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_le, COMMUTATOR = '>=', NEGATOR = '>', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); +CREATE OPERATOR <= ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_le, COMMUTATOR = '>=', NEGATOR = '>', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); + +CREATE OR REPLACE FUNCTION ip4_lt(ip4,ip4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip4r_lt(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6_lt(ip6,ip6) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6r_lt(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ipaddress_lt(ipaddress,ipaddress) RETURNS bool AS 'MODULE_PATHNAME','ipaddr_lt' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange_lt(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +ALTER EXTENSION ip4r ADD OPERATOR <(ip4,ip4); +ALTER EXTENSION ip4r ADD OPERATOR <(ip4r,ip4r); +CREATE OPERATOR < ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_lt, COMMUTATOR = '>', NEGATOR = '>=', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); +CREATE OPERATOR < ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_lt, COMMUTATOR = '>', NEGATOR = '>=', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); +CREATE OPERATOR < ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_lt, COMMUTATOR = '>', NEGATOR = '>=', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); +CREATE OPERATOR < ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_lt, COMMUTATOR = '>', NEGATOR = '>=', RESTRICT = scalarltsel, JOIN = scalarltjoinsel ); + +CREATE OR REPLACE FUNCTION ip4_neq(ip4,ip4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip4r_neq(ip4r,ip4r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6_neq(ip6,ip6) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6r_neq(ip6r,ip6r) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ipaddress_neq(ipaddress,ipaddress) RETURNS bool AS 'MODULE_PATHNAME','ipaddr_neq' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange_neq(iprange,iprange) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +ALTER EXTENSION ip4r ADD OPERATOR <>(ip4,ip4); +ALTER EXTENSION ip4r ADD OPERATOR <>(ip4r,ip4r); +CREATE OPERATOR <> ( LEFTARG = ip6, RIGHTARG = ip6, PROCEDURE = ip6_neq, COMMUTATOR = '<>', NEGATOR = '=', RESTRICT = neqsel, JOIN = neqjoinsel ); +CREATE OPERATOR <> ( LEFTARG = ip6r, RIGHTARG = ip6r, PROCEDURE = ip6r_neq, COMMUTATOR = '<>', NEGATOR = '=', RESTRICT = neqsel, JOIN = neqjoinsel ); +CREATE OPERATOR <> ( LEFTARG = ipaddress, RIGHTARG = ipaddress, PROCEDURE = ipaddress_neq, COMMUTATOR = '<>', NEGATOR = '=', RESTRICT = neqsel, JOIN = neqjoinsel ); +CREATE OPERATOR <> ( LEFTARG = iprange, RIGHTARG = iprange, PROCEDURE = iprange_neq, COMMUTATOR = '<>', NEGATOR = '=', RESTRICT = neqsel, JOIN = neqjoinsel ); + +-- ---------------------------------------------------------------------- +-- Btree index + +CREATE OR REPLACE FUNCTION ip4_cmp(ip4,ip4) RETURNS integer AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip4r_cmp(ip4r,ip4r) RETURNS integer AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6_cmp(ip6,ip6) RETURNS integer AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6r_cmp(ip6r,ip6r) RETURNS integer AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ipaddress_cmp(ipaddress,ipaddress) RETURNS integer AS 'MODULE_PATHNAME','ipaddr_cmp' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprange_cmp(iprange,iprange) RETURNS integer AS 'MODULE_PATHNAME' LANGUAGE C IMMUTABLE STRICT; + +ALTER EXTENSION ip4r ADD OPERATOR CLASS btree_ip4_ops USING btree; +ALTER EXTENSION ip4r ADD OPERATOR CLASS btree_ip4r_ops USING btree; + +CREATE OPERATOR CLASS btree_ip6_ops DEFAULT FOR TYPE ip6 USING btree AS + OPERATOR 1 < , + OPERATOR 2 <= , + OPERATOR 3 = , + OPERATOR 4 >= , + OPERATOR 5 > , + FUNCTION 1 ip6_cmp(ip6, ip6); + +CREATE OPERATOR CLASS btree_ip6r_ops DEFAULT FOR TYPE ip6r USING btree AS + OPERATOR 1 < , + OPERATOR 2 <= , + OPERATOR 3 = , + OPERATOR 4 >= , + OPERATOR 5 > , + FUNCTION 1 ip6r_cmp(ip6r, ip6r); + +CREATE OPERATOR CLASS btree_ipaddress_ops DEFAULT FOR TYPE ipaddress USING btree AS + OPERATOR 1 < , + OPERATOR 2 <= , + OPERATOR 3 = , + OPERATOR 4 >= , + OPERATOR 5 > , + FUNCTION 1 ipaddress_cmp(ipaddress, ipaddress); + +CREATE OPERATOR CLASS btree_iprange_ops DEFAULT FOR TYPE iprange USING btree AS + OPERATOR 1 < , + OPERATOR 2 <= , + OPERATOR 3 = , + OPERATOR 4 >= , + OPERATOR 5 > , + FUNCTION 1 iprange_cmp(iprange, iprange); + +-- ---------------------------------------------------------------------- +-- Hash index + +-- the hash index definitions are needed for hashagg, hashjoin, hash-distinct, hashsetop +-- etc. even if no actual hash indexes are used. + +CREATE OR REPLACE FUNCTION ip4hash(ip4) RETURNS integer AS 'MODULE_PATHNAME', 'ip4hash' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6hash(ip6) RETURNS integer AS 'MODULE_PATHNAME', 'ip6hash' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ipaddresshash(ipaddress) RETURNS integer AS 'MODULE_PATHNAME', 'ipaddr_hash' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip4rhash(ip4r) RETURNS integer AS 'MODULE_PATHNAME', 'ip4rhash' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION ip6rhash(ip6r) RETURNS integer AS 'MODULE_PATHNAME', 'ip6rhash' LANGUAGE C IMMUTABLE STRICT; +CREATE OR REPLACE FUNCTION iprangehash(iprange) RETURNS integer AS 'MODULE_PATHNAME', 'iprange_hash' LANGUAGE C IMMUTABLE STRICT; + +ALTER EXTENSION ip4r ADD OPERATOR CLASS hash_ip4_ops USING hash; +ALTER EXTENSION ip4r ADD OPERATOR CLASS hash_ip4r_ops USING hash; + +CREATE OPERATOR CLASS hash_ip6_ops DEFAULT FOR TYPE ip6 USING hash AS + OPERATOR 1 = , + FUNCTION 1 ip6hash(ip6); + +CREATE OPERATOR CLASS hash_ip6r_ops DEFAULT FOR TYPE ip6r USING hash AS + OPERATOR 1 = , + FUNCTION 1 ip6rhash(ip6r); + +CREATE OPERATOR CLASS hash_ipaddress_ops DEFAULT FOR TYPE ipaddress USING hash AS + OPERATOR 1 = , + FUNCTION 1 ipaddresshash(ipaddress); + +CREATE OPERATOR CLASS hash_iprange_ops DEFAULT FOR TYPE iprange USING hash AS + OPERATOR 1 = , + FUNCTION 1 iprangehash(iprange); + +-- ---------------------------------------------------------------------- +-- GiST + +-- these type declarations are actually wrong for 8.4+ (which added +-- more args to consistent) but we ignore that because the access +-- method code doesn't actually look at the function declaration, and +-- the differences are handled in the C code. Having the SQL +-- definition changing is just too much of a pain. + +CREATE OR REPLACE FUNCTION gip4r_consistent(internal,ip4r,int4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE OR REPLACE FUNCTION gip4r_compress(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE OR REPLACE FUNCTION gip4r_decompress(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE OR REPLACE FUNCTION gip4r_penalty(internal,internal,internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C STRICT; +CREATE OR REPLACE FUNCTION gip4r_picksplit(internal, internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE OR REPLACE FUNCTION gip4r_union(internal, internal) RETURNS ip4r AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE OR REPLACE FUNCTION gip4r_same(ip4r, ip4r, internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; + +CREATE OR REPLACE FUNCTION gip6r_consistent(internal,ip6r,int4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE OR REPLACE FUNCTION gip6r_compress(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE OR REPLACE FUNCTION gip6r_decompress(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE OR REPLACE FUNCTION gip6r_penalty(internal,internal,internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C STRICT; +CREATE OR REPLACE FUNCTION gip6r_picksplit(internal, internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE OR REPLACE FUNCTION gip6r_union(internal, internal) RETURNS ip6r AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE OR REPLACE FUNCTION gip6r_same(ip6r, ip6r, internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; + +CREATE OR REPLACE FUNCTION gipr_consistent(internal,iprange,int4) RETURNS bool AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE OR REPLACE FUNCTION gipr_compress(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE OR REPLACE FUNCTION gipr_decompress(internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE OR REPLACE FUNCTION gipr_penalty(internal,internal,internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C STRICT; +CREATE OR REPLACE FUNCTION gipr_picksplit(internal, internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE OR REPLACE FUNCTION gipr_union(internal, internal) RETURNS iprange AS 'MODULE_PATHNAME' LANGUAGE C; +CREATE OR REPLACE FUNCTION gipr_same(iprange, iprange, internal) RETURNS internal AS 'MODULE_PATHNAME' LANGUAGE C; + +ALTER EXTENSION ip4r ADD OPERATOR CLASS gist_ip4r_ops USING gist; + +CREATE OPERATOR CLASS gist_ip6r_ops DEFAULT FOR TYPE ip6r USING gist AS + OPERATOR 1 >>= , + OPERATOR 2 <<= , + OPERATOR 3 >> , + OPERATOR 4 << , + OPERATOR 5 && , + OPERATOR 6 = , + FUNCTION 1 gip6r_consistent (internal, ip6r, int4), + FUNCTION 2 gip6r_union (internal, internal), + FUNCTION 3 gip6r_compress (internal), + FUNCTION 4 gip6r_decompress (internal), + FUNCTION 5 gip6r_penalty (internal, internal, internal), + FUNCTION 6 gip6r_picksplit (internal, internal), + FUNCTION 7 gip6r_same (ip6r, ip6r, internal); + +CREATE OPERATOR CLASS gist_iprange_ops DEFAULT FOR TYPE iprange USING gist AS + OPERATOR 1 >>= , + OPERATOR 2 <<= , + OPERATOR 3 >> , + OPERATOR 4 << , + OPERATOR 5 && , + OPERATOR 6 = , + FUNCTION 1 gipr_consistent (internal, iprange, int4), + FUNCTION 2 gipr_union (internal, internal), + FUNCTION 3 gipr_compress (internal), + FUNCTION 4 gipr_decompress (internal), + FUNCTION 5 gipr_penalty (internal, internal, internal), + FUNCTION 6 gipr_picksplit (internal, internal), + FUNCTION 7 gipr_same (iprange, iprange, internal); + +-- cleanup old cruft + +DROP OPERATOR IF EXISTS @(ip4r,ip4r); +DROP OPERATOR IF EXISTS ~(ip4r,ip4r); + +DROP OPERATOR IF EXISTS &<<(ip4r,ip4r); +DROP OPERATOR IF EXISTS &>>(ip4r,ip4r); +DROP OPERATOR IF EXISTS <<<(ip4r,ip4r); +DROP OPERATOR IF EXISTS >>>(ip4r,ip4r); + +DROP FUNCTION IF EXISTS ip4r_left_of(ip4r,ip4r); +DROP FUNCTION IF EXISTS ip4r_left_overlap(ip4r,ip4r); +DROP FUNCTION IF EXISTS ip4r_right_of(ip4r,ip4r); +DROP FUNCTION IF EXISTS ip4r_right_overlap(ip4r,ip4r); + +-- end diff -Nru ip4r-2.3/scripts/ip4r--unpackaged2.0--2.0.sql ip4r-2.4/scripts/ip4r--unpackaged2.0--2.0.sql --- ip4r-2.3/scripts/ip4r--unpackaged2.0--2.0.sql 1970-01-01 00:00:00.000000000 +0000 +++ ip4r-2.4/scripts/ip4r--unpackaged2.0--2.0.sql 2018-11-21 06:35:30.000000000 +0000 @@ -0,0 +1,420 @@ +-- ip4r extension + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION ip4r" to load this file. \quit + +ALTER EXTENSION ip4r ADD FUNCTION ip4_in(cstring); +ALTER EXTENSION ip4r ADD FUNCTION ip4_out(ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip4_recv(internal); +ALTER EXTENSION ip4r ADD FUNCTION ip4_send(ip4); +ALTER EXTENSION ip4r ADD TYPE ip4; +ALTER EXTENSION ip4r ADD FUNCTION ip4r_in(cstring); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_out(ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_recv(internal); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_send(ip4r); +ALTER EXTENSION ip4r ADD TYPE ip4r; +ALTER EXTENSION ip4r ADD FUNCTION ip6_in(cstring); +ALTER EXTENSION ip4r ADD FUNCTION ip6_out(ip6); +ALTER EXTENSION ip4r ADD FUNCTION ip6_recv(internal); +ALTER EXTENSION ip4r ADD FUNCTION ip6_send(ip6); +ALTER EXTENSION ip4r ADD TYPE ip6; +ALTER EXTENSION ip4r ADD FUNCTION ip6r_in(cstring); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_out(ip6r); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_recv(internal); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_send(ip6r); +ALTER EXTENSION ip4r ADD TYPE ip6r; +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_in(cstring); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_out(ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_recv(internal); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_send(ipaddress); +ALTER EXTENSION ip4r ADD TYPE ipaddress; +ALTER EXTENSION ip4r ADD FUNCTION iprange_in(cstring); +ALTER EXTENSION ip4r ADD FUNCTION iprange_out(iprange); +ALTER EXTENSION ip4r ADD FUNCTION iprange_recv(internal); +ALTER EXTENSION ip4r ADD FUNCTION iprange_send(iprange); +ALTER EXTENSION ip4r ADD TYPE iprange; +ALTER EXTENSION ip4r ADD FUNCTION ip4(bigint); +ALTER EXTENSION ip4r ADD FUNCTION ip4(double precision); +ALTER EXTENSION ip4r ADD FUNCTION ip4(numeric); +ALTER EXTENSION ip4r ADD FUNCTION ip4(inet); +ALTER EXTENSION ip4r ADD FUNCTION ip4(text); +ALTER EXTENSION ip4r ADD FUNCTION ip4(ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION ip6(numeric); +ALTER EXTENSION ip4r ADD FUNCTION ip6(inet); +ALTER EXTENSION ip4r ADD FUNCTION ip6(text); +ALTER EXTENSION ip4r ADD FUNCTION ip6(ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress(inet); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress(ip4); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress(ip6); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress(text); +ALTER EXTENSION ip4r ADD FUNCTION ip4r(cidr); +ALTER EXTENSION ip4r ADD FUNCTION ip4r(ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip4r(text); +ALTER EXTENSION ip4r ADD FUNCTION ip4r(iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip6r(cidr); +ALTER EXTENSION ip4r ADD FUNCTION ip6r(ip6); +ALTER EXTENSION ip4r ADD FUNCTION ip6r(text); +ALTER EXTENSION ip4r ADD FUNCTION ip6r(iprange); +ALTER EXTENSION ip4r ADD FUNCTION iprange(cidr); +ALTER EXTENSION ip4r ADD FUNCTION iprange(ip4); +ALTER EXTENSION ip4r ADD FUNCTION iprange(ip6); +ALTER EXTENSION ip4r ADD FUNCTION iprange(ip4r); +ALTER EXTENSION ip4r ADD FUNCTION iprange(ip6r); +ALTER EXTENSION ip4r ADD FUNCTION iprange(ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION iprange(text); +ALTER EXTENSION ip4r ADD FUNCTION cidr(ip4); +ALTER EXTENSION ip4r ADD FUNCTION cidr(ip4r); +ALTER EXTENSION ip4r ADD FUNCTION cidr(ip6); +ALTER EXTENSION ip4r ADD FUNCTION cidr(ip6r); +ALTER EXTENSION ip4r ADD FUNCTION cidr(ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION cidr(iprange); +ALTER EXTENSION ip4r ADD FUNCTION text(ip4); +ALTER EXTENSION ip4r ADD FUNCTION text(ip4r); +ALTER EXTENSION ip4r ADD FUNCTION text(ip6); +ALTER EXTENSION ip4r ADD FUNCTION text(ip6r); +ALTER EXTENSION ip4r ADD FUNCTION text(ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION text(iprange); +ALTER EXTENSION ip4r ADD FUNCTION to_bigint(ip4); +ALTER EXTENSION ip4r ADD FUNCTION to_double(ip4); +ALTER EXTENSION ip4r ADD FUNCTION to_numeric(ip4); +ALTER EXTENSION ip4r ADD FUNCTION to_numeric(ip6); +ALTER EXTENSION ip4r ADD FUNCTION to_numeric(ipaddress); +ALTER EXTENSION ip4r ADD CAST (ip4 as bigint); +ALTER EXTENSION ip4r ADD CAST (ip4 as double precision); +ALTER EXTENSION ip4r ADD CAST (ip4 as numeric); +ALTER EXTENSION ip4r ADD CAST (ip4 as text); +ALTER EXTENSION ip4r ADD CAST (ip4 as cidr); +ALTER EXTENSION ip4r ADD CAST (ip4r as cidr); +ALTER EXTENSION ip4r ADD CAST (ip4r as text); +ALTER EXTENSION ip4r ADD CAST (ip6 as numeric); +ALTER EXTENSION ip4r ADD CAST (ip6 as text); +ALTER EXTENSION ip4r ADD CAST (ip6 as cidr); +ALTER EXTENSION ip4r ADD CAST (ip6r as cidr); +ALTER EXTENSION ip4r ADD CAST (ip6r as text); +ALTER EXTENSION ip4r ADD CAST (ipaddress as numeric); +ALTER EXTENSION ip4r ADD CAST (ipaddress as text); +ALTER EXTENSION ip4r ADD CAST (ipaddress as cidr); +ALTER EXTENSION ip4r ADD CAST (iprange as cidr); +ALTER EXTENSION ip4r ADD CAST (iprange as text); +ALTER EXTENSION ip4r ADD CAST (text as ip4); +ALTER EXTENSION ip4r ADD CAST (text as ip4r); +ALTER EXTENSION ip4r ADD CAST (text as ip6); +ALTER EXTENSION ip4r ADD CAST (text as ip6r); +ALTER EXTENSION ip4r ADD CAST (text as ipaddress); +ALTER EXTENSION ip4r ADD CAST (text as iprange); +ALTER EXTENSION ip4r ADD CAST (bigint as ip4); +ALTER EXTENSION ip4r ADD CAST (double precision as ip4); +ALTER EXTENSION ip4r ADD CAST (numeric as ip4); +ALTER EXTENSION ip4r ADD CAST (numeric as ip6); +ALTER EXTENSION ip4r ADD CAST (cidr as ip4r); +ALTER EXTENSION ip4r ADD CAST (cidr as ip6r); +ALTER EXTENSION ip4r ADD CAST (cidr as iprange); +ALTER EXTENSION ip4r ADD CAST (inet as ip4); +ALTER EXTENSION ip4r ADD CAST (inet as ip6); +ALTER EXTENSION ip4r ADD CAST (inet as ipaddress); +ALTER EXTENSION ip4r ADD CAST (ip4 as ip4r); +ALTER EXTENSION ip4r ADD CAST (ip4 as ipaddress); +ALTER EXTENSION ip4r ADD CAST (ip4 as iprange); +ALTER EXTENSION ip4r ADD CAST (ip4r as iprange); +ALTER EXTENSION ip4r ADD CAST (ip6 as ip6r); +ALTER EXTENSION ip4r ADD CAST (ip6 as ipaddress); +ALTER EXTENSION ip4r ADD CAST (ip6 as iprange); +ALTER EXTENSION ip4r ADD CAST (ip6r as iprange); +ALTER EXTENSION ip4r ADD CAST (ipaddress as iprange); +ALTER EXTENSION ip4r ADD CAST (ipaddress as ip4); +ALTER EXTENSION ip4r ADD CAST (ipaddress as ip6); +ALTER EXTENSION ip4r ADD CAST (iprange as ip4r); +ALTER EXTENSION ip4r ADD CAST (iprange as ip6r); +ALTER EXTENSION ip4r ADD FUNCTION ip4r(ip4,ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip6r(ip6,ip6); +ALTER EXTENSION ip4r ADD FUNCTION iprange(ip4,ip4); +ALTER EXTENSION ip4r ADD FUNCTION iprange(ip6,ip6); +ALTER EXTENSION ip4r ADD FUNCTION iprange(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION family(ip4); +ALTER EXTENSION ip4r ADD FUNCTION family(ip4r); +ALTER EXTENSION ip4r ADD FUNCTION family(ip6); +ALTER EXTENSION ip4r ADD FUNCTION family(ip6r); +ALTER EXTENSION ip4r ADD FUNCTION family(ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION family(iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4_netmask(integer); +ALTER EXTENSION ip4r ADD FUNCTION ip6_netmask(integer); +ALTER EXTENSION ip4r ADD FUNCTION is_cidr(ip4r); +ALTER EXTENSION ip4r ADD FUNCTION is_cidr(ip6r); +ALTER EXTENSION ip4r ADD FUNCTION is_cidr(iprange); +ALTER EXTENSION ip4r ADD FUNCTION masklen(ip4r); +ALTER EXTENSION ip4r ADD FUNCTION masklen(ip6r); +ALTER EXTENSION ip4r ADD FUNCTION masklen(iprange); +ALTER EXTENSION ip4r ADD FUNCTION lower(ip4r); +ALTER EXTENSION ip4r ADD FUNCTION lower(ip6r); +ALTER EXTENSION ip4r ADD FUNCTION lower(iprange); +ALTER EXTENSION ip4r ADD FUNCTION upper(ip4r); +ALTER EXTENSION ip4r ADD FUNCTION upper(ip6r); +ALTER EXTENSION ip4r ADD FUNCTION upper(iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4_net_lower(ip4,integer); +ALTER EXTENSION ip4r ADD FUNCTION ip6_net_lower(ip6,integer); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_net_lower(ipaddress,integer); +ALTER EXTENSION ip4r ADD FUNCTION ip4_net_upper(ip4,integer); +ALTER EXTENSION ip4r ADD FUNCTION ip6_net_upper(ip6,integer); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_net_upper(ipaddress,integer); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_union(ip4r, ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_union(ip6r, ip6r); +ALTER EXTENSION ip4r ADD FUNCTION iprange_union(iprange, iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_inter(ip4r,ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_inter(ip6r,ip6r); +ALTER EXTENSION ip4r ADD FUNCTION iprange_inter(iprange,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_net_mask(ip4,ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_net_mask(ip6,ip6); +ALTER EXTENSION ip4r ADD FUNCTION iprange_net_mask(ip4,ip4); +ALTER EXTENSION ip4r ADD FUNCTION iprange_net_mask(ip6,ip6); +ALTER EXTENSION ip4r ADD FUNCTION iprange_net_mask(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_net_prefix(ip4,integer); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_net_prefix(ip6,integer); +ALTER EXTENSION ip4r ADD FUNCTION iprange_net_prefix(ip4,integer); +ALTER EXTENSION ip4r ADD FUNCTION iprange_net_prefix(ip6,integer); +ALTER EXTENSION ip4r ADD FUNCTION iprange_net_prefix(ipaddress,integer); +ALTER EXTENSION ip4r ADD OPERATOR /(ip4,ip4); +ALTER EXTENSION ip4r ADD OPERATOR /(ip6,ip6); +ALTER EXTENSION ip4r ADD OPERATOR /(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD OPERATOR /(ip4,integer); +ALTER EXTENSION ip4r ADD OPERATOR /(ip6,integer); +ALTER EXTENSION ip4r ADD OPERATOR /(ipaddress,integer); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_size(ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_size(ip6r); +ALTER EXTENSION ip4r ADD FUNCTION iprange_size(iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_size_exact(ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_size_exact(ip6r); +ALTER EXTENSION ip4r ADD FUNCTION iprange_size_exact(iprange); +ALTER EXTENSION ip4r ADD OPERATOR @(NONE,ip4r); +ALTER EXTENSION ip4r ADD OPERATOR @(NONE,ip6r); +ALTER EXTENSION ip4r ADD OPERATOR @(NONE,iprange); +ALTER EXTENSION ip4r ADD OPERATOR @@(NONE,ip4r); +ALTER EXTENSION ip4r ADD OPERATOR @@(NONE,ip6r); +ALTER EXTENSION ip4r ADD OPERATOR @@(NONE,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4_and(ip4,ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip6_and(ip6,ip6); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_and(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD OPERATOR &(ip4,ip4); +ALTER EXTENSION ip4r ADD OPERATOR &(ip6,ip6); +ALTER EXTENSION ip4r ADD OPERATOR &(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION ip4_or(ip4,ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip6_or(ip6,ip6); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_or(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD OPERATOR |(ip4,ip4); +ALTER EXTENSION ip4r ADD OPERATOR |(ip6,ip6); +ALTER EXTENSION ip4r ADD OPERATOR |(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION ip4_not(ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip6_not(ip6); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_not(ipaddress); +ALTER EXTENSION ip4r ADD OPERATOR ~(NONE,ip4); +ALTER EXTENSION ip4r ADD OPERATOR ~(NONE,ip6); +ALTER EXTENSION ip4r ADD OPERATOR ~(NONE,ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION ip4_xor(ip4,ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip6_xor(ip6,ip6); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_xor(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD OPERATOR #(ip4,ip4); +ALTER EXTENSION ip4r ADD OPERATOR #(ip6,ip6); +ALTER EXTENSION ip4r ADD OPERATOR #(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION ip4_plus_bigint(ip4,bigint); +ALTER EXTENSION ip4r ADD FUNCTION ip4_plus_int(ip4,integer); +ALTER EXTENSION ip4r ADD FUNCTION ip4_plus_numeric(ip4,numeric); +ALTER EXTENSION ip4r ADD OPERATOR +(ip4,bigint); +ALTER EXTENSION ip4r ADD OPERATOR +(ip4,integer); +ALTER EXTENSION ip4r ADD OPERATOR +(ip4,numeric); +ALTER EXTENSION ip4r ADD FUNCTION ip6_plus_bigint(ip6,bigint); +ALTER EXTENSION ip4r ADD FUNCTION ip6_plus_int(ip6,integer); +ALTER EXTENSION ip4r ADD FUNCTION ip6_plus_numeric(ip6,numeric); +ALTER EXTENSION ip4r ADD OPERATOR +(ip6,bigint); +ALTER EXTENSION ip4r ADD OPERATOR +(ip6,integer); +ALTER EXTENSION ip4r ADD OPERATOR +(ip6,numeric); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_plus_bigint(ipaddress,bigint); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_plus_int(ipaddress,integer); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_plus_numeric(ipaddress,numeric); +ALTER EXTENSION ip4r ADD OPERATOR +(ipaddress,bigint); +ALTER EXTENSION ip4r ADD OPERATOR +(ipaddress,integer); +ALTER EXTENSION ip4r ADD OPERATOR +(ipaddress,numeric); +ALTER EXTENSION ip4r ADD FUNCTION ip4_minus_bigint(ip4,bigint); +ALTER EXTENSION ip4r ADD FUNCTION ip4_minus_int(ip4,integer); +ALTER EXTENSION ip4r ADD FUNCTION ip4_minus_numeric(ip4,numeric); +ALTER EXTENSION ip4r ADD OPERATOR -(ip4,bigint); +ALTER EXTENSION ip4r ADD OPERATOR -(ip4,integer); +ALTER EXTENSION ip4r ADD OPERATOR -(ip4,numeric); +ALTER EXTENSION ip4r ADD FUNCTION ip6_minus_bigint(ip6,bigint); +ALTER EXTENSION ip4r ADD FUNCTION ip6_minus_int(ip6,integer); +ALTER EXTENSION ip4r ADD FUNCTION ip6_minus_numeric(ip6,numeric); +ALTER EXTENSION ip4r ADD OPERATOR -(ip6,bigint); +ALTER EXTENSION ip4r ADD OPERATOR -(ip6,integer); +ALTER EXTENSION ip4r ADD OPERATOR -(ip6,numeric); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_minus_bigint(ipaddress,bigint); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_minus_int(ipaddress,integer); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_minus_numeric(ipaddress,numeric); +ALTER EXTENSION ip4r ADD OPERATOR -(ipaddress,bigint); +ALTER EXTENSION ip4r ADD OPERATOR -(ipaddress,integer); +ALTER EXTENSION ip4r ADD OPERATOR -(ipaddress,numeric); +ALTER EXTENSION ip4r ADD FUNCTION ip4_minus_ip4(ip4,ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip6_minus_ip6(ip6,ip6); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_minus_ipaddress(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD OPERATOR -(ip4,ip4); +ALTER EXTENSION ip4r ADD OPERATOR -(ip6,ip6); +ALTER EXTENSION ip4r ADD OPERATOR -(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_contained_by(ip4r,ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_contained_by(ip6r,ip6r); +ALTER EXTENSION ip4r ADD FUNCTION iprange_contained_by(iprange,iprange); +ALTER EXTENSION ip4r ADD OPERATOR <<=(ip4r,ip4r); +ALTER EXTENSION ip4r ADD OPERATOR <<=(ip6r,ip6r); +ALTER EXTENSION ip4r ADD OPERATOR <<=(iprange,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_contained_by_strict(ip4r,ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_contained_by_strict(ip6r,ip6r); +ALTER EXTENSION ip4r ADD FUNCTION iprange_contained_by_strict(iprange,iprange); +ALTER EXTENSION ip4r ADD OPERATOR <<(ip4r,ip4r); +ALTER EXTENSION ip4r ADD OPERATOR <<(ip6r,ip6r); +ALTER EXTENSION ip4r ADD OPERATOR <<(iprange,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_contains(ip4r,ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_contains(ip6r,ip6r); +ALTER EXTENSION ip4r ADD FUNCTION iprange_contains(iprange,iprange); +ALTER EXTENSION ip4r ADD OPERATOR >>=(ip4r,ip4r); +ALTER EXTENSION ip4r ADD OPERATOR >>=(ip6r,ip6r); +ALTER EXTENSION ip4r ADD OPERATOR >>=(iprange,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_contains_strict(ip4r,ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_contains_strict(ip6r,ip6r); +ALTER EXTENSION ip4r ADD FUNCTION iprange_contains_strict(iprange,iprange); +ALTER EXTENSION ip4r ADD OPERATOR >>(ip4r,ip4r); +ALTER EXTENSION ip4r ADD OPERATOR >>(ip6r,ip6r); +ALTER EXTENSION ip4r ADD OPERATOR >>(iprange,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_overlaps(ip4r,ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_overlaps(ip6r,ip6r); +ALTER EXTENSION ip4r ADD FUNCTION iprange_overlaps(iprange,iprange); +ALTER EXTENSION ip4r ADD OPERATOR &&(ip4r,ip4r); +ALTER EXTENSION ip4r ADD OPERATOR &&(ip6r,ip6r); +ALTER EXTENSION ip4r ADD OPERATOR &&(iprange,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4_contained_by(ip4,ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip4_contained_by(ip4,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip6_contained_by(ip6,ip6r); +ALTER EXTENSION ip4r ADD FUNCTION ip6_contained_by(ip6,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_contained_by(ipaddress,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4_contains(ip4r,ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip6_contains(ip6r,ip6); +ALTER EXTENSION ip4r ADD FUNCTION ip4_contains(iprange,ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip6_contains(iprange,ip6); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_contains(iprange,ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION ip4_eq(ip4,ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_eq(ip4r,ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6_eq(ip6,ip6); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_eq(ip6r,ip6r); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_eq(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION iprange_eq(iprange,iprange); +ALTER EXTENSION ip4r ADD OPERATOR =(ip4,ip4); +ALTER EXTENSION ip4r ADD OPERATOR =(ip4r,ip4r); +ALTER EXTENSION ip4r ADD OPERATOR =(ip6,ip6); +ALTER EXTENSION ip4r ADD OPERATOR =(ip6r,ip6r); +ALTER EXTENSION ip4r ADD OPERATOR =(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD OPERATOR =(iprange,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4_ge(ip4,ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_ge(ip4r,ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6_ge(ip6,ip6); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_ge(ip6r,ip6r); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_ge(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION iprange_ge(iprange,iprange); +ALTER EXTENSION ip4r ADD OPERATOR >=(ip4,ip4); +ALTER EXTENSION ip4r ADD OPERATOR >=(ip4r,ip4r); +ALTER EXTENSION ip4r ADD OPERATOR >=(ip6,ip6); +ALTER EXTENSION ip4r ADD OPERATOR >=(ip6r,ip6r); +ALTER EXTENSION ip4r ADD OPERATOR >=(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD OPERATOR >=(iprange,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4_gt(ip4,ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_gt(ip4r,ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6_gt(ip6,ip6); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_gt(ip6r,ip6r); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_gt(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION iprange_gt(iprange,iprange); +ALTER EXTENSION ip4r ADD OPERATOR >(ip4,ip4); +ALTER EXTENSION ip4r ADD OPERATOR >(ip4r,ip4r); +ALTER EXTENSION ip4r ADD OPERATOR >(ip6,ip6); +ALTER EXTENSION ip4r ADD OPERATOR >(ip6r,ip6r); +ALTER EXTENSION ip4r ADD OPERATOR >(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD OPERATOR >(iprange,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4_le(ip4,ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_le(ip4r,ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6_le(ip6,ip6); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_le(ip6r,ip6r); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_le(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION iprange_le(iprange,iprange); +ALTER EXTENSION ip4r ADD OPERATOR <=(ip4,ip4); +ALTER EXTENSION ip4r ADD OPERATOR <=(ip4r,ip4r); +ALTER EXTENSION ip4r ADD OPERATOR <=(ip6,ip6); +ALTER EXTENSION ip4r ADD OPERATOR <=(ip6r,ip6r); +ALTER EXTENSION ip4r ADD OPERATOR <=(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD OPERATOR <=(iprange,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4_lt(ip4,ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_lt(ip4r,ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6_lt(ip6,ip6); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_lt(ip6r,ip6r); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_lt(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION iprange_lt(iprange,iprange); +ALTER EXTENSION ip4r ADD OPERATOR <(ip4,ip4); +ALTER EXTENSION ip4r ADD OPERATOR <(ip4r,ip4r); +ALTER EXTENSION ip4r ADD OPERATOR <(ip6,ip6); +ALTER EXTENSION ip4r ADD OPERATOR <(ip6r,ip6r); +ALTER EXTENSION ip4r ADD OPERATOR <(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD OPERATOR <(iprange,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4_neq(ip4,ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_neq(ip4r,ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6_neq(ip6,ip6); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_neq(ip6r,ip6r); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_neq(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION iprange_neq(iprange,iprange); +ALTER EXTENSION ip4r ADD OPERATOR <>(ip4,ip4); +ALTER EXTENSION ip4r ADD OPERATOR <>(ip4r,ip4r); +ALTER EXTENSION ip4r ADD OPERATOR <>(ip6,ip6); +ALTER EXTENSION ip4r ADD OPERATOR <>(ip6r,ip6r); +ALTER EXTENSION ip4r ADD OPERATOR <>(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD OPERATOR <>(iprange,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4_cmp(ip4,ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_cmp(ip4r,ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6_cmp(ip6,ip6); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_cmp(ip6r,ip6r); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_cmp(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION iprange_cmp(iprange,iprange); +ALTER EXTENSION ip4r ADD OPERATOR CLASS btree_ip4_ops USING btree; +ALTER EXTENSION ip4r ADD OPERATOR CLASS btree_ip4r_ops USING btree; +ALTER EXTENSION ip4r ADD OPERATOR CLASS btree_ip6_ops USING btree; +ALTER EXTENSION ip4r ADD OPERATOR CLASS btree_ip6r_ops USING btree; +ALTER EXTENSION ip4r ADD OPERATOR CLASS btree_ipaddress_ops USING btree; +ALTER EXTENSION ip4r ADD OPERATOR CLASS btree_iprange_ops USING btree; +ALTER EXTENSION ip4r ADD FUNCTION ip4hash(ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip6hash(ip6); +ALTER EXTENSION ip4r ADD FUNCTION ipaddresshash(ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION ip4rhash(ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6rhash(ip6r); +ALTER EXTENSION ip4r ADD FUNCTION iprangehash(iprange); +ALTER EXTENSION ip4r ADD OPERATOR CLASS hash_ip4_ops USING hash; +ALTER EXTENSION ip4r ADD OPERATOR CLASS hash_ip4r_ops USING hash; +ALTER EXTENSION ip4r ADD OPERATOR CLASS hash_ip6_ops USING hash; +ALTER EXTENSION ip4r ADD OPERATOR CLASS hash_ip6r_ops USING hash; +ALTER EXTENSION ip4r ADD OPERATOR CLASS hash_ipaddress_ops USING hash; +ALTER EXTENSION ip4r ADD OPERATOR CLASS hash_iprange_ops USING hash; +ALTER EXTENSION ip4r ADD FUNCTION gip4r_consistent(internal,ip4r,int4); +ALTER EXTENSION ip4r ADD FUNCTION gip4r_compress(internal); +ALTER EXTENSION ip4r ADD FUNCTION gip4r_decompress(internal); +ALTER EXTENSION ip4r ADD FUNCTION gip4r_penalty(internal,internal,internal); +ALTER EXTENSION ip4r ADD FUNCTION gip4r_picksplit(internal, internal); +ALTER EXTENSION ip4r ADD FUNCTION gip4r_union(internal, internal); +ALTER EXTENSION ip4r ADD FUNCTION gip4r_same(ip4r, ip4r, internal); +ALTER EXTENSION ip4r ADD FUNCTION gip6r_consistent(internal,ip6r,int4); +ALTER EXTENSION ip4r ADD FUNCTION gip6r_compress(internal); +ALTER EXTENSION ip4r ADD FUNCTION gip6r_decompress(internal); +ALTER EXTENSION ip4r ADD FUNCTION gip6r_penalty(internal,internal,internal); +ALTER EXTENSION ip4r ADD FUNCTION gip6r_picksplit(internal, internal); +ALTER EXTENSION ip4r ADD FUNCTION gip6r_union(internal, internal); +ALTER EXTENSION ip4r ADD FUNCTION gip6r_same(ip6r, ip6r, internal); +ALTER EXTENSION ip4r ADD FUNCTION gipr_consistent(internal,iprange,int4); +ALTER EXTENSION ip4r ADD FUNCTION gipr_compress(internal); +ALTER EXTENSION ip4r ADD FUNCTION gipr_decompress(internal); +ALTER EXTENSION ip4r ADD FUNCTION gipr_penalty(internal,internal,internal); +ALTER EXTENSION ip4r ADD FUNCTION gipr_picksplit(internal, internal); +ALTER EXTENSION ip4r ADD FUNCTION gipr_union(internal, internal); +ALTER EXTENSION ip4r ADD FUNCTION gipr_same(iprange, iprange, internal); +ALTER EXTENSION ip4r ADD OPERATOR CLASS gist_ip4r_ops USING gist; +ALTER EXTENSION ip4r ADD OPERATOR CLASS gist_ip6r_ops USING gist; +ALTER EXTENSION ip4r ADD OPERATOR CLASS gist_iprange_ops USING gist; + +-- end diff -Nru ip4r-2.3/scripts/ip4r--unpackaged2.1--2.1.sql ip4r-2.4/scripts/ip4r--unpackaged2.1--2.1.sql --- ip4r-2.3/scripts/ip4r--unpackaged2.1--2.1.sql 1970-01-01 00:00:00.000000000 +0000 +++ ip4r-2.4/scripts/ip4r--unpackaged2.1--2.1.sql 2018-11-21 06:35:30.000000000 +0000 @@ -0,0 +1,423 @@ +-- ip4r extension + +-- complain if script is sourced in psql, rather than via CREATE EXTENSION +\echo Use "CREATE EXTENSION ip4r" to load this file. \quit + +ALTER EXTENSION ip4r ADD FUNCTION ip4_in(cstring); +ALTER EXTENSION ip4r ADD FUNCTION ip4_out(ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip4_recv(internal); +ALTER EXTENSION ip4r ADD FUNCTION ip4_send(ip4); +ALTER EXTENSION ip4r ADD TYPE ip4; +ALTER EXTENSION ip4r ADD FUNCTION ip4r_in(cstring); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_out(ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_recv(internal); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_send(ip4r); +ALTER EXTENSION ip4r ADD TYPE ip4r; +ALTER EXTENSION ip4r ADD FUNCTION ip6_in(cstring); +ALTER EXTENSION ip4r ADD FUNCTION ip6_out(ip6); +ALTER EXTENSION ip4r ADD FUNCTION ip6_recv(internal); +ALTER EXTENSION ip4r ADD FUNCTION ip6_send(ip6); +ALTER EXTENSION ip4r ADD TYPE ip6; +ALTER EXTENSION ip4r ADD FUNCTION ip6r_in(cstring); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_out(ip6r); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_recv(internal); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_send(ip6r); +ALTER EXTENSION ip4r ADD TYPE ip6r; +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_in(cstring); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_out(ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_recv(internal); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_send(ipaddress); +ALTER EXTENSION ip4r ADD TYPE ipaddress; +ALTER EXTENSION ip4r ADD FUNCTION iprange_in(cstring); +ALTER EXTENSION ip4r ADD FUNCTION iprange_out(iprange); +ALTER EXTENSION ip4r ADD FUNCTION iprange_recv(internal); +ALTER EXTENSION ip4r ADD FUNCTION iprange_send(iprange); +ALTER EXTENSION ip4r ADD TYPE iprange; +ALTER EXTENSION ip4r ADD FUNCTION ip4(bigint); +ALTER EXTENSION ip4r ADD FUNCTION ip4(double precision); +ALTER EXTENSION ip4r ADD FUNCTION ip4(numeric); +ALTER EXTENSION ip4r ADD FUNCTION ip4(inet); +ALTER EXTENSION ip4r ADD FUNCTION ip4(text); +ALTER EXTENSION ip4r ADD FUNCTION ip4(ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION ip6(numeric); +ALTER EXTENSION ip4r ADD FUNCTION ip6(inet); +ALTER EXTENSION ip4r ADD FUNCTION ip6(text); +ALTER EXTENSION ip4r ADD FUNCTION ip6(ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress(inet); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress(ip4); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress(ip6); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress(text); +ALTER EXTENSION ip4r ADD FUNCTION ip4r(cidr); +ALTER EXTENSION ip4r ADD FUNCTION ip4r(ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip4r(text); +ALTER EXTENSION ip4r ADD FUNCTION ip4r(iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip6r(cidr); +ALTER EXTENSION ip4r ADD FUNCTION ip6r(ip6); +ALTER EXTENSION ip4r ADD FUNCTION ip6r(text); +ALTER EXTENSION ip4r ADD FUNCTION ip6r(iprange); +ALTER EXTENSION ip4r ADD FUNCTION iprange(cidr); +ALTER EXTENSION ip4r ADD FUNCTION iprange(ip4); +ALTER EXTENSION ip4r ADD FUNCTION iprange(ip6); +ALTER EXTENSION ip4r ADD FUNCTION iprange(ip4r); +ALTER EXTENSION ip4r ADD FUNCTION iprange(ip6r); +ALTER EXTENSION ip4r ADD FUNCTION iprange(ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION iprange(text); +ALTER EXTENSION ip4r ADD FUNCTION cidr(ip4); +ALTER EXTENSION ip4r ADD FUNCTION cidr(ip4r); +ALTER EXTENSION ip4r ADD FUNCTION cidr(ip6); +ALTER EXTENSION ip4r ADD FUNCTION cidr(ip6r); +ALTER EXTENSION ip4r ADD FUNCTION cidr(ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION cidr(iprange); +ALTER EXTENSION ip4r ADD FUNCTION text(ip4); +ALTER EXTENSION ip4r ADD FUNCTION text(ip4r); +ALTER EXTENSION ip4r ADD FUNCTION text(ip6); +ALTER EXTENSION ip4r ADD FUNCTION text(ip6r); +ALTER EXTENSION ip4r ADD FUNCTION text(ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION text(iprange); +ALTER EXTENSION ip4r ADD FUNCTION to_bigint(ip4); +ALTER EXTENSION ip4r ADD FUNCTION to_double(ip4); +ALTER EXTENSION ip4r ADD FUNCTION to_numeric(ip4); +ALTER EXTENSION ip4r ADD FUNCTION to_numeric(ip6); +ALTER EXTENSION ip4r ADD FUNCTION to_numeric(ipaddress); +ALTER EXTENSION ip4r ADD CAST (ip4 as bigint); +ALTER EXTENSION ip4r ADD CAST (ip4 as double precision); +ALTER EXTENSION ip4r ADD CAST (ip4 as numeric); +ALTER EXTENSION ip4r ADD CAST (ip4 as text); +ALTER EXTENSION ip4r ADD CAST (ip4 as cidr); +ALTER EXTENSION ip4r ADD CAST (ip4r as cidr); +ALTER EXTENSION ip4r ADD CAST (ip4r as text); +ALTER EXTENSION ip4r ADD CAST (ip6 as numeric); +ALTER EXTENSION ip4r ADD CAST (ip6 as text); +ALTER EXTENSION ip4r ADD CAST (ip6 as cidr); +ALTER EXTENSION ip4r ADD CAST (ip6r as cidr); +ALTER EXTENSION ip4r ADD CAST (ip6r as text); +ALTER EXTENSION ip4r ADD CAST (ipaddress as numeric); +ALTER EXTENSION ip4r ADD CAST (ipaddress as text); +ALTER EXTENSION ip4r ADD CAST (ipaddress as cidr); +ALTER EXTENSION ip4r ADD CAST (iprange as cidr); +ALTER EXTENSION ip4r ADD CAST (iprange as text); +ALTER EXTENSION ip4r ADD CAST (text as ip4); +ALTER EXTENSION ip4r ADD CAST (text as ip4r); +ALTER EXTENSION ip4r ADD CAST (text as ip6); +ALTER EXTENSION ip4r ADD CAST (text as ip6r); +ALTER EXTENSION ip4r ADD CAST (text as ipaddress); +ALTER EXTENSION ip4r ADD CAST (text as iprange); +ALTER EXTENSION ip4r ADD CAST (bigint as ip4); +ALTER EXTENSION ip4r ADD CAST (double precision as ip4); +ALTER EXTENSION ip4r ADD CAST (numeric as ip4); +ALTER EXTENSION ip4r ADD CAST (numeric as ip6); +ALTER EXTENSION ip4r ADD CAST (cidr as ip4r); +ALTER EXTENSION ip4r ADD CAST (cidr as ip6r); +ALTER EXTENSION ip4r ADD CAST (cidr as iprange); +ALTER EXTENSION ip4r ADD CAST (inet as ip4); +ALTER EXTENSION ip4r ADD CAST (inet as ip6); +ALTER EXTENSION ip4r ADD CAST (inet as ipaddress); +ALTER EXTENSION ip4r ADD CAST (ip4 as ip4r); +ALTER EXTENSION ip4r ADD CAST (ip4 as ipaddress); +ALTER EXTENSION ip4r ADD CAST (ip4 as iprange); +ALTER EXTENSION ip4r ADD CAST (ip4r as iprange); +ALTER EXTENSION ip4r ADD CAST (ip6 as ip6r); +ALTER EXTENSION ip4r ADD CAST (ip6 as ipaddress); +ALTER EXTENSION ip4r ADD CAST (ip6 as iprange); +ALTER EXTENSION ip4r ADD CAST (ip6r as iprange); +ALTER EXTENSION ip4r ADD CAST (ipaddress as iprange); +ALTER EXTENSION ip4r ADD CAST (ipaddress as ip4); +ALTER EXTENSION ip4r ADD CAST (ipaddress as ip6); +ALTER EXTENSION ip4r ADD CAST (iprange as ip4r); +ALTER EXTENSION ip4r ADD CAST (iprange as ip6r); +ALTER EXTENSION ip4r ADD FUNCTION ip4r(ip4,ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip6r(ip6,ip6); +ALTER EXTENSION ip4r ADD FUNCTION iprange(ip4,ip4); +ALTER EXTENSION ip4r ADD FUNCTION iprange(ip6,ip6); +ALTER EXTENSION ip4r ADD FUNCTION iprange(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION family(ip4); +ALTER EXTENSION ip4r ADD FUNCTION family(ip4r); +ALTER EXTENSION ip4r ADD FUNCTION family(ip6); +ALTER EXTENSION ip4r ADD FUNCTION family(ip6r); +ALTER EXTENSION ip4r ADD FUNCTION family(ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION family(iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4_netmask(integer); +ALTER EXTENSION ip4r ADD FUNCTION ip6_netmask(integer); +ALTER EXTENSION ip4r ADD FUNCTION is_cidr(ip4r); +ALTER EXTENSION ip4r ADD FUNCTION is_cidr(ip6r); +ALTER EXTENSION ip4r ADD FUNCTION is_cidr(iprange); +ALTER EXTENSION ip4r ADD FUNCTION masklen(ip4r); +ALTER EXTENSION ip4r ADD FUNCTION masklen(ip6r); +ALTER EXTENSION ip4r ADD FUNCTION masklen(iprange); +ALTER EXTENSION ip4r ADD FUNCTION lower(ip4r); +ALTER EXTENSION ip4r ADD FUNCTION lower(ip6r); +ALTER EXTENSION ip4r ADD FUNCTION lower(iprange); +ALTER EXTENSION ip4r ADD FUNCTION upper(ip4r); +ALTER EXTENSION ip4r ADD FUNCTION upper(ip6r); +ALTER EXTENSION ip4r ADD FUNCTION upper(iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4_net_lower(ip4,integer); +ALTER EXTENSION ip4r ADD FUNCTION ip6_net_lower(ip6,integer); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_net_lower(ipaddress,integer); +ALTER EXTENSION ip4r ADD FUNCTION ip4_net_upper(ip4,integer); +ALTER EXTENSION ip4r ADD FUNCTION ip6_net_upper(ip6,integer); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_net_upper(ipaddress,integer); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_union(ip4r, ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_union(ip6r, ip6r); +ALTER EXTENSION ip4r ADD FUNCTION iprange_union(iprange, iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_inter(ip4r,ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_inter(ip6r,ip6r); +ALTER EXTENSION ip4r ADD FUNCTION iprange_inter(iprange,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_net_mask(ip4,ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_net_mask(ip6,ip6); +ALTER EXTENSION ip4r ADD FUNCTION iprange_net_mask(ip4,ip4); +ALTER EXTENSION ip4r ADD FUNCTION iprange_net_mask(ip6,ip6); +ALTER EXTENSION ip4r ADD FUNCTION iprange_net_mask(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_net_prefix(ip4,integer); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_net_prefix(ip6,integer); +ALTER EXTENSION ip4r ADD FUNCTION iprange_net_prefix(ip4,integer); +ALTER EXTENSION ip4r ADD FUNCTION iprange_net_prefix(ip6,integer); +ALTER EXTENSION ip4r ADD FUNCTION iprange_net_prefix(ipaddress,integer); +ALTER EXTENSION ip4r ADD OPERATOR /(ip4,ip4); +ALTER EXTENSION ip4r ADD OPERATOR /(ip6,ip6); +ALTER EXTENSION ip4r ADD OPERATOR /(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD OPERATOR /(ip4,integer); +ALTER EXTENSION ip4r ADD OPERATOR /(ip6,integer); +ALTER EXTENSION ip4r ADD OPERATOR /(ipaddress,integer); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_size(ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_size(ip6r); +ALTER EXTENSION ip4r ADD FUNCTION iprange_size(iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_size_exact(ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_size_exact(ip6r); +ALTER EXTENSION ip4r ADD FUNCTION iprange_size_exact(iprange); +ALTER EXTENSION ip4r ADD OPERATOR @(NONE,ip4r); +ALTER EXTENSION ip4r ADD OPERATOR @(NONE,ip6r); +ALTER EXTENSION ip4r ADD OPERATOR @(NONE,iprange); +ALTER EXTENSION ip4r ADD OPERATOR @@(NONE,ip4r); +ALTER EXTENSION ip4r ADD OPERATOR @@(NONE,ip6r); +ALTER EXTENSION ip4r ADD OPERATOR @@(NONE,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4_and(ip4,ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip6_and(ip6,ip6); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_and(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD OPERATOR &(ip4,ip4); +ALTER EXTENSION ip4r ADD OPERATOR &(ip6,ip6); +ALTER EXTENSION ip4r ADD OPERATOR &(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION ip4_or(ip4,ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip6_or(ip6,ip6); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_or(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD OPERATOR |(ip4,ip4); +ALTER EXTENSION ip4r ADD OPERATOR |(ip6,ip6); +ALTER EXTENSION ip4r ADD OPERATOR |(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION ip4_not(ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip6_not(ip6); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_not(ipaddress); +ALTER EXTENSION ip4r ADD OPERATOR ~(NONE,ip4); +ALTER EXTENSION ip4r ADD OPERATOR ~(NONE,ip6); +ALTER EXTENSION ip4r ADD OPERATOR ~(NONE,ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION ip4_xor(ip4,ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip6_xor(ip6,ip6); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_xor(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD OPERATOR #(ip4,ip4); +ALTER EXTENSION ip4r ADD OPERATOR #(ip6,ip6); +ALTER EXTENSION ip4r ADD OPERATOR #(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION ip4_plus_bigint(ip4,bigint); +ALTER EXTENSION ip4r ADD FUNCTION ip4_plus_int(ip4,integer); +ALTER EXTENSION ip4r ADD FUNCTION ip4_plus_numeric(ip4,numeric); +ALTER EXTENSION ip4r ADD OPERATOR +(ip4,bigint); +ALTER EXTENSION ip4r ADD OPERATOR +(ip4,integer); +ALTER EXTENSION ip4r ADD OPERATOR +(ip4,numeric); +ALTER EXTENSION ip4r ADD FUNCTION ip6_plus_bigint(ip6,bigint); +ALTER EXTENSION ip4r ADD FUNCTION ip6_plus_int(ip6,integer); +ALTER EXTENSION ip4r ADD FUNCTION ip6_plus_numeric(ip6,numeric); +ALTER EXTENSION ip4r ADD OPERATOR +(ip6,bigint); +ALTER EXTENSION ip4r ADD OPERATOR +(ip6,integer); +ALTER EXTENSION ip4r ADD OPERATOR +(ip6,numeric); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_plus_bigint(ipaddress,bigint); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_plus_int(ipaddress,integer); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_plus_numeric(ipaddress,numeric); +ALTER EXTENSION ip4r ADD OPERATOR +(ipaddress,bigint); +ALTER EXTENSION ip4r ADD OPERATOR +(ipaddress,integer); +ALTER EXTENSION ip4r ADD OPERATOR +(ipaddress,numeric); +ALTER EXTENSION ip4r ADD FUNCTION ip4_minus_bigint(ip4,bigint); +ALTER EXTENSION ip4r ADD FUNCTION ip4_minus_int(ip4,integer); +ALTER EXTENSION ip4r ADD FUNCTION ip4_minus_numeric(ip4,numeric); +ALTER EXTENSION ip4r ADD OPERATOR -(ip4,bigint); +ALTER EXTENSION ip4r ADD OPERATOR -(ip4,integer); +ALTER EXTENSION ip4r ADD OPERATOR -(ip4,numeric); +ALTER EXTENSION ip4r ADD FUNCTION ip6_minus_bigint(ip6,bigint); +ALTER EXTENSION ip4r ADD FUNCTION ip6_minus_int(ip6,integer); +ALTER EXTENSION ip4r ADD FUNCTION ip6_minus_numeric(ip6,numeric); +ALTER EXTENSION ip4r ADD OPERATOR -(ip6,bigint); +ALTER EXTENSION ip4r ADD OPERATOR -(ip6,integer); +ALTER EXTENSION ip4r ADD OPERATOR -(ip6,numeric); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_minus_bigint(ipaddress,bigint); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_minus_int(ipaddress,integer); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_minus_numeric(ipaddress,numeric); +ALTER EXTENSION ip4r ADD OPERATOR -(ipaddress,bigint); +ALTER EXTENSION ip4r ADD OPERATOR -(ipaddress,integer); +ALTER EXTENSION ip4r ADD OPERATOR -(ipaddress,numeric); +ALTER EXTENSION ip4r ADD FUNCTION ip4_minus_ip4(ip4,ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip6_minus_ip6(ip6,ip6); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_minus_ipaddress(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD OPERATOR -(ip4,ip4); +ALTER EXTENSION ip4r ADD OPERATOR -(ip6,ip6); +ALTER EXTENSION ip4r ADD OPERATOR -(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_contained_by(ip4r,ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_contained_by(ip6r,ip6r); +ALTER EXTENSION ip4r ADD FUNCTION iprange_contained_by(iprange,iprange); +ALTER EXTENSION ip4r ADD OPERATOR <<=(ip4r,ip4r); +ALTER EXTENSION ip4r ADD OPERATOR <<=(ip6r,ip6r); +ALTER EXTENSION ip4r ADD OPERATOR <<=(iprange,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_contained_by_strict(ip4r,ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_contained_by_strict(ip6r,ip6r); +ALTER EXTENSION ip4r ADD FUNCTION iprange_contained_by_strict(iprange,iprange); +ALTER EXTENSION ip4r ADD OPERATOR <<(ip4r,ip4r); +ALTER EXTENSION ip4r ADD OPERATOR <<(ip6r,ip6r); +ALTER EXTENSION ip4r ADD OPERATOR <<(iprange,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_contains(ip4r,ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_contains(ip6r,ip6r); +ALTER EXTENSION ip4r ADD FUNCTION iprange_contains(iprange,iprange); +ALTER EXTENSION ip4r ADD OPERATOR >>=(ip4r,ip4r); +ALTER EXTENSION ip4r ADD OPERATOR >>=(ip6r,ip6r); +ALTER EXTENSION ip4r ADD OPERATOR >>=(iprange,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_contains_strict(ip4r,ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_contains_strict(ip6r,ip6r); +ALTER EXTENSION ip4r ADD FUNCTION iprange_contains_strict(iprange,iprange); +ALTER EXTENSION ip4r ADD OPERATOR >>(ip4r,ip4r); +ALTER EXTENSION ip4r ADD OPERATOR >>(ip6r,ip6r); +ALTER EXTENSION ip4r ADD OPERATOR >>(iprange,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_overlaps(ip4r,ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_overlaps(ip6r,ip6r); +ALTER EXTENSION ip4r ADD FUNCTION iprange_overlaps(iprange,iprange); +ALTER EXTENSION ip4r ADD OPERATOR &&(ip4r,ip4r); +ALTER EXTENSION ip4r ADD OPERATOR &&(ip6r,ip6r); +ALTER EXTENSION ip4r ADD OPERATOR &&(iprange,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4_contained_by(ip4,ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip4_contained_by(ip4,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip6_contained_by(ip6,ip6r); +ALTER EXTENSION ip4r ADD FUNCTION ip6_contained_by(ip6,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_contained_by(ipaddress,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4_contains(ip4r,ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip6_contains(ip6r,ip6); +ALTER EXTENSION ip4r ADD FUNCTION ip4_contains(iprange,ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip6_contains(iprange,ip6); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_contains(iprange,ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION ip4_eq(ip4,ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_eq(ip4r,ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6_eq(ip6,ip6); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_eq(ip6r,ip6r); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_eq(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION iprange_eq(iprange,iprange); +ALTER EXTENSION ip4r ADD OPERATOR =(ip4,ip4); +ALTER EXTENSION ip4r ADD OPERATOR =(ip4r,ip4r); +ALTER EXTENSION ip4r ADD OPERATOR =(ip6,ip6); +ALTER EXTENSION ip4r ADD OPERATOR =(ip6r,ip6r); +ALTER EXTENSION ip4r ADD OPERATOR =(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD OPERATOR =(iprange,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4_ge(ip4,ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_ge(ip4r,ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6_ge(ip6,ip6); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_ge(ip6r,ip6r); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_ge(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION iprange_ge(iprange,iprange); +ALTER EXTENSION ip4r ADD OPERATOR >=(ip4,ip4); +ALTER EXTENSION ip4r ADD OPERATOR >=(ip4r,ip4r); +ALTER EXTENSION ip4r ADD OPERATOR >=(ip6,ip6); +ALTER EXTENSION ip4r ADD OPERATOR >=(ip6r,ip6r); +ALTER EXTENSION ip4r ADD OPERATOR >=(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD OPERATOR >=(iprange,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4_gt(ip4,ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_gt(ip4r,ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6_gt(ip6,ip6); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_gt(ip6r,ip6r); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_gt(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION iprange_gt(iprange,iprange); +ALTER EXTENSION ip4r ADD OPERATOR >(ip4,ip4); +ALTER EXTENSION ip4r ADD OPERATOR >(ip4r,ip4r); +ALTER EXTENSION ip4r ADD OPERATOR >(ip6,ip6); +ALTER EXTENSION ip4r ADD OPERATOR >(ip6r,ip6r); +ALTER EXTENSION ip4r ADD OPERATOR >(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD OPERATOR >(iprange,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4_le(ip4,ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_le(ip4r,ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6_le(ip6,ip6); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_le(ip6r,ip6r); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_le(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION iprange_le(iprange,iprange); +ALTER EXTENSION ip4r ADD OPERATOR <=(ip4,ip4); +ALTER EXTENSION ip4r ADD OPERATOR <=(ip4r,ip4r); +ALTER EXTENSION ip4r ADD OPERATOR <=(ip6,ip6); +ALTER EXTENSION ip4r ADD OPERATOR <=(ip6r,ip6r); +ALTER EXTENSION ip4r ADD OPERATOR <=(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD OPERATOR <=(iprange,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4_lt(ip4,ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_lt(ip4r,ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6_lt(ip6,ip6); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_lt(ip6r,ip6r); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_lt(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION iprange_lt(iprange,iprange); +ALTER EXTENSION ip4r ADD OPERATOR <(ip4,ip4); +ALTER EXTENSION ip4r ADD OPERATOR <(ip4r,ip4r); +ALTER EXTENSION ip4r ADD OPERATOR <(ip6,ip6); +ALTER EXTENSION ip4r ADD OPERATOR <(ip6r,ip6r); +ALTER EXTENSION ip4r ADD OPERATOR <(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD OPERATOR <(iprange,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4_neq(ip4,ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_neq(ip4r,ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6_neq(ip6,ip6); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_neq(ip6r,ip6r); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_neq(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION iprange_neq(iprange,iprange); +ALTER EXTENSION ip4r ADD OPERATOR <>(ip4,ip4); +ALTER EXTENSION ip4r ADD OPERATOR <>(ip4r,ip4r); +ALTER EXTENSION ip4r ADD OPERATOR <>(ip6,ip6); +ALTER EXTENSION ip4r ADD OPERATOR <>(ip6r,ip6r); +ALTER EXTENSION ip4r ADD OPERATOR <>(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD OPERATOR <>(iprange,iprange); +ALTER EXTENSION ip4r ADD FUNCTION ip4_cmp(ip4,ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip4r_cmp(ip4r,ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6_cmp(ip6,ip6); +ALTER EXTENSION ip4r ADD FUNCTION ip6r_cmp(ip6r,ip6r); +ALTER EXTENSION ip4r ADD FUNCTION ipaddress_cmp(ipaddress,ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION iprange_cmp(iprange,iprange); +ALTER EXTENSION ip4r ADD OPERATOR CLASS btree_ip4_ops USING btree; +ALTER EXTENSION ip4r ADD OPERATOR CLASS btree_ip4r_ops USING btree; +ALTER EXTENSION ip4r ADD OPERATOR CLASS btree_ip6_ops USING btree; +ALTER EXTENSION ip4r ADD OPERATOR CLASS btree_ip6r_ops USING btree; +ALTER EXTENSION ip4r ADD OPERATOR CLASS btree_ipaddress_ops USING btree; +ALTER EXTENSION ip4r ADD OPERATOR CLASS btree_iprange_ops USING btree; +ALTER EXTENSION ip4r ADD FUNCTION ip4hash(ip4); +ALTER EXTENSION ip4r ADD FUNCTION ip6hash(ip6); +ALTER EXTENSION ip4r ADD FUNCTION ipaddresshash(ipaddress); +ALTER EXTENSION ip4r ADD FUNCTION ip4rhash(ip4r); +ALTER EXTENSION ip4r ADD FUNCTION ip6rhash(ip6r); +ALTER EXTENSION ip4r ADD FUNCTION iprangehash(iprange); +ALTER EXTENSION ip4r ADD OPERATOR CLASS hash_ip4_ops USING hash; +ALTER EXTENSION ip4r ADD OPERATOR CLASS hash_ip4r_ops USING hash; +ALTER EXTENSION ip4r ADD OPERATOR CLASS hash_ip6_ops USING hash; +ALTER EXTENSION ip4r ADD OPERATOR CLASS hash_ip6r_ops USING hash; +ALTER EXTENSION ip4r ADD OPERATOR CLASS hash_ipaddress_ops USING hash; +ALTER EXTENSION ip4r ADD OPERATOR CLASS hash_iprange_ops USING hash; +ALTER EXTENSION ip4r ADD FUNCTION gip4r_consistent(internal,ip4r,int2,oid,internal); +ALTER EXTENSION ip4r ADD FUNCTION gip4r_compress(internal); +ALTER EXTENSION ip4r ADD FUNCTION gip4r_decompress(internal); +ALTER EXTENSION ip4r ADD FUNCTION gip4r_penalty(internal,internal,internal); +ALTER EXTENSION ip4r ADD FUNCTION gip4r_picksplit(internal, internal); +ALTER EXTENSION ip4r ADD FUNCTION gip4r_union(internal, internal); +ALTER EXTENSION ip4r ADD FUNCTION gip4r_same(ip4r, ip4r, internal); +ALTER EXTENSION ip4r ADD FUNCTION gip4r_fetch(internal); +ALTER EXTENSION ip4r ADD FUNCTION gip6r_consistent(internal,ip6r,int2,oid,internal); +ALTER EXTENSION ip4r ADD FUNCTION gip6r_compress(internal); +ALTER EXTENSION ip4r ADD FUNCTION gip6r_decompress(internal); +ALTER EXTENSION ip4r ADD FUNCTION gip6r_penalty(internal,internal,internal); +ALTER EXTENSION ip4r ADD FUNCTION gip6r_picksplit(internal, internal); +ALTER EXTENSION ip4r ADD FUNCTION gip6r_union(internal, internal); +ALTER EXTENSION ip4r ADD FUNCTION gip6r_same(ip6r, ip6r, internal); +ALTER EXTENSION ip4r ADD FUNCTION gip6r_fetch(internal); +ALTER EXTENSION ip4r ADD FUNCTION gipr_consistent(internal,iprange,int2,oid,internal); +ALTER EXTENSION ip4r ADD FUNCTION gipr_compress(internal); +ALTER EXTENSION ip4r ADD FUNCTION gipr_decompress(internal); +ALTER EXTENSION ip4r ADD FUNCTION gipr_penalty(internal,internal,internal); +ALTER EXTENSION ip4r ADD FUNCTION gipr_picksplit(internal, internal); +ALTER EXTENSION ip4r ADD FUNCTION gipr_union(internal, internal); +ALTER EXTENSION ip4r ADD FUNCTION gipr_same(iprange, iprange, internal); +ALTER EXTENSION ip4r ADD FUNCTION gipr_fetch(internal); +ALTER EXTENSION ip4r ADD OPERATOR CLASS gist_ip4r_ops USING gist; +ALTER EXTENSION ip4r ADD OPERATOR CLASS gist_ip6r_ops USING gist; +ALTER EXTENSION ip4r ADD OPERATOR CLASS gist_iprange_ops USING gist; + +-- end diff -Nru ip4r-2.3/sql/ip4r.sql ip4r-2.4/sql/ip4r.sql --- ip4r-2.3/sql/ip4r.sql 2018-05-24 21:30:28.000000000 +0000 +++ ip4r-2.4/sql/ip4r.sql 2018-11-21 06:35:30.000000000 +0000 @@ -1,7 +1,41 @@ -- +/*CUT-HERE*/ CREATE EXTENSION ip4r; +-- Check whether any of our opclasses fail amvalidate + +DO $d$ + DECLARE + r record; + BEGIN + IF current_setting('server_version_num')::integer >= 90600 THEN + FOR r IN SELECT amname, + CASE amname WHEN 'btree' THEN 6 + WHEN 'hash' THEN 6 + WHEN 'gist' THEN 3 + ELSE 0 END as expected, + count(nullif(amvalidate(opc.oid),false)) as actual + FROM pg_opclass opc + LEFT JOIN pg_am am ON am.oid = opcmethod + WHERE opcintype IN ('ip4'::regtype, + 'ip4r'::regtype, + 'ip6'::regtype, + 'ip6r'::regtype, + 'ipaddress'::regtype, + 'iprange'::regtype) + GROUP BY amname + ORDER BY amname + LOOP + IF r.expected IS DISTINCT FROM r.actual THEN + RAISE INFO '% % operator classes did not validate', r.expected - r.actual, r.amname; + END IF; + END LOOP; + END IF; + END; +$d$; +/*CUT-END*/ + \set VERBOSITY terse -- @@ -1596,6 +1630,64 @@ select '::'::ipaddress::ip4; select '0.0.0.0'::ipaddress::ip6; +-- bit casts + +select (x'01020304')::ip4; +select (x'fff0fff1fff2fff3000000000000fff4')::ip6; +select (x'01020304')::ipaddress; +select (x'fff0fff1fff2fff3000000000000fff4')::ipaddress; + +select (b'0001')::varbit::ip4r; +select (b'0001')::varbit::ip6r; +select (x'fff0fff1fff2fff3000000000000fff')::varbit::ip6r; + +select (ip4 '1.2.3.4')::varbit; +select (ip6 'fff0:fff1:fff2:fff3::fff4')::varbit; +select (ipaddress '1.2.3.4')::varbit; +select (ipaddress 'fff0:fff1:fff2:fff3::fff4')::varbit; + +select (ip4r '1.2.3.0/24')::varbit; +select (ip6r 'fff0::/12')::varbit; +select (ip6r 'fff0::/127')::varbit; + +select (iprange '-')::varbit; +select (iprange '1.2.3.0/24')::varbit; +select (iprange '1.2.3.1-1.2.3.2')::varbit; +select (iprange 'fff0::/12')::varbit; +select (iprange 'fff0::0001-fff0::0002')::varbit; + +-- invalid bit casts + +select (x'0102030')::ip4; +select (x'0102030405')::ip4; +select (x'fff0fff1fff2fff3000000000000fff')::ip6; +select (x'fff0fff1fff2fff3000000000000fff4f')::ip6; +select (x'0102030')::ipaddress; +select (x'0102030405')::ipaddress; +select (x'fff0fff1fff2fff3000000000000fff')::ipaddress; +select (x'fff0fff1fff2fff3000000000000fff4f')::ipaddress; + +-- bytea casts + +select (decode('01020304','hex'))::ip4; +select (decode('fff0fff1fff2fff3000000000000fff4','hex'))::ip6; +select (decode('01020304','hex'))::ipaddress; +select (decode('fff0fff1fff2fff3000000000000fff4','hex'))::ipaddress; + +select encode((ip4 '1.2.3.4')::bytea,'hex'); +select encode((ip6 'fff0:fff1:fff2:fff3::fff4')::bytea,'hex'); +select encode((ipaddress '1.2.3.4')::bytea,'hex'); +select encode((ipaddress 'fff0:fff1:fff2:fff3::fff4')::bytea,'hex'); + +-- invalid bytea casts + +select (decode('010203','hex'))::ip4; +select (decode('0102030405','hex'))::ip4; +select (decode('fff0fff1fff2fff3000000000000ff','hex'))::ip6; +select (decode('0102030405','hex'))::ipaddress; +select (decode('fff0fff1fff2fff3000000000000ff','hex'))::ipaddress; +select (decode('fff0fff1fff2fff3000000000000ffffff','hex'))::ipaddress; + -- constructor functions select ip4r('0.0.0.0','255.255.255.255'); @@ -1763,6 +1855,42 @@ select iprange_inter('2000::-4000::','3000::-5000::'); select iprange_inter('::/0','3000::-5000::'); +-- split + +select * from cidr_split(ip4r '1.2.3.4-5.6.7.8'); +select * from cidr_split(ip4r '1.2.3.5-5.6.7.7'); +select * from cidr_split(ip4r '1.0.0.0-1.0.255.255'); +select * from cidr_split(ip4r '0.0.0.0-255.255.255.255'); +select * from cidr_split(ip4r '0.0.0.0-0.0.0.9'); +select * from cidr_split(ip4r '255.255.255.251-255.255.255.255'); + +select * from cidr_split(ip6r 'ffff::1234-ffff::1243'); +select * from cidr_split(ip6r 'ffff:0:0:1234::-ffff:0:0:1243::'); +select * from cidr_split(ip6r 'aaaa::cdef-aaaa::fedc'); +select * from cidr_split(ip6r 'ffff:0:0:aaaa::/64'); +select * from cidr_split(ip6r '::-::0009'); +select * from cidr_split(ip6r 'ffff:ffff:ffff:ffff:ffff:ffff:ffff:fff3-ffff:ffff:ffff:ffff:ffff:ffff:ffff:ffff'); + +select * from cidr_split(iprange '1.2.3.4-5.6.7.8'); +select * from cidr_split(iprange '1.2.3.5-5.6.7.7'); +select * from cidr_split(iprange 'ffff::1234-ffff::1243'); +select * from cidr_split(iprange 'aaaa::cdef-aaaa::fedc'); +select * from cidr_split(iprange '1.0.0.0/16'); +select * from cidr_split(iprange 'ffff:0:0:aaaa::/64'); +select * from cidr_split(iprange '-'); + +-- rescan + +with d(a) as (values (ip4r '1.2.3.4-1.2.4.3'),(ip4r '10.2.3.5-10.2.4.4')) +select *, (select * from cidr_split(a) limit 1) as s from d; + +with d(a) as (values (ip6r 'ffff::1234-ffff::1243'),(ip6r 'aaaa::cdef-aaaa::fedc')) +select *, (select * from cidr_split(a) limit 1) as s from d; + +with d(a) as (values (iprange '-'),(iprange '1.2.3.4-1.2.4.3'), + (iprange 'aaaa::fedc-aaaa::cdef'),(iprange '-')) +select *, (select * from cidr_split(a) limit 1) as s from d; + -- operators select ip4 '255.255.255.255' / 32; diff -Nru ip4r-2.3/sql/ip4r-v11.sql ip4r-2.4/sql/ip4r-v11.sql --- ip4r-2.3/sql/ip4r-v11.sql 1970-01-01 00:00:00.000000000 +0000 +++ ip4r-2.4/sql/ip4r-v11.sql 2018-11-21 06:35:30.000000000 +0000 @@ -0,0 +1,41 @@ +-- Tests for pg11+ + +-- RANGE support + +select a4, + array_agg(a4) over (order by a4 range between 268435456 preceding and 268435456 following) + from ipaddrs + where a4 is not null; + +select a4, + array_agg(a4) over (order by a4 range between ip4 '16.0.0.0' preceding and ip4 '16.0.0.0' following) + from ipaddrs + where a4 is not null; + +select a4, + array_agg(a4) over (order by a4 range between -3 preceding and -3 following) + from ipaddrs + where a4 is not null; + +select a6, + array_agg(a6) over (order by a6 range between -10 preceding and -10 following) + from ipaddrs + where a6 is not null; + +select a6, + array_agg(a6) over (order by a6 range between ip6 '0010::' preceding and ip6 '0010::' following) + from ipaddrs + where a6 is not null; + +-- errors +select a4, + array_agg(a4) over (order by a4 range between -33 preceding and -33 following) + from ipaddrs + where a4 is not null; + +select a6, + array_agg(a6) over (order by a6 range between -129 preceding and -129 following) + from ipaddrs + where a6 is not null; + +-- end diff -Nru ip4r-2.3/src/ip4r.c ip4r-2.4/src/ip4r.c --- ip4r-2.3/src/ip4r.c 1970-01-01 00:00:00.000000000 +0000 +++ ip4r-2.4/src/ip4r.c 2018-11-21 06:35:30.000000000 +0000 @@ -0,0 +1,1759 @@ +/* ip4r.c */ + +#include "postgres.h" + +#include +#include + +#include "fmgr.h" +#include "funcapi.h" + +#include "access/gist.h" +#include "access/hash.h" +#include "access/skey.h" +#include "libpq/pqformat.h" +#include "utils/builtins.h" +#include "utils/elog.h" +#include "utils/numeric.h" +#include "utils/palloc.h" +#include "utils/varbit.h" + +#include "ipr_internal.h" +#include "ip4r_funcs.h" + +/* + * extract an IP range from text. + */ +static +bool ip4r_from_str(char *str, IP4R *ipr) +{ + char buf[IP4_STRING_MAX]; + int pos = strcspn(str, "-/"); + IP4 ip; + + switch (str[pos]) + { + case 0: /* no separator, must be single ip4 addr */ + { + if (!ip4_raw_input(str, &ip)) + return false; + ipr->lower = ip; + ipr->upper = ip; + return true; + } + + case '-': /* lower-upper */ + { + char *rest = str + pos + 1; + + if (pos >= sizeof(buf)) + return false; + memcpy(buf, str, pos); + buf[pos] = 0; + if (!ip4_raw_input(buf, &ip)) + return false; + ipr->lower = ip; + if (!ip4_raw_input(rest, &ip)) + return false; + if (!ip4_lessthan(ip, ipr->lower)) + ipr->upper = ip; + else + { + ipr->upper = ipr->lower; + ipr->lower = ip; + } + return true; + } + + case '/': /* prefix/len */ + { + char *rest = str + pos + 1; + unsigned pfxlen; + char dummy; + + if (pos >= sizeof(buf)) + return false; + memcpy(buf, str, pos); + buf[pos] = 0; + if (!ip4_raw_input(buf, &ip)) + return false; + if (rest[strspn(rest,"0123456789")]) + return false; + if (sscanf(rest, "%u%c", &pfxlen, &dummy) != 1) + return false; + return ip4r_from_cidr(ip, pfxlen, ipr); + } + + default: + return false; /* can't happen */ + } +} + + +/* Output an ip range in text form + */ +static inline +int ip4r_to_str(IP4R *ipr, char *str, int slen) +{ + char buf1[IP4_STRING_MAX]; + char buf2[IP4_STRING_MAX]; + unsigned msk; + + if (ip4_equal(ipr->lower, ipr->upper)) + return ip4_raw_output(ipr->lower, str, slen); + + if ((msk = masklen(ipr->lower,ipr->upper)) <= 32) + { + ip4_raw_output(ipr->lower, buf1, sizeof(buf1)); + return snprintf(str, slen, "%s/%u", buf1, msk); + } + + ip4_raw_output(ipr->lower, buf1, sizeof(buf1)); + ip4_raw_output(ipr->upper, buf2, sizeof(buf2)); + + return snprintf(str, slen, "%s-%s", buf1, buf2); +} + + +/**************************************************************************/ +/* This part handles all aspects of postgres interfacing. + */ + +static +text * +make_text(int len) +{ + text *ret = (text *) palloc0(len + VARHDRSZ); + SET_VARSIZE(ret, len + VARHDRSZ); + return ret; +} + +static inline +void +set_text_len(text *txt, int len) +{ + Assert(len + VARHDRSZ <= VARSIZE(txt)); + if (len + VARHDRSZ <= VARSIZE(txt)) + SET_VARSIZE(txt, len + VARHDRSZ); +} + +/* +** Input/Output routines +*/ + +PG_FUNCTION_INFO_V1(ip4_in); +Datum +ip4_in(PG_FUNCTION_ARGS) +{ + char *str = PG_GETARG_CSTRING(0); + IP4 ip; + if (ip4_raw_input(str, &ip)) + PG_RETURN_IP4(ip); + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid IP4 value: '%s'", str))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(ip4_out); +Datum +ip4_out(PG_FUNCTION_ARGS) +{ + IP4 ip = PG_GETARG_IP4(0); + char *out = palloc(IP4_STRING_MAX); + ip4_raw_output(ip, out, IP4_STRING_MAX); + PG_RETURN_CSTRING(out); +} + +PG_FUNCTION_INFO_V1(ip4_recv); +Datum +ip4_recv(PG_FUNCTION_ARGS) +{ + StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); + PG_RETURN_IP4((IP4) pq_getmsgint(buf, sizeof(IP4))); +} + +PG_FUNCTION_INFO_V1(ip4_send); +Datum +ip4_send(PG_FUNCTION_ARGS) +{ + IP4 arg1 = PG_GETARG_IP4(0); + StringInfoData buf; + + pq_begintypsend(&buf); + pq_sendint(&buf, arg1, sizeof(IP4)); + PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); +} + +PG_FUNCTION_INFO_V1(ip4hash); +Datum +ip4hash(PG_FUNCTION_ARGS) +{ + IP4 arg1 = PG_GETARG_IP4(0); + + return hash_any((unsigned char *)&arg1, sizeof(IP4)); +} + +PG_FUNCTION_INFO_V1(ip4_hash_extended); +Datum +ip4_hash_extended(PG_FUNCTION_ARGS) +{ + IP4 arg1 = PG_GETARG_IP4(0); + uint64 seed = DatumGetUInt64(PG_GETARG_DATUM(1)); + + return hash_any_extended((unsigned char *)&arg1, sizeof(IP4), seed); +} + +PG_FUNCTION_INFO_V1(ip4_cast_to_text); +Datum +ip4_cast_to_text(PG_FUNCTION_ARGS) +{ + IP4 ip = PG_GETARG_IP4(0); + text *out = make_text(IP4_STRING_MAX); + set_text_len(out, ip4_raw_output(ip, VARDATA(out), IP4_STRING_MAX)); + PG_RETURN_TEXT_P(out); +} + +PG_FUNCTION_INFO_V1(ip4_cast_from_text); +Datum +ip4_cast_from_text(PG_FUNCTION_ARGS) +{ + text *txt = PG_GETARG_TEXT_PP(0); + int tlen = VARSIZE_ANY_EXHDR(txt); + char buf[IP4_STRING_MAX]; + + if (tlen < sizeof(buf)) + { + IP4 ip; + + memcpy(buf, VARDATA_ANY(txt), tlen); + buf[tlen] = 0; + if (ip4_raw_input(buf, &ip)) + PG_RETURN_IP4(ip); + } + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid IP4 value in text"))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(ip4_cast_from_inet); +Datum +ip4_cast_from_inet(PG_FUNCTION_ARGS) +{ + inet *inetptr = PG_GETARG_INET_P(0); + inet_struct *in = INET_STRUCT_DATA(inetptr); + + if (in->family == PGSQL_AF_INET) + { + unsigned char *p = in->ipaddr; + IP4 ip = (p[0] << 24)|(p[1] << 16)|(p[2] << 8)|p[3]; + PG_RETURN_IP4(ip); + } + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid INET value for conversion to IP4"))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(ip4_cast_to_cidr); +Datum +ip4_cast_to_cidr(PG_FUNCTION_ARGS) +{ + IP4 ip = PG_GETARG_IP4(0); + inet *res = palloc0(VARHDRSZ + sizeof(inet_struct)); + inet_struct *in; + + SET_VARSIZE(res, VARHDRSZ + offsetof(inet_struct, ipaddr) + 4); + + in = ((inet_struct *)VARDATA(res)); + in->bits = 32; + in->family = PGSQL_AF_INET; + { + unsigned char *p = in->ipaddr; + p[0] = (ip >> 24) & 0xff; + p[1] = (ip >> 16) & 0xff; + p[2] = (ip >> 8) & 0xff; + p[3] = (ip ) & 0xff; + } + + PG_RETURN_INET_P(res); +} + +PG_FUNCTION_INFO_V1(ip4_cast_to_bigint); +Datum +ip4_cast_to_bigint(PG_FUNCTION_ARGS) +{ + IP4 ip = PG_GETARG_IP4(0); + PG_RETURN_INT64(ip); +} + +PG_FUNCTION_INFO_V1(ip4_cast_to_numeric); +Datum +ip4_cast_to_numeric(PG_FUNCTION_ARGS) +{ + IP4 ip = PG_GETARG_IP4(0); + int64 v = ip; + PG_RETURN_DATUM(DirectFunctionCall1(int8_numeric, Int64GetDatumFast(v))); +} + +PG_FUNCTION_INFO_V1(ip4_cast_from_bigint); +Datum +ip4_cast_from_bigint(PG_FUNCTION_ARGS) +{ + int64 val = PG_GETARG_INT64(0); + + if (val < -(int64)0x80000000UL || val > (int64)0xFFFFFFFFUL) + ereport(ERROR, + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("ip address out of range"))); + + PG_RETURN_IP4(val); +} + +PG_FUNCTION_INFO_V1(ip4_cast_to_double); +Datum +ip4_cast_to_double(PG_FUNCTION_ARGS) +{ + IP4 ip = PG_GETARG_IP4(0); + PG_RETURN_FLOAT8(ip); +} + +PG_FUNCTION_INFO_V1(ip4_cast_from_double); +Datum +ip4_cast_from_double(PG_FUNCTION_ARGS) +{ + float8 val = PG_GETARG_FLOAT8(0); + float8 ival = 0; + + if (modf(val,&ival) != 0.0) + { + ereport(WARNING, + (errcode(ERRCODE_WARNING), + errmsg("double converted to IP4 is not integral"))); + } + + if (ival < -(float8)0x80000000UL || ival > (float8)0xFFFFFFFFUL) + ereport(ERROR, + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("ip address out of range"))); + + /* + * casting directly to ulong evokes the nasal demons for negative values, + * casting to long first evokes them for large positive values if long is + * 32bit. + */ + if (ival < 0) + PG_RETURN_IP4((unsigned long) (long) ival); + else + PG_RETURN_IP4((unsigned long) ival); +} + +PG_FUNCTION_INFO_V1(ip4_cast_from_numeric); +Datum +ip4_cast_from_numeric(PG_FUNCTION_ARGS) +{ + Datum val_num = PG_GETARG_DATUM(0); + int64 val = DatumGetInt64(DirectFunctionCall1(numeric_int8,val_num)); + + if (val < -(int64)0x80000000UL || val > (int64)0xFFFFFFFFUL) + ereport(ERROR, + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("ip address out of range"))); + + PG_RETURN_IP4((unsigned long) val); +} + +PG_FUNCTION_INFO_V1(ip4_cast_from_bit); +Datum +ip4_cast_from_bit(PG_FUNCTION_ARGS) +{ + VarBit *val = PG_GETARG_VARBIT_P(0); + + if (val->bit_len == 32) + { + bits8 *p = VARBITS(val); + IP4 ip = (p[0] << 24)|(p[1] << 16)|(p[2] << 8)|p[3]; + PG_RETURN_IP4(ip); + } + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid BIT value for conversion to IP4"))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(ip4_cast_to_bit); +Datum +ip4_cast_to_bit(PG_FUNCTION_ARGS) +{ + IP4 ip = PG_GETARG_IP4(0); + int len = VARBITTOTALLEN(32); + VarBit *res = palloc0(len); + unsigned char *p = VARBITS(res); + + SET_VARSIZE(res, len); + VARBITLEN(res) = 32; + + p[0] = (ip >> 24) & 0xff; + p[1] = (ip >> 16) & 0xff; + p[2] = (ip >> 8) & 0xff; + p[3] = (ip ) & 0xff; + + PG_RETURN_VARBIT_P(res); +} + +PG_FUNCTION_INFO_V1(ip4_cast_from_bytea); +Datum +ip4_cast_from_bytea(PG_FUNCTION_ARGS) +{ + void *val = PG_GETARG_BYTEA_PP(0); + + if (VARSIZE_ANY_EXHDR(val) == 4) + { + unsigned char *p = (unsigned char *) VARDATA_ANY(val); + IP4 ip = (p[0] << 24)|(p[1] << 16)|(p[2] << 8)|p[3]; + PG_RETURN_IP4(ip); + } + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid BYTEA value for conversion to IP4"))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(ip4_cast_to_bytea); +Datum +ip4_cast_to_bytea(PG_FUNCTION_ARGS) +{ + IP4 ip = PG_GETARG_IP4(0); + bytea *res = palloc(VARHDRSZ + 4); + unsigned char *p = (unsigned char *) VARDATA(res); + + SET_VARSIZE(res, VARHDRSZ + 4); + + p[0] = (ip >> 24) & 0xff; + p[1] = (ip >> 16) & 0xff; + p[2] = (ip >> 8) & 0xff; + p[3] = (ip ) & 0xff; + + PG_RETURN_BYTEA_P(res); +} + +PG_FUNCTION_INFO_V1(ip4_netmask); +Datum +ip4_netmask(PG_FUNCTION_ARGS) +{ + int pfxlen = PG_GETARG_INT32(0); + + if (pfxlen < 0 || pfxlen > 32) + { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("prefix length out of range"))); + } + + PG_RETURN_IP4( netmask(pfxlen) ); +} + +PG_FUNCTION_INFO_V1(ip4_net_lower); +Datum +ip4_net_lower(PG_FUNCTION_ARGS) +{ + IP4 ip = PG_GETARG_IP4(0); + int pfxlen = PG_GETARG_INT32(1); + + if (pfxlen < 0 || pfxlen > 32) + { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("prefix length out of range"))); + } + + PG_RETURN_IP4( ip & netmask(pfxlen) ); +} + +PG_FUNCTION_INFO_V1(ip4_net_upper); +Datum +ip4_net_upper(PG_FUNCTION_ARGS) +{ + IP4 ip = PG_GETARG_IP4(0); + int pfxlen = PG_GETARG_INT32(1); + + if (pfxlen < 0 || pfxlen > 32) + { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("prefix length out of range"))); + } + + PG_RETURN_IP4( ip | hostmask(pfxlen) ); +} + +PG_FUNCTION_INFO_V1(ip4_plus_int); +Datum +ip4_plus_int(PG_FUNCTION_ARGS) +{ + IP4 ip = PG_GETARG_IP4(0); + int addend = PG_GETARG_INT32(1); + IP4 result = ip + (IP4) addend; + + if ((addend < 0) != (result < ip)) + { + ereport(ERROR, + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("ip address out of range"))); + } + + PG_RETURN_IP4(result); +} + +PG_FUNCTION_INFO_V1(ip4_plus_bigint); +Datum +ip4_plus_bigint(PG_FUNCTION_ARGS) +{ + IP4 ip = PG_GETARG_IP4(0); + int64 addend = PG_GETARG_INT64(1); + int64 result = (int64) ip + addend; + + if (((addend < 0) != (result < ip)) + || result != (int64)(IP4)result) + { + ereport(ERROR, + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("ip address out of range"))); + } + + PG_RETURN_IP4( (IP4)(result) ); +} + +PG_FUNCTION_INFO_V1(ip4_plus_numeric); +Datum +ip4_plus_numeric(PG_FUNCTION_ARGS) +{ + IP4 ip = PG_GETARG_IP4(0); + Datum addend_num = PG_GETARG_DATUM(1); + int64 addend = DatumGetInt64(DirectFunctionCall1(numeric_int8,addend_num)); + int64 result = (int64) ip + addend; + + if (((addend < 0) != (result < ip)) + || result != (int64)(IP4)result) + { + ereport(ERROR, + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("ip address out of range"))); + } + + PG_RETURN_IP4( (IP4)(result) ); +} + +PG_FUNCTION_INFO_V1(ip4_minus_int); +Datum +ip4_minus_int(PG_FUNCTION_ARGS) +{ + IP4 ip = PG_GETARG_IP4(0); + int subtrahend = PG_GETARG_INT32(1); + IP4 result = ip - (IP4) subtrahend; + + if ((subtrahend > 0) != (result < ip)) + { + ereport(ERROR, + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("ip address out of range"))); + } + + PG_RETURN_IP4(result); +} + +PG_FUNCTION_INFO_V1(ip4_minus_bigint); +Datum +ip4_minus_bigint(PG_FUNCTION_ARGS) +{ + IP4 ip = PG_GETARG_IP4(0); + int64 subtrahend = PG_GETARG_INT64(1); + int64 result = (int64) ip - subtrahend; + + if (((subtrahend > 0) != (result < ip)) + || result != (int64)(IP4)result) + { + ereport(ERROR, + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("ip address out of range"))); + } + + PG_RETURN_IP4( (IP4)(result) ); +} + +PG_FUNCTION_INFO_V1(ip4_minus_numeric); +Datum +ip4_minus_numeric(PG_FUNCTION_ARGS) +{ + IP4 ip = PG_GETARG_IP4(0); + Datum subtrahend_num = PG_GETARG_DATUM(1); + int64 subtrahend = DatumGetInt64(DirectFunctionCall1(numeric_int8,subtrahend_num)); + int64 result = (int64) ip - subtrahend; + + if (((subtrahend > 0) != (result < ip)) + || result != (int64)(IP4)result) + { + ereport(ERROR, + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("ip address out of range"))); + } + + PG_RETURN_IP4( (IP4)(result) ); +} + +PG_FUNCTION_INFO_V1(ip4_minus_ip4); +Datum +ip4_minus_ip4(PG_FUNCTION_ARGS) +{ + IP4 minuend = PG_GETARG_IP4(0); + IP4 subtrahend = PG_GETARG_IP4(1); + int64 result = (int64) minuend - (int64) subtrahend; + + PG_RETURN_INT64(result); +} + +PG_FUNCTION_INFO_V1(ip4_and); +Datum +ip4_and(PG_FUNCTION_ARGS) +{ + IP4 a = PG_GETARG_IP4(0); + IP4 b = PG_GETARG_IP4(1); + + PG_RETURN_IP4(a & b); +} + +PG_FUNCTION_INFO_V1(ip4_or); +Datum +ip4_or(PG_FUNCTION_ARGS) +{ + IP4 a = PG_GETARG_IP4(0); + IP4 b = PG_GETARG_IP4(1); + + PG_RETURN_IP4(a | b); +} + +PG_FUNCTION_INFO_V1(ip4_xor); +Datum +ip4_xor(PG_FUNCTION_ARGS) +{ + IP4 a = PG_GETARG_IP4(0); + IP4 b = PG_GETARG_IP4(1); + + PG_RETURN_IP4(a ^ b); +} + +PG_FUNCTION_INFO_V1(ip4_not); +Datum +ip4_not(PG_FUNCTION_ARGS) +{ + IP4 a = PG_GETARG_IP4(0); + + PG_RETURN_IP4(~a); +} + + +/*---- ip4r ----*/ + +PG_FUNCTION_INFO_V1(ip4r_in); +Datum +ip4r_in(PG_FUNCTION_ARGS) +{ + char *str = PG_GETARG_CSTRING(0); + IP4R ipr; + if (ip4r_from_str(str, &ipr)) + { + IP4R *res = palloc(sizeof(IP4R)); + *res = ipr; + PG_RETURN_IP4R_P(res); + } + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid IP4R value: \"%s\"", str))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(ip4r_out); +Datum +ip4r_out(PG_FUNCTION_ARGS) +{ + IP4R *ipr = PG_GETARG_IP4R_P(0); + char *out = palloc(IP4R_STRING_MAX); + ip4r_to_str(ipr, out, IP4R_STRING_MAX); + PG_RETURN_CSTRING(out); +} + +PG_FUNCTION_INFO_V1(ip4r_recv); +Datum +ip4r_recv(PG_FUNCTION_ARGS) +{ + StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); + IP4R *ipr = palloc(sizeof(IP4R)); + + ipr->lower = (IP4) pq_getmsgint(buf, sizeof(IP4)); + ipr->upper = (IP4) pq_getmsgint(buf, sizeof(IP4)); + + PG_RETURN_IP4R_P(ipr); +} + +PG_FUNCTION_INFO_V1(ip4r_send); +Datum +ip4r_send(PG_FUNCTION_ARGS) +{ + IP4R *ipr = PG_GETARG_IP4R_P(0); + StringInfoData buf; + + pq_begintypsend(&buf); + pq_sendint(&buf, ipr->lower, sizeof(IP4)); + pq_sendint(&buf, ipr->upper, sizeof(IP4)); + PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); +} + +PG_FUNCTION_INFO_V1(ip4rhash); +Datum +ip4rhash(PG_FUNCTION_ARGS) +{ + IP4R *arg1 = PG_GETARG_IP4R_P(0); + + return hash_any((unsigned char *)arg1, sizeof(IP4R)); +} + +PG_FUNCTION_INFO_V1(ip4r_hash_extended); +Datum +ip4r_hash_extended(PG_FUNCTION_ARGS) +{ + IP4R *arg1 = PG_GETARG_IP4R_P(0); + uint64 seed = DatumGetUInt64(PG_GETARG_DATUM(1)); + + return hash_any_extended((unsigned char *)arg1, sizeof(IP4R), seed); +} + +PG_FUNCTION_INFO_V1(ip4r_cast_to_text); +Datum +ip4r_cast_to_text(PG_FUNCTION_ARGS) +{ + IP4R *ipr = PG_GETARG_IP4R_P(0); + text *out = make_text(IP4R_STRING_MAX); + set_text_len(out, ip4r_to_str(ipr, VARDATA(out), IP4R_STRING_MAX)); + PG_RETURN_TEXT_P(out); +} + +PG_FUNCTION_INFO_V1(ip4r_cast_from_text); +Datum +ip4r_cast_from_text(PG_FUNCTION_ARGS) +{ + text *txt = PG_GETARG_TEXT_PP(0); + int tlen = VARSIZE_ANY_EXHDR(txt); + char buf[IP4R_STRING_MAX]; + + if (tlen < sizeof(buf)) + { + IP4R ipr; + + memcpy(buf, VARDATA_ANY(txt), tlen); + buf[tlen] = 0; + if (ip4r_from_str(buf, &ipr)) + { + IP4R *res = palloc(sizeof(IP4R)); + *res = ipr; + PG_RETURN_IP4R_P(res); + } + } + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid IP4R value in text"))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(ip4r_cast_from_cidr); +Datum +ip4r_cast_from_cidr(PG_FUNCTION_ARGS) +{ + inet *inetptr = PG_GETARG_INET_P(0); + inet_struct *in = INET_STRUCT_DATA(inetptr); + + if (in->family == PGSQL_AF_INET) + { + unsigned char *p = in->ipaddr; + IP4 ip = (p[0] << 24)|(p[1] << 16)|(p[2] << 8)|p[3]; + IP4R ipr; + if (ip4r_from_cidr(ip, in->bits, &ipr)) + { + IP4R *res = palloc(sizeof(IP4R)); + *res = ipr; + PG_RETURN_IP4R_P(res); + } + } + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid CIDR value for conversion to IP4R"))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(ip4r_cast_to_cidr); +Datum +ip4r_cast_to_cidr(PG_FUNCTION_ARGS) +{ + IP4R *ipr = PG_GETARG_IP4R_P(0); + IP4 ip = ipr->lower; + inet *res; + inet_struct *in; + unsigned bits = masklen(ip, ipr->upper); + + if (bits > 32) + PG_RETURN_NULL(); + + res = palloc0(VARHDRSZ + sizeof(inet_struct)); + SET_VARSIZE(res, VARHDRSZ + offsetof(inet_struct, ipaddr) + 4); + + in = ((inet_struct *)VARDATA(res)); + in->bits = bits; + in->family = PGSQL_AF_INET; + { + unsigned char *p = in->ipaddr; + p[0] = (ip >> 24) & 0xff; + p[1] = (ip >> 16) & 0xff; + p[2] = (ip >> 8) & 0xff; + p[3] = (ip ) & 0xff; + } + + PG_RETURN_INET_P(res); +} + +PG_FUNCTION_INFO_V1(ip4r_cast_from_ip4); +Datum +ip4r_cast_from_ip4(PG_FUNCTION_ARGS) +{ + IP4 ip = PG_GETARG_IP4(0); + IP4R *res = palloc(sizeof(IP4R)); + if (ip4r_from_inet(ip, 32, res)) + { + PG_RETURN_IP4R_P(res); + } + + pfree(res); + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid IP4 value for conversion to IP4R (shouldn't be possible)"))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(ip4r_from_ip4s); +Datum +ip4r_from_ip4s(PG_FUNCTION_ARGS) +{ + IP4 a = PG_GETARG_IP4(0); + IP4 b = PG_GETARG_IP4(1); + IP4R *res = palloc(sizeof(IP4R)); + if (a < b) + res->lower = a, res->upper = b; + else + res->lower = b, res->upper = a; + PG_RETURN_IP4R_P( res ); +} + +PG_FUNCTION_INFO_V1(ip4r_cast_from_bit); +Datum +ip4r_cast_from_bit(PG_FUNCTION_ARGS) +{ + VarBit *val = PG_GETARG_VARBIT_P(0); + int bitlen = VARBITLEN(val); + + if (bitlen <= 32) + { + bits8 buf[4]; + bits8 *p = VARBITS(val); + IP4 ip; + IP4R *res = palloc(sizeof(IP4R)); + + if (bitlen <= 24) + { + memset(buf, 0, sizeof(buf)); + memcpy(buf, p, VARBITBYTES(val)); + p = buf; + } + + ip = (p[0] << 24)|(p[1] << 16)|(p[2] << 8)|p[3]; + + if (ip4r_from_cidr(ip, bitlen, res)) + PG_RETURN_IP4R_P(res); + } + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid BIT value for conversion to IP4R"))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(ip4r_cast_to_bit); +Datum +ip4r_cast_to_bit(PG_FUNCTION_ARGS) +{ + IP4R *ipr = PG_GETARG_IP4R_P(0); + IP4 ip = ipr->lower; + unsigned bits = masklen(ip, ipr->upper); + VarBit *res; + unsigned char buf[4]; + int len; + + if (bits > 32) + PG_RETURN_NULL(); + + len = VARBITTOTALLEN(bits); + res = palloc0(len); + SET_VARSIZE(res, len); + VARBITLEN(res) = bits; + + buf[0] = (ip >> 24) & 0xff; + buf[1] = (ip >> 16) & 0xff; + buf[2] = (ip >> 8) & 0xff; + buf[3] = (ip ) & 0xff; + + memcpy(VARBITS(res), buf, VARBITBYTES(res)); + PG_RETURN_VARBIT_P(res); +} + +PG_FUNCTION_INFO_V1(ip4r_net_prefix); +Datum +ip4r_net_prefix(PG_FUNCTION_ARGS) +{ + IP4 ip = PG_GETARG_IP4(0); + int pfxlen = PG_GETARG_INT32(1); + + if (pfxlen < 0 || pfxlen > 32) + { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("prefix length out of range"))); + } + + { + IP4 mask = netmask(pfxlen); + IP4R *res = palloc(sizeof(IP4R)); + + res->lower = ip & mask; + res->upper = ip | ~mask; + + PG_RETURN_IP4R_P(res); + } +} + +PG_FUNCTION_INFO_V1(ip4r_net_mask); +Datum +ip4r_net_mask(PG_FUNCTION_ARGS) +{ + IP4 ip = PG_GETARG_IP4(0); + IP4 mask = PG_GETARG_IP4(1); + + if (!ip4_valid_netmask(mask)) + { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid netmask"))); + } + + { + IP4R *res = palloc(sizeof(IP4R)); + + res->lower = ip & mask; + res->upper = ip | ~mask; + + PG_RETURN_IP4R_P(res); + } +} + +PG_FUNCTION_INFO_V1(ip4r_lower); +Datum +ip4r_lower(PG_FUNCTION_ARGS) +{ + IP4R *ipr = PG_GETARG_IP4R_P(0); + PG_RETURN_IP4( ipr->lower ); +} + +PG_FUNCTION_INFO_V1(ip4r_upper); +Datum +ip4r_upper(PG_FUNCTION_ARGS) +{ + IP4R *ipr = PG_GETARG_IP4R_P(0); + PG_RETURN_IP4( ipr->upper ); +} + +PG_FUNCTION_INFO_V1(ip4r_is_cidr); +Datum +ip4r_is_cidr(PG_FUNCTION_ARGS) +{ + IP4R *ipr = PG_GETARG_IP4R_P(0); + PG_RETURN_BOOL( (masklen(ipr->lower,ipr->upper) <= 32U) ); +} + +/* + * Decompose an arbitrary range into CIDRs + */ + +PG_FUNCTION_INFO_V1(ip4r_cidr_split); +Datum +ip4r_cidr_split(PG_FUNCTION_ARGS) +{ + FuncCallContext *funcctx; + IP4R *val; + IP4R *res; + + if (SRF_IS_FIRSTCALL()) + { + IP4R *in = PG_GETARG_IP4R_P(0); + funcctx = SRF_FIRSTCALL_INIT(); + val = MemoryContextAlloc(funcctx->multi_call_memory_ctx, + sizeof(IP4R)); + *val = *in; + funcctx->user_fctx = val; + } + + funcctx = SRF_PERCALL_SETUP(); + val = funcctx->user_fctx; + if (!val) + SRF_RETURN_DONE(funcctx); + + res = palloc(sizeof(IP4R)); + if (ip4r_split_cidr(val, res)) + funcctx->user_fctx = NULL; + + SRF_RETURN_NEXT(funcctx, IP4RPGetDatum(res)); +} + +/* + * comparisons and indexing + */ + +PG_FUNCTION_INFO_V1(ip4_lt); +Datum +ip4_lt(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip4_lessthan(PG_GETARG_IP4(0), PG_GETARG_IP4(1)) ); +} + +PG_FUNCTION_INFO_V1(ip4_le); +Datum +ip4_le(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip4_less_eq(PG_GETARG_IP4(0), PG_GETARG_IP4(1)) ); +} + +PG_FUNCTION_INFO_V1(ip4_gt); +Datum +ip4_gt(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip4_lessthan(PG_GETARG_IP4(1), PG_GETARG_IP4(0)) ); +} + +PG_FUNCTION_INFO_V1(ip4_ge); +Datum +ip4_ge(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip4_less_eq(PG_GETARG_IP4(1), PG_GETARG_IP4(0)) ); +} + +PG_FUNCTION_INFO_V1(ip4_eq); +Datum +ip4_eq(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip4_equal(PG_GETARG_IP4(0), PG_GETARG_IP4(1)) ); +} + +PG_FUNCTION_INFO_V1(ip4_neq); +Datum +ip4_neq(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( !ip4_equal(PG_GETARG_IP4(0), PG_GETARG_IP4(1)) ); +} + +PG_FUNCTION_INFO_V1(ip4r_lt); +Datum +ip4r_lt(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip4r_lessthan(PG_GETARG_IP4R_P(0), PG_GETARG_IP4R_P(1)) ); +} + +PG_FUNCTION_INFO_V1(ip4r_le); +Datum +ip4r_le(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip4r_less_eq(PG_GETARG_IP4R_P(0), PG_GETARG_IP4R_P(1)) ); +} + +PG_FUNCTION_INFO_V1(ip4r_gt); +Datum +ip4r_gt(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip4r_lessthan(PG_GETARG_IP4R_P(1), PG_GETARG_IP4R_P(0)) ); +} + +PG_FUNCTION_INFO_V1(ip4r_ge); +Datum +ip4r_ge(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip4r_less_eq(PG_GETARG_IP4R_P(1), PG_GETARG_IP4R_P(0)) ); +} + +PG_FUNCTION_INFO_V1(ip4r_eq); +Datum +ip4r_eq(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip4r_equal(PG_GETARG_IP4R_P(0), PG_GETARG_IP4R_P(1)) ); +} + +PG_FUNCTION_INFO_V1(ip4r_neq); +Datum +ip4r_neq(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( !ip4r_equal(PG_GETARG_IP4R_P(0), PG_GETARG_IP4R_P(1)) ); +} + +PG_FUNCTION_INFO_V1(ip4r_overlaps); +Datum +ip4r_overlaps(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip4r_overlaps_internal(PG_GETARG_IP4R_P(0), + PG_GETARG_IP4R_P(1)) ); +} + +PG_FUNCTION_INFO_V1(ip4r_contains); +Datum +ip4r_contains(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip4r_contains_internal(PG_GETARG_IP4R_P(0), + PG_GETARG_IP4R_P(1), + true) ); +} + +PG_FUNCTION_INFO_V1(ip4r_contains_strict); +Datum +ip4r_contains_strict(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip4r_contains_internal(PG_GETARG_IP4R_P(0), + PG_GETARG_IP4R_P(1), + false) ); +} + +PG_FUNCTION_INFO_V1(ip4r_contained_by); +Datum +ip4r_contained_by(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip4r_contains_internal(PG_GETARG_IP4R_P(1), + PG_GETARG_IP4R_P(0), + true) ); +} + +PG_FUNCTION_INFO_V1(ip4r_contained_by_strict); +Datum +ip4r_contained_by_strict(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip4r_contains_internal(PG_GETARG_IP4R_P(1), + PG_GETARG_IP4R_P(0), + false) ); +} + +PG_FUNCTION_INFO_V1(ip4_contains); +Datum +ip4_contains(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip4_contains_internal(PG_GETARG_IP4R_P(0), PG_GETARG_IP4(1)) ); +} + +PG_FUNCTION_INFO_V1(ip4_contained_by); +Datum +ip4_contained_by(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip4_contains_internal(PG_GETARG_IP4R_P(1), PG_GETARG_IP4(0)) ); +} + +PG_FUNCTION_INFO_V1(ip4r_left_of); +Datum +ip4r_left_of(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip4r_left_internal(PG_GETARG_IP4R_P(0), PG_GETARG_IP4R_P(1)) ); +} + +PG_FUNCTION_INFO_V1(ip4r_right_of); +Datum +ip4r_right_of(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip4r_left_internal(PG_GETARG_IP4R_P(1), PG_GETARG_IP4R_P(0)) ); +} + + +PG_FUNCTION_INFO_V1(ip4r_union); +Datum +ip4r_union(PG_FUNCTION_ARGS) +{ + IP4R *res = (IP4R *) palloc(sizeof(IP4R)); + ip4r_union_internal(PG_GETARG_IP4R_P(0), PG_GETARG_IP4R_P(1), res); + PG_RETURN_IP4R_P(res); +} + +PG_FUNCTION_INFO_V1(ip4r_inter); +Datum +ip4r_inter(PG_FUNCTION_ARGS) +{ + IP4R *res = (IP4R *) palloc(sizeof(IP4R)); + if (ip4r_inter_internal(PG_GETARG_IP4R_P(0), PG_GETARG_IP4R_P(1), res)) + { + PG_RETURN_IP4R_P(res); + } + pfree(res); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(ip4r_size); +Datum +ip4r_size(PG_FUNCTION_ARGS) +{ + double size = ip4r_metric(PG_GETARG_IP4R_P(0)); + PG_RETURN_FLOAT8(size); +} + +PG_FUNCTION_INFO_V1(ip4r_size_exact); +Datum +ip4r_size_exact(PG_FUNCTION_ARGS) +{ + int64 size = (int64) ip4r_metric(PG_GETARG_IP4R_P(0)); + PG_RETURN_DATUM(DirectFunctionCall1(int8_numeric, Int64GetDatumFast(size))); +} + +PG_FUNCTION_INFO_V1(ip4r_prefixlen); +Datum +ip4r_prefixlen(PG_FUNCTION_ARGS) +{ + IP4R *ipr = PG_GETARG_IP4R_P(0); + unsigned len = masklen(ipr->lower, ipr->upper); + if (len <= 32) + PG_RETURN_INT32((int32) len); + PG_RETURN_NULL(); +} + + +/***************************************************************************** + * Btree functions + *****************************************************************************/ + +PG_FUNCTION_INFO_V1(ip4r_cmp); +Datum +ip4r_cmp(PG_FUNCTION_ARGS) +{ + IP4R *a = PG_GETARG_IP4R_P(0); + IP4R *b = PG_GETARG_IP4R_P(1); + if (ip4r_lessthan(a,b)) + PG_RETURN_INT32(-1); + if (ip4r_equal(a,b)) + PG_RETURN_INT32(0); + PG_RETURN_INT32(1); +} + +PG_FUNCTION_INFO_V1(ip4_cmp); +Datum +ip4_cmp(PG_FUNCTION_ARGS) +{ + IP4 a = PG_GETARG_IP4(0); + IP4 b = PG_GETARG_IP4(1); + if (ip4_lessthan(a,b)) + PG_RETURN_INT32(-1); + if (ip4_equal(a,b)) + PG_RETURN_INT32(0); + PG_RETURN_INT32(1); +} + +/* + * in_range(val ip4,base ip4,offset bigint,sub bool,less bool) + * returns val CMP (base OP offset) + * where CMP is <= if less, >= otherwise + * and OP is - if sub, + otherwise + * We treat negative values of offset as special: they indicate + * the (negation of) a cidr prefix length + */ +PG_FUNCTION_INFO_V1(ip4_in_range_bigint); +Datum +ip4_in_range_bigint(PG_FUNCTION_ARGS) +{ + IP4 val = PG_GETARG_IP4(0); + IP4 base = PG_GETARG_IP4(1); + int64 offset = PG_GETARG_INT64(2); + bool sub = PG_GETARG_BOOL(3); + bool less = PG_GETARG_BOOL(4); + + if (offset >= INT64CONST(0x100000000) || offset < -32) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE), + errmsg("invalid preceding or following size in window function"), + errdetail("Offset value " INT64_FORMAT " is outside the range -32 to 4294967295", offset))); + + if (offset < 0) + { + int bits = -offset; + if (sub) + base &= netmask(bits); + else + base |= hostmask(bits); + if (less) + PG_RETURN_BOOL(val <= base); + else + PG_RETURN_BOOL(val >= base); + } + else + { + /* + * val CMP (base OP offset) is equivalent to + * val - base CMP (OP offset), which avoids overflow. + */ + int64 delta = (int64)val - (int64)base; + if (sub) + offset = -offset; + if (less) + PG_RETURN_BOOL(delta <= offset); + else + PG_RETURN_BOOL(delta >= offset); + } +} + +PG_FUNCTION_INFO_V1(ip4_in_range_ip4); +Datum +ip4_in_range_ip4(PG_FUNCTION_ARGS) +{ + IP4 val = PG_GETARG_IP4(0); + IP4 base = PG_GETARG_IP4(1); + IP4 offset = PG_GETARG_IP4(2); + bool sub = PG_GETARG_BOOL(3); + bool less = PG_GETARG_BOOL(4); + + /* + * val CMP (base OP offset) is equivalent to + * val - base CMP (OP offset), which avoids overflow. + */ + int64 delta = (int64)val - (int64)base; + int64 offs = (int64)offset; + if (sub) + offs = -offs; + if (less) + PG_RETURN_BOOL(delta <= offs); + else + PG_RETURN_BOOL(delta >= offs); +} + + +/***************************************************************************** + * GiST functions + *****************************************************************************/ + +/* +** GiST support methods +*/ + +Datum gip4r_consistent(PG_FUNCTION_ARGS); +Datum gip4r_compress(PG_FUNCTION_ARGS); +Datum gip4r_decompress(PG_FUNCTION_ARGS); +Datum gip4r_penalty(PG_FUNCTION_ARGS); +Datum gip4r_picksplit(PG_FUNCTION_ARGS); +Datum gip4r_union(PG_FUNCTION_ARGS); +Datum gip4r_same(PG_FUNCTION_ARGS); +Datum gip4r_fetch(PG_FUNCTION_ARGS); + +static bool gip4r_leaf_consistent(IP4R * key, IP4R * query, StrategyNumber strategy); +static bool gip4r_internal_consistent(IP4R * key, IP4R * query, StrategyNumber strategy); + +/* +** The GiST Consistent method for IP ranges +** Should return false if for all data items x below entry, +** the predicate x op query == false, where op is the oper +** corresponding to strategy in the pg_amop table. +*/ +PG_FUNCTION_INFO_V1(gip4r_consistent); +Datum +gip4r_consistent(PG_FUNCTION_ARGS) +{ + GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); + IP4R *query = (IP4R *) PG_GETARG_POINTER(1); + StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); + bool *recheck = (bool *) PG_GETARG_POINTER(4); + IP4R *key = (IP4R *) DatumGetPointer(entry->key); + bool retval; + + /* recheck is never needed with this type */ + if (recheck) + *recheck = false; + + /* + * * if entry is not leaf, use gip4r_internal_consistent, * else use + * gip4r_leaf_consistent + */ + if (GIST_LEAF(entry)) + retval = gip4r_leaf_consistent(key, query, strategy); + else + retval = gip4r_internal_consistent(key, query, strategy); + + PG_RETURN_BOOL(retval); +} + +/* +** The GiST Union method for IP ranges +** returns the minimal bounding IP4R that encloses all the entries in entryvec +*/ +PG_FUNCTION_INFO_V1(gip4r_union); +Datum +gip4r_union(PG_FUNCTION_ARGS) +{ + GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0); + int *sizep = (int *) PG_GETARG_POINTER(1); + GISTENTRY *ent = GISTENTRYVEC(entryvec); + + int numranges, i; + IP4R *out = (IP4R *) palloc(sizeof(IP4R)); + IP4R *tmp; + +#ifdef GIST_DEBUG + fprintf(stderr, "union\n"); +#endif + + numranges = GISTENTRYCOUNT(entryvec); + tmp = (IP4R *) DatumGetPointer(ent[0].key); + *sizep = sizeof(IP4R); + *out = *tmp; + + for (i = 1; i < numranges; i++) + { + tmp = (IP4R *) DatumGetPointer(ent[i].key); + if (tmp->lower < out->lower) + out->lower = tmp->lower; + if (tmp->upper > out->upper) + out->upper = tmp->upper; + } + + PG_RETURN_IP4R_P(out); +} + +/* +** GiST Compress and Decompress methods for IP ranges +** do not do anything. +*/ +PG_FUNCTION_INFO_V1(gip4r_compress); +Datum +gip4r_compress(PG_FUNCTION_ARGS) +{ + PG_RETURN_POINTER(PG_GETARG_POINTER(0)); +} + +PG_FUNCTION_INFO_V1(gip4r_decompress); +Datum +gip4r_decompress(PG_FUNCTION_ARGS) +{ + PG_RETURN_POINTER(PG_GETARG_POINTER(0)); +} + +PG_FUNCTION_INFO_V1(gip4r_fetch); +Datum +gip4r_fetch(PG_FUNCTION_ARGS) +{ + PG_RETURN_POINTER(PG_GETARG_POINTER(0)); +} + +/* +** The GiST Penalty method for IP ranges +** As in the R-tree paper, we use change in area as our penalty metric +*/ +PG_FUNCTION_INFO_V1(gip4r_penalty); +Datum +gip4r_penalty(PG_FUNCTION_ARGS) +{ + GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0); + GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1); + float *result = (float *) PG_GETARG_POINTER(2); + IP4R *key; + IP4R ud; + float tmp1, tmp2; + + key = (IP4R *) DatumGetPointer(origentry->key); + ud = *key; + tmp2 = ip4r_metric(&ud); + + key = (IP4R *) DatumGetPointer(newentry->key); + if (key->lower < ud.lower) + ud.lower = key->lower; + if (key->upper > ud.upper) + ud.upper = key->upper; + tmp1 = ip4r_metric(&ud); + + *result = tmp1 - tmp2; + +#ifdef GIST_DEBUG + fprintf(stderr, "penalty\n"); + fprintf(stderr, "\t%g\n", *result); +#endif + + PG_RETURN_POINTER(result); +} + + +/* Helper functions for picksplit. We might need to sort a list of + * ranges by size; these are for that. + */ + +struct gip4r_sort +{ + IP4R *key; + OffsetNumber pos; +}; + +static int +gip4r_sort_compare(const void *a, const void *b) +{ + double sa = ip4r_metric(((struct gip4r_sort *)a)->key); + double sb = ip4r_metric(((struct gip4r_sort *)b)->key); + return (sa > sb) ? 1 : ((sa == sb) ? 0 : -1); +} + +/* +** The GiST PickSplit method for IP ranges +** This is a linear-time algorithm based on a left/right split, +** based on the box functions in rtree_gist simplified to one +** dimension +*/ +PG_FUNCTION_INFO_V1(gip4r_picksplit); +Datum +gip4r_picksplit(PG_FUNCTION_ARGS) +{ + GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0); + GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1); + GISTENTRY *ent = GISTENTRYVEC(entryvec); + OffsetNumber i; + int nbytes; + OffsetNumber maxoff; + OffsetNumber *listL; + OffsetNumber *listR; + bool allisequal = true; + IP4R pageunion; + IP4R *cur; + IP4R *unionL; + IP4R *unionR; + int posL = 0; + int posR = 0; + + posL = posR = 0; + maxoff = GISTENTRYCOUNT(entryvec) - 1; + + cur = (IP4R *) DatumGetPointer(ent[FirstOffsetNumber].key); + pageunion = *cur; + + /* find MBR */ + for (i = OffsetNumberNext(FirstOffsetNumber); i <= maxoff; i = OffsetNumberNext(i)) + { + cur = (IP4R *) DatumGetPointer(ent[i].key); + if (allisequal == true + && (pageunion.lower != cur->lower || pageunion.upper != cur->upper)) + allisequal = false; + + if (cur->lower < pageunion.lower) + pageunion.lower = cur->lower; + if (cur->upper > pageunion.upper) + pageunion.upper = cur->upper; + } + + nbytes = (maxoff + 2) * sizeof(OffsetNumber); + listL = (OffsetNumber *) palloc(nbytes); + listR = (OffsetNumber *) palloc(nbytes); + unionL = (IP4R *) palloc(sizeof(IP4R)); + unionR = (IP4R *) palloc(sizeof(IP4R)); + v->spl_ldatum = PointerGetDatum(unionL); + v->spl_rdatum = PointerGetDatum(unionR); + v->spl_left = listL; + v->spl_right = listR; + + if (allisequal) + { + cur = (IP4R *) DatumGetPointer(ent[OffsetNumberNext(FirstOffsetNumber)].key); + if (ip4r_equal(cur, &pageunion)) + { + OffsetNumber split_at = FirstOffsetNumber + (maxoff - FirstOffsetNumber + 1)/2; + v->spl_nleft = v->spl_nright = 0; + *unionL = pageunion; + *unionR = pageunion; + + for (i = FirstOffsetNumber; i < split_at; i = OffsetNumberNext(i)) + v->spl_left[v->spl_nleft++] = i; + for (; i <= maxoff; i = OffsetNumberNext(i)) + v->spl_right[v->spl_nright++] = i; + + PG_RETURN_POINTER(v); + } + } + +#define ADDLIST( list_, u_, pos_, num_ ) do { \ + if ( pos_ ) { \ + if ( (u_)->upper < (cur)->upper ) (u_)->upper = (cur)->upper; \ + if ( (u_)->lower > (cur)->lower ) (u_)->lower = (cur)->lower; \ + } else { \ + *(u_) = *(cur); \ + } \ + (list_)[(pos_)++] = (num_); \ +} while(0) + + for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) + { + cur = (IP4R *) DatumGetPointer(ent[i].key); + if (cur->lower - pageunion.lower < pageunion.upper - cur->upper) + ADDLIST(listL, unionL, posL, i); + else + ADDLIST(listR, unionR, posR, i); + } + + /* bad disposition, sort by ascending size and resplit */ + if (posR == 0 || posL == 0) + { + struct gip4r_sort *arr = (struct gip4r_sort *) + palloc(sizeof(struct gip4r_sort) * (maxoff + FirstOffsetNumber)); + + for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) + { + arr[i].key = (IP4R *) DatumGetPointer(ent[i].key); + arr[i].pos = i; + } + + qsort(arr + FirstOffsetNumber, + maxoff - FirstOffsetNumber + 1, + sizeof(struct gip4r_sort), + gip4r_sort_compare); + + posL = posR = 0; + for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) + { + cur = arr[i].key; + if (cur->lower - pageunion.lower < pageunion.upper - cur->upper) + ADDLIST(listL, unionL, posL, arr[i].pos); + else if (cur->lower - pageunion.lower == pageunion.upper - cur->upper) + { + if (posL > posR) + ADDLIST(listR, unionR, posR, arr[i].pos); + else + ADDLIST(listL, unionL, posL, arr[i].pos); + } + else + ADDLIST(listR, unionR, posR, arr[i].pos); + } + pfree(arr); + } + + v->spl_nleft = posL; + v->spl_nright = posR; + + PG_RETURN_POINTER(v); +} + +#undef ADDLIST + +/* +** Equality methods +*/ +PG_FUNCTION_INFO_V1(gip4r_same); +Datum +gip4r_same(PG_FUNCTION_ARGS) +{ + IP4R *v1 = (IP4R *) PG_GETARG_POINTER(0); + IP4R *v2 = (IP4R *) PG_GETARG_POINTER(1); + bool *result = (bool *) PG_GETARG_POINTER(2); + + if (v1 && v2) + *result = ip4r_equal(v1,v2); + else + *result = (v1 == NULL && v2 == NULL); + +#ifdef GIST_DEBUG + fprintf(stderr, "same: %s\n", (*result ? "true" : "false")); +#endif + + PG_RETURN_POINTER(result); +} + + +/* + * Strategy numbers: + * OPERATOR 1 >>= , + * OPERATOR 2 <<= , + * OPERATOR 3 >> , + * OPERATOR 4 << , + * OPERATOR 5 && , + * OPERATOR 6 = , + */ + +/* +** SUPPORT ROUTINES +*/ +static bool +gip4r_leaf_consistent(IP4R * key, + IP4R * query, + StrategyNumber strategy) +{ +#ifdef GIST_QUERY_DEBUG + fprintf(stderr, "leaf_consistent, %d\n", strategy); +#endif + + switch (strategy) + { + case 1: /* left contains right nonstrict */ + return ip4r_contains_internal(key, query, true); + case 2: /* left contained in right nonstrict */ + return ip4r_contains_internal(query, key, true); + case 3: /* left contains right strict */ + return ip4r_contains_internal(key, query, false); + case 4: /* left contained in right strict */ + return ip4r_contains_internal(query, key, false); + case 5: /* left overlaps right */ + return ip4r_overlaps_internal(key, query); + case 6: /* left equal right */ + return ip4r_equal(key, query); + default: + return false; + } +} + +/* logic notes: + * If the union value we're looking at overlaps with our query value + * at all, then any of the values underneath it might overlap with us + * or be contained by us, so all the "contained by" and "overlaps" + * cases degenerate to "overlap". + * If the union value is equal to the query value, then none of the + * values under it can strictly contain the query value, so for + * "contained" queries the strictness is preserved. + * If we're looking for an "equal" value, then we have to enter any + * subtree whose union contains (not strictly) our query value. + */ + +bool +gip4r_internal_consistent(IP4R * key, + IP4R * query, + StrategyNumber strategy) +{ +#ifdef GIST_QUERY_DEBUG + fprintf(stderr, "internal_consistent, %d\n", strategy); +#endif + + switch (strategy) + { + case 2: /* left contained in right nonstrict */ + case 4: /* left contained in right strict */ + case 5: /* left overlaps right */ + return ip4r_overlaps_internal(key, query); + case 3: /* left contains right strict */ + return ip4r_contains_internal(key, query, false); + case 1: /* left contains right nonstrict */ + case 6: /* left equal right */ + return ip4r_contains_internal(key, query, true); + default: + return false; + } +} + +/* end */ diff -Nru ip4r-2.3/src/ip4r_funcs.h ip4r-2.4/src/ip4r_funcs.h --- ip4r-2.3/src/ip4r_funcs.h 1970-01-01 00:00:00.000000000 +0000 +++ ip4r-2.4/src/ip4r_funcs.h 2018-11-21 06:35:30.000000000 +0000 @@ -0,0 +1,252 @@ +/* ip4r_funcs.h */ + +static inline +uint32 hostmask(unsigned masklen) +{ + return (masklen) ? ( (((uint32)(1U)) << (32-masklen)) - 1U ) : 0xFFFFFFFFU; +} + +static inline +uint32 netmask(unsigned masklen) +{ + return ~hostmask(masklen); +} + +/* if LO and HI are ends of a CIDR prefix, return the mask length. + * If not, returns ~0. + */ + +static inline +unsigned masklen(uint32 lo, uint32 hi) +{ + uint32 d = (lo ^ hi) + 1; + /* at this point, d can be: + * 0 if A and B have all bits different + * 1 if A and B are equal + * 1 << (32-masklen) + * some other value if A and B are not ends of a CIDR range + * but in any case, after extracting the masklen, we have to + * recheck because some non-CIDR ranges will produce the same + * results. + */ + int fbit = ffs(d); + switch (fbit) + { + case 0: return (lo == 0 && hi == ~0) ? 0 : ~0; + case 1: return (lo == hi) ? 32 : ~0; + default: + if ( ((uint32)(1U) << (fbit-1)) == d ) + { + uint32 mask = hostmask(33-fbit); + if ((lo & mask) == 0 && (hi & mask) == mask) + return 33-fbit; + } + return ~0; + } +} + +static inline +bool ip4_valid_netmask(uint32 mask) +{ + uint32 d = ~mask + 1; + /* at this point, d can be: + * 0 if mask was 0x00000000 (valid) + * 1 << (32-masklen) (valid) + * some other value (invalid) + */ + int fbit = ffs(d); + switch (fbit) + { + case 0: + return true; + default: + return ( ((uint32)(1U) << (fbit-1)) == d ); + } +} + + +static inline +bool ip4r_from_cidr(IP4 prefix, unsigned masklen, IP4R *ipr) +{ + uint32 mask = hostmask(masklen); + if (masklen > 32) + return false; + if (prefix & mask) + return false; + ipr->lower = prefix; + ipr->upper = prefix | mask; + return true; +} + +static inline +bool ip4r_from_inet(IP4 addr, unsigned masklen, IP4R *ipr) +{ + uint32 mask = hostmask(masklen); + if (masklen > 32) + return false; + ipr->lower = addr & ~mask; + ipr->upper = addr | mask; + return true; +} + +static inline +bool ip4r_split_cidr(IP4R *val, IP4R *res) +{ + IP4 lo = val->lower; + IP4 hi = val->upper; + int len = 32; + IP4 mask = 1; + + res->lower = lo; + res->upper = hi; + + if (masklen(lo,hi) <= 32U) + return true; + + /* + * We know that all these cases are impossible because the CIDR check + * would catch them: + * + * lo==hi + * lo==0 && hi==~0 + * lo==~0 + * + * Therefore this loop must terminate before the mask overflows + */ + while ((lo & mask) == 0 && (lo | mask) <= hi) + --len, mask = (mask << 1) | 1; + mask >>= 1; + + res->upper = lo | mask; + val->lower = (lo | mask) + 1; + + return false; +} + +/* comparisons */ + +static inline +bool ip4_equal(IP4 a, IP4 b) +{ + return (a == b); +} + +static inline +bool ip4_lessthan(IP4 a, IP4 b) +{ + return (a < b); +} + +static inline +bool ip4_less_eq(IP4 a, IP4 b) +{ + return (a <= b); +} + +/* helpers for union/intersection for indexing */ + +static inline +IP4R *ip4r_union_internal(IP4R *a, IP4R *b, IP4R *result) +{ + if (a->lower < b->lower) + result->lower = a->lower; + else + result->lower = b->lower; + + if (a->upper > b->upper) + result->upper = a->upper; + else + result->upper = b->upper; + + return result; +} + +static inline +IP4R *ip4r_inter_internal(IP4R *a, IP4R *b, IP4R *result) +{ + if (a->upper < b->lower || a->lower > b->upper) + { + /* disjoint */ + result->lower = 1; + result->upper = 0; /* INVALID VALUE */ + return NULL; + } + + if (a->upper < b->upper) + result->upper = a->upper; + else + result->upper = b->upper; + + if (a->lower > b->lower) + result->lower = a->lower; + else + result->lower = b->lower; + + return result; +} + +static inline +double ip4r_metric(IP4R *v) +{ + if (!v) + return 0.0; + return ((v->upper - v->lower) + 1.0); +} + +static inline +bool ip4r_equal(IP4R *a, IP4R *b) +{ + return (a->lower == b->lower && a->upper == b->upper); +} + +static inline +bool ip4r_lessthan(IP4R *a, IP4R *b) +{ + return (a->lower == b->lower) ? (a->upper < b->upper) : (a->lower < b->lower); +} + +static inline +bool ip4r_less_eq(IP4R *a, IP4R *b) +{ + return (a->lower == b->lower) ? (a->upper <= b->upper) : (a->lower < b->lower); +} + +static inline +bool ip4r_contains_internal(IP4R *left, IP4R *right, bool eqval) +{ + if (ip4r_equal(left,right)) + return eqval; + return ((left->lower <= right->lower) && (left->upper >= right->upper)); +} + +static inline +bool ip4r_overlaps_internal(IP4R *left, IP4R *right) +{ + return (left->upper >= right->lower && left->lower <= right->upper); +} + +static inline +bool ip4_contains_internal(IP4R *left, IP4 right) +{ + return (left->lower <= right && left->upper >= right); +} + +static inline +bool ip4r_left_internal(IP4R *left, IP4R *right) +{ + return (left->upper < right->lower); +} + +static inline +bool ip4r_extends_left_of_internal(IP4R *left, IP4R *right) +{ + return (left->lower < right->lower); +} + +static inline +bool ip4r_extends_right_of_internal(IP4R *left, IP4R *right) +{ + return (left->upper > right->upper); +} + +/* end */ diff -Nru ip4r-2.3/src/ip4r_module.c ip4r-2.4/src/ip4r_module.c --- ip4r-2.3/src/ip4r_module.c 1970-01-01 00:00:00.000000000 +0000 +++ ip4r-2.4/src/ip4r_module.c 2018-11-21 06:35:30.000000000 +0000 @@ -0,0 +1,8 @@ +/* ip4r_module.c */ + +#include "postgres.h" +#include "fmgr.h" + +PG_MODULE_MAGIC; + +/* end */ diff -Nru ip4r-2.3/src/ip6r.c ip4r-2.4/src/ip6r.c --- ip4r-2.3/src/ip6r.c 1970-01-01 00:00:00.000000000 +0000 +++ ip4r-2.4/src/ip6r.c 2018-11-21 06:35:30.000000000 +0000 @@ -0,0 +1,1892 @@ +/* ip6r.c */ + +#include "postgres.h" + +#include +#include + +#include "fmgr.h" +#include "funcapi.h" + +#include "access/gist.h" +#include "access/hash.h" +#include "access/skey.h" +#include "libpq/pqformat.h" +#include "utils/builtins.h" +#include "utils/elog.h" +#include "utils/numeric.h" +#include "utils/palloc.h" +#include "utils/varbit.h" + +#include "ipr_internal.h" +#include "ip6r_funcs.h" + +/* extract an IP range from text. + */ +static +bool ip6r_from_str(char *str, IP6R *ipr) +{ + char buf[IP6_STRING_MAX]; + int pos = strcspn(str, "-/"); + IP6 ip; + + switch (str[pos]) + { + case 0: /* no separator, must be single ip6 addr */ + { + if (!ip6_raw_input(str, ip.bits)) + return false; + ipr->lower = ip; + ipr->upper = ip; + return true; + } + + case '-': /* lower-upper */ + { + char *rest = str + pos + 1; + + if (pos > sizeof(buf)-2) + return false; + memcpy(buf, str, pos); + buf[pos] = 0; + if (!ip6_raw_input(buf, ip.bits)) + return false; + ipr->lower = ip; + if (!ip6_raw_input(rest, ip.bits)) + return false; + if (!ip6_lessthan(&ip, &ipr->lower)) + ipr->upper = ip; + else + { + ipr->upper = ipr->lower; + ipr->lower = ip; + } + return true; + } + + case '/': /* prefix/len */ + { + char *rest = str + pos + 1; + unsigned pfxlen; + char dummy; + + if (pos > sizeof(buf)-2) + return false; + memcpy(buf, str, pos); + buf[pos] = 0; + if (!ip6_raw_input(buf, ip.bits)) + return false; + if (rest[strspn(rest,"0123456789")]) + return false; + if (sscanf(rest, "%u%c", &pfxlen, &dummy) != 1) + return false; + return ip6r_from_cidr(&ip, pfxlen, ipr); + } + + default: + return false; /* can't happen */ + } +} + + +/* Output an ip range in text form + */ +static +int ip6r_to_str(IP6R *ipr, char *str, int slen) +{ + char buf1[IP6_STRING_MAX]; + char buf2[IP6_STRING_MAX]; + unsigned msk; + + if (ip6_equal(&ipr->lower, &ipr->upper)) + return ip6_raw_output(ipr->lower.bits, str, slen); + + if ((msk = masklen6(&ipr->lower,&ipr->upper)) <= 128) + { + ip6_raw_output(ipr->lower.bits, buf1, sizeof(buf1)); + return snprintf(str, slen, "%s/%u", buf1, msk); + } + + ip6_raw_output(ipr->lower.bits, buf1, sizeof(buf1)); + ip6_raw_output(ipr->upper.bits, buf2, sizeof(buf2)); + + return snprintf(str, slen, "%s-%s", buf1, buf2); +} + + +/**************************************************************************/ +/* This part handles all aspects of postgres interfacing. + */ + + +/* end of version dependencies */ + + +/* +#define GIST_DEBUG +#define GIST_QUERY_DEBUG +*/ + +static +text * +make_text(int len) +{ + text *ret = (text *) palloc0(len + VARHDRSZ); + SET_VARSIZE(ret, len + VARHDRSZ); + return ret; +} + +static inline +void +set_text_len(text *txt, int len) +{ + Assert(len >= 0 && len + VARHDRSZ <= VARSIZE(txt)); + if (len + VARHDRSZ <= VARSIZE(txt)) + SET_VARSIZE(txt, len + VARHDRSZ); +} + +/* +** Input/Output routines +*/ + +PG_FUNCTION_INFO_V1(ip6_in); +Datum +ip6_in(PG_FUNCTION_ARGS) +{ + char *str = PG_GETARG_CSTRING(0); + IP6 *ip = palloc(sizeof(IP6)); + if (ip6_raw_input(str, ip->bits)) + PG_RETURN_IP6_P(ip); + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid IP6 value: '%s'", str))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(ip6_out); +Datum +ip6_out(PG_FUNCTION_ARGS) +{ + IP6 *ip = PG_GETARG_IP6_P(0); + char *out = palloc(IP6_STRING_MAX); + ip6_raw_output(ip->bits, out, IP6_STRING_MAX); + PG_RETURN_CSTRING(out); +} + +PG_FUNCTION_INFO_V1(ip6_recv); +Datum +ip6_recv(PG_FUNCTION_ARGS) +{ + StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); + IP6 *ip = palloc(sizeof(IP6)); + + ip->bits[0] = pq_getmsgint64(buf); + ip->bits[1] = pq_getmsgint64(buf); + + PG_RETURN_IP6_P(ip); +} + +PG_FUNCTION_INFO_V1(ip6_send); +Datum +ip6_send(PG_FUNCTION_ARGS) +{ + IP6 *arg1 = PG_GETARG_IP6_P(0); + StringInfoData buf; + + pq_begintypsend(&buf); + pq_sendint64(&buf, arg1->bits[0]); + pq_sendint64(&buf, arg1->bits[1]); + PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); +} + +PG_FUNCTION_INFO_V1(ip6hash); +Datum +ip6hash(PG_FUNCTION_ARGS) +{ + IP6 *arg1 = PG_GETARG_IP6_P(0); + + return hash_any((unsigned char *)arg1, sizeof(IP6)); +} + +PG_FUNCTION_INFO_V1(ip6_hash_extended); +Datum +ip6_hash_extended(PG_FUNCTION_ARGS) +{ + IP6 *arg1 = PG_GETARG_IP6_P(0); + uint64 seed = DatumGetUInt64(PG_GETARG_DATUM(1)); + + return hash_any_extended((unsigned char *)arg1, sizeof(IP6), seed); +} + +PG_FUNCTION_INFO_V1(ip6_cast_to_text); +Datum +ip6_cast_to_text(PG_FUNCTION_ARGS) +{ + IP6 *ip = PG_GETARG_IP6_P(0); + text *out = make_text(IP6_STRING_MAX); + set_text_len(out, ip6_raw_output(ip->bits, VARDATA(out), IP6_STRING_MAX)); + PG_RETURN_TEXT_P(out); +} + +PG_FUNCTION_INFO_V1(ip6_cast_from_text); +Datum +ip6_cast_from_text(PG_FUNCTION_ARGS) +{ + text *txt = PG_GETARG_TEXT_PP(0); + int tlen = VARSIZE_ANY_EXHDR(txt); + char buf[IP6_STRING_MAX]; + + if (tlen < sizeof(buf)) + { + IP6 *ip = palloc(sizeof(IP6)); + + memcpy(buf, VARDATA_ANY(txt), tlen); + buf[tlen] = 0; + if (ip6_raw_input(buf, ip->bits)) + PG_RETURN_IP6_P(ip); + } + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid IP6 value in text"))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(ip6_cast_from_inet); +Datum +ip6_cast_from_inet(PG_FUNCTION_ARGS) +{ + inet *inetptr = PG_GETARG_INET_P(0); + inet_struct *in = INET_STRUCT_DATA(inetptr); + + if (in->family == PGSQL_AF_INET6) + { + unsigned char *p = in->ipaddr; + IP6 *ip = palloc(sizeof(IP6)); + ip6_deserialize(p, ip); + PG_RETURN_IP6_P(ip); + } + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid INET value for conversion to IP6"))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(ip6_cast_to_cidr); +Datum +ip6_cast_to_cidr(PG_FUNCTION_ARGS) +{ + IP6 *ip = PG_GETARG_IP6_P(0); + inet *res = palloc0(VARHDRSZ + sizeof(inet_struct)); + inet_struct *in; + + SET_VARSIZE(res, VARHDRSZ + offsetof(inet_struct, ipaddr) + 16); + + in = ((inet_struct *)VARDATA(res)); + in->bits = 128; + in->family = PGSQL_AF_INET6; + ip6_serialize(ip, in->ipaddr); + + PG_RETURN_INET_P(res); +} + + +PG_FUNCTION_INFO_V1(ip6_cast_to_numeric); +Datum +ip6_cast_to_numeric(PG_FUNCTION_ARGS) +{ + IP6 *ip = PG_GETARG_IP6_P(0); + Datum res,tmp,mul; + static int64 mul_val = ((int64)1 << 56); + int64 tmp_val; + + mul = DirectFunctionCall1(int8_numeric,Int64GetDatumFast(mul_val)); + tmp_val = (ip->bits[0] >> 48); + res = DirectFunctionCall1(int8_numeric,Int64GetDatumFast(tmp_val)); + tmp_val = ((ip->bits[0] & (uint64)(0xFFFFFFFFFFFFULL)) << 8) | (ip->bits[1] >> 56); + tmp = DirectFunctionCall1(int8_numeric,Int64GetDatumFast(tmp_val)); + res = DirectFunctionCall2(numeric_mul,res,mul); + res = DirectFunctionCall2(numeric_add,res,tmp); + tmp_val = (ip->bits[1] & (uint64)(0xFFFFFFFFFFFFFFULL)); + tmp = DirectFunctionCall1(int8_numeric,Int64GetDatumFast(tmp_val)); + res = DirectFunctionCall2(numeric_mul,res,mul); + res = DirectFunctionCall2(numeric_add,res,tmp); + + PG_RETURN_DATUM(res); +} + +PG_FUNCTION_INFO_V1(ip6_cast_from_numeric); +Datum +ip6_cast_from_numeric(PG_FUNCTION_ARGS) +{ + Datum val = NumericGetDatum(PG_GETARG_NUMERIC(0)); + Datum rem,tmp,div,mul; + static int64 mul_val = ((int64)1 << 56); + uint64 tmp_val; + IP6 *res; + + tmp = DirectFunctionCall1(numeric_floor,DirectFunctionCall1(numeric_abs,val)); + + if (!DatumGetBool(DirectFunctionCall2(numeric_eq,tmp,val))) + { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid numeric value for conversion to IP6"))); + } + + res = palloc(sizeof(IP6)); + + /* we use div/mul here rather than mod because numeric_mod is implemented as + * a div/mul/subtract in any case, so we save a division step by doing the + * mul/subtract ourselves + */ + + mul = DirectFunctionCall1(int8_numeric,Int64GetDatumFast(mul_val)); + div = DirectFunctionCall2(numeric_div_trunc,val,mul); + tmp = DirectFunctionCall2(numeric_mul,div,mul); + rem = DirectFunctionCall2(numeric_sub,val,tmp); + res->bits[1] = (uint64)DatumGetInt64(DirectFunctionCall1(numeric_int8,rem)); + val = div; + div = DirectFunctionCall2(numeric_div_trunc,val,mul); + tmp = DirectFunctionCall2(numeric_mul,div,mul); + rem = DirectFunctionCall2(numeric_sub,val,tmp); + tmp_val = (uint64)DatumGetInt64(DirectFunctionCall1(numeric_int8,rem)); + res->bits[1] |= ((tmp_val & 0xFF) << 56); + res->bits[0] = (tmp_val >> 8); + if (!DatumGetBool(DirectFunctionCall2(numeric_gt,div,mul))) + { + tmp_val = (uint64)DatumGetInt64(DirectFunctionCall1(numeric_int8,div)); + if (tmp_val <= (uint64)0xFFFFU) + { + res->bits[0] |= (tmp_val << 48); + PG_RETURN_IP6_P(res); + } + } + + ereport(ERROR, + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("numeric value too large for conversion to IP6"))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(ip6_cast_from_bit); +Datum +ip6_cast_from_bit(PG_FUNCTION_ARGS) +{ + VarBit *val = PG_GETARG_VARBIT_P(0); + + if (VARBITLEN(val) == 128) + { + bits8 *p = VARBITS(val); + IP6 *res = palloc(sizeof(IP6)); + ip6_deserialize(p, res); + PG_RETURN_IP6_P(res); + } + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid BIT value for conversion to IP6"))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(ip6_cast_to_bit); +Datum +ip6_cast_to_bit(PG_FUNCTION_ARGS) +{ + IP6 *ip = PG_GETARG_IP6_P(0); + int len = VARBITTOTALLEN(128); + VarBit *res = palloc0(len); + unsigned char *p = VARBITS(res); + + SET_VARSIZE(res, len); + VARBITLEN(res) = 128; + + ip6_serialize(ip, p); + + PG_RETURN_VARBIT_P(res); +} + +PG_FUNCTION_INFO_V1(ip6_cast_from_bytea); +Datum +ip6_cast_from_bytea(PG_FUNCTION_ARGS) +{ + void *val = PG_GETARG_BYTEA_PP(0); + + if (VARSIZE_ANY_EXHDR(val) == 16) + { + void *p = VARDATA_ANY(val); + IP6 *res = palloc(sizeof(IP6)); + ip6_deserialize(p, res); + PG_RETURN_IP6_P(res); + } + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid BYTEA value for conversion to IP4"))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(ip6_cast_to_bytea); +Datum +ip6_cast_to_bytea(PG_FUNCTION_ARGS) +{ + IP6 *ip = PG_GETARG_IP6_P(0); + bytea *res = palloc(VARHDRSZ + 16); + unsigned char *p = (unsigned char *) VARDATA(res); + + SET_VARSIZE(res, VARHDRSZ + 16); + + ip6_serialize(ip, p); + + PG_RETURN_BYTEA_P(res); +} + +PG_FUNCTION_INFO_V1(ip6_netmask); +Datum +ip6_netmask(PG_FUNCTION_ARGS) +{ + int pfxlen = PG_GETARG_INT32(0); + IP6 *mask; + + if (pfxlen < 0 || pfxlen > 128) + { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("prefix length out of range"))); + } + + mask = palloc(sizeof(IP6)); + mask->bits[0] = netmask6_hi(pfxlen); + mask->bits[1] = netmask6_lo(pfxlen); + PG_RETURN_IP6_P(mask); +} + +PG_FUNCTION_INFO_V1(ip6_net_lower); +Datum +ip6_net_lower(PG_FUNCTION_ARGS) +{ + IP6 *ip = PG_GETARG_IP6_P(0); + int pfxlen = PG_GETARG_INT32(1); + IP6 *res; + + if (pfxlen < 0 || pfxlen > 128) + { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("prefix length out of range"))); + } + + res = palloc(sizeof(IP6)); + res->bits[0] = ip->bits[0] & netmask6_hi(pfxlen); + res->bits[1] = ip->bits[1] & netmask6_lo(pfxlen); + + PG_RETURN_IP6_P(res); +} + +PG_FUNCTION_INFO_V1(ip6_net_upper); +Datum +ip6_net_upper(PG_FUNCTION_ARGS) +{ + IP6 *ip = PG_GETARG_IP6_P(0); + int pfxlen = PG_GETARG_INT32(1); + IP6 *res; + + if (pfxlen < 0 || pfxlen > 128) + { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("prefix length out of range"))); + } + + res = palloc(sizeof(IP6)); + res->bits[0] = ip->bits[0] | hostmask6_hi(pfxlen); + res->bits[1] = ip->bits[1] | hostmask6_lo(pfxlen); + + PG_RETURN_IP6_P(res); +} + +PG_FUNCTION_INFO_V1(ip6_plus_int); +Datum +ip6_plus_int(PG_FUNCTION_ARGS) +{ + IP6 *ip = PG_GETARG_IP6_P(0); + int addend = PG_GETARG_INT32(1); + IP6 *result = palloc(sizeof(IP6)); + + if (addend >= 0) + { + result->bits[1] = ip->bits[1] + addend; + result->bits[0] = ip->bits[0] + (result->bits[1] < ip->bits[1]); + } + else + { + result->bits[1] = ip->bits[1] - (uint64)(-addend); + result->bits[0] = ip->bits[0] - (result->bits[1] > ip->bits[1]); + } + + if ((addend < 0) != ip6_lessthan(result,ip)) + { + ereport(ERROR, + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("ip address out of range"))); + } + + PG_RETURN_IP6_P(result); +} + +PG_FUNCTION_INFO_V1(ip6_plus_bigint); +Datum +ip6_plus_bigint(PG_FUNCTION_ARGS) +{ + IP6 *ip = PG_GETARG_IP6_P(0); + int64 addend = PG_GETARG_INT64(1); + IP6 *result = palloc(sizeof(IP6)); + + if (addend >= 0) + { + result->bits[1] = ip->bits[1] + addend; + result->bits[0] = ip->bits[0] + (result->bits[1] < ip->bits[1]); + } + else + { + result->bits[1] = ip->bits[1] - (uint64)(-addend); + result->bits[0] = ip->bits[0] - (result->bits[1] > ip->bits[1]); + } + + if ((addend < 0) != ip6_lessthan(result,ip)) + { + ereport(ERROR, + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("ip address out of range"))); + } + + PG_RETURN_IP6_P(result); +} + +PG_FUNCTION_INFO_V1(ip6_plus_numeric); +Datum +ip6_plus_numeric(PG_FUNCTION_ARGS) +{ + IP6 *ip = PG_GETARG_IP6_P(0); + Datum addend_num = NumericGetDatum(PG_GETARG_NUMERIC(1)); + Datum addend_abs; + IP6 *addend; + IP6 *result = palloc(sizeof(IP6)); + bool is_negative; + + addend_abs = DirectFunctionCall1(numeric_abs,addend_num); + addend = DatumGetIP6P(DirectFunctionCall1(ip6_cast_from_numeric,addend_abs)); + + if (DatumGetBool(DirectFunctionCall2(numeric_eq,addend_num,addend_abs))) + { + is_negative = false; + result->bits[1] = ip->bits[1] + addend->bits[1]; + result->bits[0] = ip->bits[0] + addend->bits[0] + (result->bits[1] < ip->bits[1]); + } + else + { + is_negative = true; + result->bits[1] = ip->bits[1] - addend->bits[1]; + result->bits[0] = ip->bits[0] - addend->bits[0] - (result->bits[1] > ip->bits[1]); + } + + if (is_negative != ip6_lessthan(result,ip)) + { + ereport(ERROR, + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("ip address out of range"))); + } + + PG_RETURN_IP6_P(result); +} + +PG_FUNCTION_INFO_V1(ip6_minus_int); +Datum +ip6_minus_int(PG_FUNCTION_ARGS) +{ + IP6 *ip = PG_GETARG_IP6_P(0); + int subtrahend = PG_GETARG_INT32(1); + IP6 *result = palloc(sizeof(IP6)); + + ip6_sub_int(ip, subtrahend, result); + + if ((subtrahend > 0) != ip6_lessthan(result,ip)) + { + ereport(ERROR, + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("ip address out of range"))); + } + + PG_RETURN_IP6_P(result); +} + +PG_FUNCTION_INFO_V1(ip6_minus_bigint); +Datum +ip6_minus_bigint(PG_FUNCTION_ARGS) +{ + IP6 *ip = PG_GETARG_IP6_P(0); + int64 subtrahend = PG_GETARG_INT64(1); + IP6 *result = palloc(sizeof(IP6)); + + if (subtrahend >= 0) + { + result->bits[1] = ip->bits[1] - (uint64)subtrahend; + result->bits[0] = ip->bits[0] - (result->bits[1] > ip->bits[1]); + } + else + { + result->bits[1] = ip->bits[1] + (uint64)(-subtrahend); + result->bits[0] = ip->bits[0] + (result->bits[1] < ip->bits[1]); + } + + if ((subtrahend > 0) != ip6_lessthan(result,ip)) + { + ereport(ERROR, + (errcode(ERRCODE_NUMERIC_VALUE_OUT_OF_RANGE), + errmsg("ip address out of range"))); + } + + PG_RETURN_IP6_P(result); +} + +PG_FUNCTION_INFO_V1(ip6_minus_numeric); +Datum +ip6_minus_numeric(PG_FUNCTION_ARGS) +{ + Datum ip = PG_GETARG_DATUM(0); + Datum subtrahend = PG_GETARG_DATUM(1); + + subtrahend = DirectFunctionCall1(numeric_uminus,subtrahend); + return DirectFunctionCall2(ip6_plus_numeric,ip,subtrahend); +} + +PG_FUNCTION_INFO_V1(ip6_minus_ip6); +Datum +ip6_minus_ip6(PG_FUNCTION_ARGS) +{ + Datum minuend = PG_GETARG_DATUM(0); + Datum subtrahend = PG_GETARG_DATUM(1); + Datum res; + + res = DirectFunctionCall2(numeric_sub, + DirectFunctionCall1(ip6_cast_to_numeric,minuend), + DirectFunctionCall1(ip6_cast_to_numeric,subtrahend)); + + PG_RETURN_DATUM(res); +} + +PG_FUNCTION_INFO_V1(ip6_and); +Datum +ip6_and(PG_FUNCTION_ARGS) +{ + IP6 *a = PG_GETARG_IP6_P(0); + IP6 *b = PG_GETARG_IP6_P(1); + IP6 *res = palloc(sizeof(IP6)); + + res->bits[0] = a->bits[0] & b->bits[0]; + res->bits[1] = a->bits[1] & b->bits[1]; + + PG_RETURN_IP6_P(res); +} + +PG_FUNCTION_INFO_V1(ip6_or); +Datum +ip6_or(PG_FUNCTION_ARGS) +{ + IP6 *a = PG_GETARG_IP6_P(0); + IP6 *b = PG_GETARG_IP6_P(1); + IP6 *res = palloc(sizeof(IP6)); + + res->bits[0] = a->bits[0] | b->bits[0]; + res->bits[1] = a->bits[1] | b->bits[1]; + + PG_RETURN_IP6_P(res); +} + +PG_FUNCTION_INFO_V1(ip6_xor); +Datum +ip6_xor(PG_FUNCTION_ARGS) +{ + IP6 *a = PG_GETARG_IP6_P(0); + IP6 *b = PG_GETARG_IP6_P(1); + IP6 *res = palloc(sizeof(IP6)); + + res->bits[0] = a->bits[0] ^ b->bits[0]; + res->bits[1] = a->bits[1] ^ b->bits[1]; + + PG_RETURN_IP6_P(res); +} + +PG_FUNCTION_INFO_V1(ip6_not); +Datum +ip6_not(PG_FUNCTION_ARGS) +{ + IP6 *a = PG_GETARG_IP6_P(0); + IP6 *res = palloc(sizeof(IP6)); + + res->bits[0] = ~a->bits[0]; + res->bits[1] = ~a->bits[1]; + + PG_RETURN_IP6_P(res); +} + + +/*---- ip6r ----*/ + +PG_FUNCTION_INFO_V1(ip6r_in); +Datum +ip6r_in(PG_FUNCTION_ARGS) +{ + char *str = PG_GETARG_CSTRING(0); + IP6R ipr; + + if (ip6r_from_str(str, &ipr)) + { + IP6R *res = palloc(sizeof(IP6R)); + *res = ipr; + PG_RETURN_IP6R_P(res); + } + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid IP6R value: \"%s\"", str))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(ip6r_out); +Datum +ip6r_out(PG_FUNCTION_ARGS) +{ + IP6R *ipr = PG_GETARG_IP6R_P(0); + char *out = palloc(IP6R_STRING_MAX); + ip6r_to_str(ipr, out, IP6R_STRING_MAX); + PG_RETURN_CSTRING(out); +} + +PG_FUNCTION_INFO_V1(ip6r_recv); +Datum +ip6r_recv(PG_FUNCTION_ARGS) +{ + StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); + IP6R *ipr = palloc(sizeof(IP6R)); + + ipr->lower.bits[0] = pq_getmsgint64(buf); + ipr->lower.bits[1] = pq_getmsgint64(buf); + ipr->upper.bits[0] = pq_getmsgint64(buf); + ipr->upper.bits[1] = pq_getmsgint64(buf); + + PG_RETURN_IP6R_P(ipr); +} + +PG_FUNCTION_INFO_V1(ip6r_send); +Datum +ip6r_send(PG_FUNCTION_ARGS) +{ + IP6R *ipr = PG_GETARG_IP6R_P(0); + StringInfoData buf; + + pq_begintypsend(&buf); + pq_sendint64(&buf, ipr->lower.bits[0]); + pq_sendint64(&buf, ipr->lower.bits[1]); + pq_sendint64(&buf, ipr->upper.bits[0]); + pq_sendint64(&buf, ipr->upper.bits[1]); + PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); +} + +PG_FUNCTION_INFO_V1(ip6rhash); +Datum +ip6rhash(PG_FUNCTION_ARGS) +{ + IP6R *arg1 = PG_GETARG_IP6R_P(0); + + return hash_any((unsigned char *)arg1, sizeof(IP6R)); +} + +PG_FUNCTION_INFO_V1(ip6r_hash_extended); +Datum +ip6r_hash_extended(PG_FUNCTION_ARGS) +{ + IP6R *arg1 = PG_GETARG_IP6R_P(0); + uint64 seed = DatumGetUInt64(PG_GETARG_DATUM(1)); + + return hash_any_extended((unsigned char *)arg1, sizeof(IP6R), seed); +} + +PG_FUNCTION_INFO_V1(ip6r_cast_to_text); +Datum +ip6r_cast_to_text(PG_FUNCTION_ARGS) +{ + IP6R *ipr = PG_GETARG_IP6R_P(0); + text *out = make_text(IP6R_STRING_MAX); + set_text_len(out, ip6r_to_str(ipr, VARDATA(out), IP6R_STRING_MAX)); + PG_RETURN_TEXT_P(out); +} + +PG_FUNCTION_INFO_V1(ip6r_cast_from_text); +Datum +ip6r_cast_from_text(PG_FUNCTION_ARGS) +{ + text *txt = PG_GETARG_TEXT_PP(0); + int tlen = VARSIZE_ANY_EXHDR(txt); + char buf[IP6R_STRING_MAX]; + + if (tlen < sizeof(buf)) + { + IP6R ipr; + + memcpy(buf, VARDATA_ANY(txt), tlen); + buf[tlen] = 0; + if (ip6r_from_str(buf, &ipr)) + { + IP6R *res = palloc(sizeof(IP6R)); + *res = ipr; + PG_RETURN_IP6R_P(res); + } + } + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid IP6R value in text"))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(ip6r_cast_from_cidr); +Datum +ip6r_cast_from_cidr(PG_FUNCTION_ARGS) +{ + inet *inetptr = PG_GETARG_INET_P(0); + inet_struct *in = INET_STRUCT_DATA(inetptr); + + if (in->family == PGSQL_AF_INET6) + { + unsigned char *p = in->ipaddr; + IP6 ip; + IP6R ipr; + ip6_deserialize(p, &ip); + if (ip6r_from_cidr(&ip, in->bits, &ipr)) + { + IP6R *res = palloc(sizeof(IP6R)); + *res = ipr; + PG_RETURN_IP6R_P(res); + } + } + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid CIDR value for conversion to IP6R"))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(ip6r_cast_to_cidr); +Datum +ip6r_cast_to_cidr(PG_FUNCTION_ARGS) +{ + IP6R *ipr = PG_GETARG_IP6R_P(0); + IP6 *ip = &ipr->lower; + inet *res; + inet_struct *in; + unsigned bits = masklen6(ip, &ipr->upper); + + if (bits > 128) + PG_RETURN_NULL(); + + res = palloc0(VARHDRSZ + sizeof(inet_struct)); + SET_VARSIZE(res, VARHDRSZ + offsetof(inet_struct, ipaddr) + 16); + + in = ((inet_struct *)VARDATA(res)); + in->bits = bits; + in->family = PGSQL_AF_INET6; + ip6_serialize(ip, in->ipaddr); + + PG_RETURN_INET_P(res); +} + +PG_FUNCTION_INFO_V1(ip6r_cast_from_ip6); +Datum +ip6r_cast_from_ip6(PG_FUNCTION_ARGS) +{ + IP6 *ip = PG_GETARG_IP6_P(0); + IP6R *res = palloc(sizeof(IP6R)); + if (ip6r_from_inet(ip, 128, res)) + { + PG_RETURN_IP6R_P(res); + } + + pfree(res); + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid IP6 value for conversion to IP6R (shouldn't be possible)"))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(ip6r_from_ip6s); +Datum +ip6r_from_ip6s(PG_FUNCTION_ARGS) +{ + IP6 *a = PG_GETARG_IP6_P(0); + IP6 *b = PG_GETARG_IP6_P(1); + IP6R *res = palloc(sizeof(IP6R)); + if (ip6_lessthan(a,b)) + res->lower = *a, res->upper = *b; + else + res->lower = *b, res->upper = *a; + PG_RETURN_IP6R_P(res); +} + +PG_FUNCTION_INFO_V1(ip6r_cast_from_bit); +Datum +ip6r_cast_from_bit(PG_FUNCTION_ARGS) +{ + VarBit *val = PG_GETARG_VARBIT_P(0); + int bitlen = VARBITLEN(val); + + if (bitlen <= 128) + { + bits8 buf[16]; + bits8 *p = VARBITS(val); + IP6 ip; + IP6R *res = palloc(sizeof(IP6R)); + + if (bitlen <= 120) + { + memset(buf, 0, sizeof(buf)); + memcpy(buf, p, VARBITBYTES(val)); + p = buf; + } + + ip6_deserialize(p, &ip); + if (ip6r_from_cidr(&ip, bitlen, res)) + PG_RETURN_IP6_P(res); + } + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid BIT value for conversion to IP6R"))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(ip6r_cast_to_bit); +Datum +ip6r_cast_to_bit(PG_FUNCTION_ARGS) +{ + IP6R *ipr = PG_GETARG_IP6R_P(0); + IP6 *ip = &ipr->lower; + unsigned bits = masklen6(ip, &ipr->upper); + VarBit *res; + unsigned char buf[16]; + int len; + + if (bits > 128) + PG_RETURN_NULL(); + + len = VARBITTOTALLEN(bits); + res = palloc0(len); + SET_VARSIZE(res, len); + VARBITLEN(res) = bits; + + ip6_serialize(ip, buf); + + memcpy(VARBITS(res), buf, VARBITBYTES(res)); + PG_RETURN_VARBIT_P(res); +} + +PG_FUNCTION_INFO_V1(ip6r_net_prefix); +Datum +ip6r_net_prefix(PG_FUNCTION_ARGS) +{ + IP6 *ip = PG_GETARG_IP6_P(0); + int pfxlen = PG_GETARG_INT32(1); + + if (pfxlen < 0 || pfxlen > 128) + { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("prefix length out of range"))); + } + + { + IP6R *res = palloc(sizeof(IP6R)); + ip6r_from_inet(ip, (unsigned)pfxlen, res); + PG_RETURN_IP6R_P(res); + } +} + +PG_FUNCTION_INFO_V1(ip6r_net_mask); +Datum +ip6r_net_mask(PG_FUNCTION_ARGS) +{ + IP6 *ip = PG_GETARG_IP6_P(0); + IP6 *mask = PG_GETARG_IP6_P(1); + + if (!ip6_valid_netmask(mask->bits[0], mask->bits[1])) + { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid netmask"))); + } + + { + IP6R *res = palloc(sizeof(IP6R)); + + res->lower.bits[0] = ip->bits[0] & mask->bits[0]; + res->lower.bits[1] = ip->bits[1] & mask->bits[1]; + res->upper.bits[0] = ip->bits[0] | ~(mask->bits[0]); + res->upper.bits[1] = ip->bits[1] | ~(mask->bits[1]); + + PG_RETURN_IP6R_P(res); + } +} + + +PG_FUNCTION_INFO_V1(ip6r_lower); +Datum +ip6r_lower(PG_FUNCTION_ARGS) +{ + IP6R *ipr = PG_GETARG_IP6R_P(0); + IP6 *res = palloc(sizeof(IP6)); + *res = ipr->lower; + PG_RETURN_IP6_P(res); +} + +PG_FUNCTION_INFO_V1(ip6r_upper); +Datum +ip6r_upper(PG_FUNCTION_ARGS) +{ + IP6R *ipr = PG_GETARG_IP6R_P(0); + IP6 *res = palloc(sizeof(IP6)); + *res = ipr->upper; + PG_RETURN_IP6_P(res); +} + +PG_FUNCTION_INFO_V1(ip6r_is_cidr); +Datum +ip6r_is_cidr(PG_FUNCTION_ARGS) +{ + IP6R *ipr = PG_GETARG_IP6R_P(0); + PG_RETURN_BOOL( (masklen6(&ipr->lower,&ipr->upper) <= 128U) ); +} + +/* + * Decompose an arbitrary range into CIDRs + */ + +PG_FUNCTION_INFO_V1(ip6r_cidr_split); +Datum +ip6r_cidr_split(PG_FUNCTION_ARGS) +{ + FuncCallContext *funcctx; + IP6R *val; + IP6R *res; + + if (SRF_IS_FIRSTCALL()) + { + IP6R *in = PG_GETARG_IP6R_P(0); + funcctx = SRF_FIRSTCALL_INIT(); + val = MemoryContextAlloc(funcctx->multi_call_memory_ctx, + sizeof(IP6R)); + *val = *in; + funcctx->user_fctx = val; + } + + funcctx = SRF_PERCALL_SETUP(); + val = funcctx->user_fctx; + if (!val) + SRF_RETURN_DONE(funcctx); + + res = palloc(sizeof(IP6R)); + if (ip6r_split_cidr(val, res)) + funcctx->user_fctx = NULL; + + SRF_RETURN_NEXT(funcctx, IP6RPGetDatum(res)); +} + +/* + * comparisons and indexing + */ + +PG_FUNCTION_INFO_V1(ip6_lt); +Datum +ip6_lt(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip6_lessthan(PG_GETARG_IP6_P(0), PG_GETARG_IP6_P(1)) ); +} + +PG_FUNCTION_INFO_V1(ip6_le); +Datum +ip6_le(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip6_less_eq(PG_GETARG_IP6_P(0), PG_GETARG_IP6_P(1)) ); +} + +PG_FUNCTION_INFO_V1(ip6_gt); +Datum +ip6_gt(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip6_lessthan(PG_GETARG_IP6_P(1), PG_GETARG_IP6_P(0)) ); +} + +PG_FUNCTION_INFO_V1(ip6_ge); +Datum +ip6_ge(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip6_less_eq(PG_GETARG_IP6_P(1), PG_GETARG_IP6_P(0)) ); +} + +PG_FUNCTION_INFO_V1(ip6_eq); +Datum +ip6_eq(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip6_equal(PG_GETARG_IP6_P(0), PG_GETARG_IP6_P(1)) ); +} + +PG_FUNCTION_INFO_V1(ip6_neq); +Datum +ip6_neq(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( !ip6_equal(PG_GETARG_IP6_P(0), PG_GETARG_IP6_P(1)) ); +} + +PG_FUNCTION_INFO_V1(ip6r_lt); +Datum +ip6r_lt(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip6r_lessthan(PG_GETARG_IP6R_P(0), PG_GETARG_IP6R_P(1)) ); +} + +PG_FUNCTION_INFO_V1(ip6r_le); +Datum +ip6r_le(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip6r_less_eq(PG_GETARG_IP6R_P(0), PG_GETARG_IP6R_P(1)) ); +} + +PG_FUNCTION_INFO_V1(ip6r_gt); +Datum +ip6r_gt(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip6r_lessthan(PG_GETARG_IP6R_P(1), PG_GETARG_IP6R_P(0)) ); +} + +PG_FUNCTION_INFO_V1(ip6r_ge); +Datum +ip6r_ge(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip6r_less_eq(PG_GETARG_IP6R_P(1), PG_GETARG_IP6R_P(0)) ); +} + +PG_FUNCTION_INFO_V1(ip6r_eq); +Datum +ip6r_eq(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip6r_equal(PG_GETARG_IP6R_P(0), PG_GETARG_IP6R_P(1)) ); +} + +PG_FUNCTION_INFO_V1(ip6r_neq); +Datum +ip6r_neq(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( !ip6r_equal(PG_GETARG_IP6R_P(0), PG_GETARG_IP6R_P(1)) ); +} + +PG_FUNCTION_INFO_V1(ip6r_overlaps); +Datum +ip6r_overlaps(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip6r_overlaps_internal(PG_GETARG_IP6R_P(0), + PG_GETARG_IP6R_P(1)) ); +} + +PG_FUNCTION_INFO_V1(ip6r_contains); +Datum +ip6r_contains(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip6r_contains_internal(PG_GETARG_IP6R_P(0), + PG_GETARG_IP6R_P(1), + true) ); +} + +PG_FUNCTION_INFO_V1(ip6r_contains_strict); +Datum +ip6r_contains_strict(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip6r_contains_internal(PG_GETARG_IP6R_P(0), + PG_GETARG_IP6R_P(1), + false) ); +} + +PG_FUNCTION_INFO_V1(ip6r_contained_by); +Datum +ip6r_contained_by(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip6r_contains_internal(PG_GETARG_IP6R_P(1), + PG_GETARG_IP6R_P(0), + true) ); +} + +PG_FUNCTION_INFO_V1(ip6r_contained_by_strict); +Datum +ip6r_contained_by_strict(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip6r_contains_internal(PG_GETARG_IP6R_P(1), + PG_GETARG_IP6R_P(0), + false) ); +} + +PG_FUNCTION_INFO_V1(ip6_contains); +Datum +ip6_contains(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip6_contains_internal(PG_GETARG_IP6R_P(0), PG_GETARG_IP6_P(1)) ); +} + +PG_FUNCTION_INFO_V1(ip6_contained_by); +Datum +ip6_contained_by(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( ip6_contains_internal(PG_GETARG_IP6R_P(1), PG_GETARG_IP6_P(0)) ); +} + +PG_FUNCTION_INFO_V1(ip6r_union); +Datum +ip6r_union(PG_FUNCTION_ARGS) +{ + IP6R *res = palloc(sizeof(IP6R)); + ip6r_union_internal(PG_GETARG_IP6R_P(0), PG_GETARG_IP6R_P(1), res); + PG_RETURN_IP6R_P(res); +} + +PG_FUNCTION_INFO_V1(ip6r_inter); +Datum +ip6r_inter(PG_FUNCTION_ARGS) +{ + IP6R *res = palloc(sizeof(IP6R)); + if (ip6r_inter_internal(PG_GETARG_IP6R_P(0), PG_GETARG_IP6R_P(1), res)) + { + PG_RETURN_IP6R_P(res); + } + pfree(res); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(ip6r_size); +Datum +ip6r_size(PG_FUNCTION_ARGS) +{ + double size = ip6r_metric(PG_GETARG_IP6R_P(0)); + PG_RETURN_FLOAT8(size); +} + +PG_FUNCTION_INFO_V1(ip6r_size_exact); +Datum +ip6r_size_exact(PG_FUNCTION_ARGS) +{ + IP6R *ipr = PG_GETARG_IP6R_P(0); + Datum l = DirectFunctionCall1(ip6_cast_to_numeric, IP6PGetDatum(&ipr->lower)); + Datum u = DirectFunctionCall1(ip6_cast_to_numeric, IP6PGetDatum(&ipr->upper)); + Datum d = DirectFunctionCall2(numeric_sub, u, l); + Datum s = DirectFunctionCall1(numeric_inc, d); + PG_RETURN_DATUM(s); +} + +PG_FUNCTION_INFO_V1(ip6r_prefixlen); +Datum +ip6r_prefixlen(PG_FUNCTION_ARGS) +{ + IP6R *ipr = PG_GETARG_IP6R_P(0); + unsigned len = masklen6(&ipr->lower, &ipr->upper); + if (len <= 128) + PG_RETURN_INT32((int32) len); + PG_RETURN_NULL(); +} + + +/***************************************************************************** + * Btree functions + *****************************************************************************/ + +PG_FUNCTION_INFO_V1(ip6r_cmp); +Datum +ip6r_cmp(PG_FUNCTION_ARGS) +{ + IP6R *a = PG_GETARG_IP6R_P(0); + IP6R *b = PG_GETARG_IP6R_P(1); + if (ip6r_lessthan(a,b)) + PG_RETURN_INT32(-1); + if (ip6r_equal(a,b)) + PG_RETURN_INT32(0); + PG_RETURN_INT32(1); +} + +PG_FUNCTION_INFO_V1(ip6_cmp); +Datum +ip6_cmp(PG_FUNCTION_ARGS) +{ + IP6 *a = PG_GETARG_IP6_P(0); + IP6 *b = PG_GETARG_IP6_P(1); + PG_RETURN_INT32(ip6_compare(a,b)); +} + +/* + * in_range(val ip6,base ip6,offset bigint,sub bool,less bool) + * returns val CMP (base OP offset) + * where CMP is <= if less, >= otherwise + * and OP is - if sub, + otherwise + * We treat negative values of offset as special: they indicate + * the (negation of) a cidr prefix length + */ +PG_FUNCTION_INFO_V1(ip6_in_range_bigint); +Datum +ip6_in_range_bigint(PG_FUNCTION_ARGS) +{ + IP6 *val = PG_GETARG_IP6_P(0); + IP6 *base = PG_GETARG_IP6_P(1); + int64 offset = PG_GETARG_INT64(2); + bool sub = PG_GETARG_BOOL(3); + bool less = PG_GETARG_BOOL(4); + bool res; + + if (offset < -128) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE), + errmsg("invalid preceding or following size in window function"), + errdetail("Offset value " INT64_FORMAT " is outside the range -128 to 2^63-1", offset))); + + if (offset < 0) + { + int bits = -offset; + res = ip6_in_range_internal_bits(val, base, bits, sub, less); + } + else + { + IP6 offs; + offs.bits[0] = 0; + offs.bits[1] = offset; + res = ip6_in_range_internal(val, base, &offs, sub, less); + } + + PG_RETURN_BOOL(res); +} + +PG_FUNCTION_INFO_V1(ip6_in_range_ip6); +Datum +ip6_in_range_ip6(PG_FUNCTION_ARGS) +{ + IP6 *val = PG_GETARG_IP6_P(0); + IP6 *base = PG_GETARG_IP6_P(1); + IP6 *offset = PG_GETARG_IP6_P(2); + bool sub = PG_GETARG_BOOL(3); + bool less = PG_GETARG_BOOL(4); + + PG_RETURN_BOOL(ip6_in_range_internal(val, base, offset, sub, less)); +} + +#if 0 +/* + * This one is left disabled because it's inefficient and causes type + * ambiguity problems; if you want it, use an explicit numeric::ip6 cast + * insteag to get the previous function. Only leaving the code here for + * reference purposes. + */ +PG_FUNCTION_INFO_V1(ip6_in_range_numeric); +Datum +ip6_in_range_numeric(PG_FUNCTION_ARGS) +{ + IP6 *val = PG_GETARG_IP6_P(0); + IP6 *base = PG_GETARG_IP6_P(1); + Numeric offset; + bool sub = PG_GETARG_BOOL(3); + bool less = PG_GETARG_BOOL(4); + Datum zero; + MemoryContext oldcontext; + MemoryContext mycontext = fcinfo->flinfo->fn_extra; + bool res; + + /* + * This is tricky because we have to not leak memory into the caller's + * context. + * + * Retail pfree of everything would be too hard, so we make a memory + * context and store it in fn_extra, resetting it each time. + */ + if (!mycontext) + fcinfo->flinfo->fn_extra = mycontext = + AllocSetContextCreate(fcinfo->flinfo->fn_mcxt, + "ip6_in_range_numeric workspace", + ALLOCSET_SMALL_SIZES); + oldcontext = MemoryContextSwitchTo(mycontext); + + /* + * Don't do this before switching contexts since it may detoast. + */ + offset = PG_GETARG_NUMERIC(2); + zero = DirectFunctionCall1(int4_numeric, Int32GetDatum(0)); + + if (DatumGetBool(DirectFunctionCall2(numeric_lt, NumericGetDatum(offset), zero))) + { + Datum tmp1 = DirectFunctionCall2(numeric_larger, + DirectFunctionCall1(int4_numeric, Int32GetDatum(-128)), + DirectFunctionCall1(numeric_floor, NumericGetDatum(offset))); + int32 bits; + if (!DatumGetBool(DirectFunctionCall2(numeric_eq, NumericGetDatum(offset), tmp1))) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE), + errmsg("invalid preceding or following size in window function"), + errdetail("numeric value is not an integer in the range -128 to 2^128"))); + bits = DatumGetInt32(DirectFunctionCall1(numeric_int4, NumericGetDatum(offset))); + res = ip6_in_range_internal_bits(val, base, bits, sub, less); + } + else + { + IP6 *offs = DatumGetIP6P(DirectFunctionCall1(ip6_cast_from_numeric, NumericGetDatum(offset))); + res = ip6_in_range_internal(val, base, offs, sub, less); + } + + MemoryContextSwitchTo(oldcontext); + MemoryContextReset(mycontext); + PG_RETURN_BOOL(res); +} +#endif + +/***************************************************************************** + * GiST functions + *****************************************************************************/ + +/* +** GiST support methods +*/ + +Datum gip6r_consistent(PG_FUNCTION_ARGS); +Datum gip6r_compress(PG_FUNCTION_ARGS); +Datum gip6r_decompress(PG_FUNCTION_ARGS); +Datum gip6r_penalty(PG_FUNCTION_ARGS); +Datum gip6r_picksplit(PG_FUNCTION_ARGS); +Datum gip6r_union(PG_FUNCTION_ARGS); +Datum gip6r_same(PG_FUNCTION_ARGS); +Datum gip6r_fetch(PG_FUNCTION_ARGS); + +static bool gip6r_leaf_consistent(IP6R * key, IP6R * query, StrategyNumber strategy); +static bool gip6r_internal_consistent(IP6R * key, IP6R * query, StrategyNumber strategy); + +/* +** The GiST Consistent method for IP ranges +** Should return false if for all data items x below entry, +** the predicate x op query == false, where op is the oper +** corresponding to strategy in the pg_amop table. +*/ +PG_FUNCTION_INFO_V1(gip6r_consistent); +Datum +gip6r_consistent(PG_FUNCTION_ARGS) +{ + GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); + IP6R *query = (IP6R *) PG_GETARG_POINTER(1); + StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); + bool *recheck = (bool *) PG_GETARG_POINTER(4); + IP6R *key = (IP6R *) DatumGetPointer(entry->key); + bool retval; + + /* recheck is never needed with this type */ + if (recheck) + *recheck = false; + + /* + * * if entry is not leaf, use gip6r_internal_consistent, * else use + * gip6r_leaf_consistent + */ + if (GIST_LEAF(entry)) + retval = gip6r_leaf_consistent(key, query, strategy); + else + retval = gip6r_internal_consistent(key, query, strategy); + + PG_RETURN_BOOL(retval); +} + +/* +** The GiST Union method for IP ranges +** returns the minimal bounding IP4R that encloses all the entries in entryvec +*/ +PG_FUNCTION_INFO_V1(gip6r_union); +Datum +gip6r_union(PG_FUNCTION_ARGS) +{ + GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0); + int *sizep = (int *) PG_GETARG_POINTER(1); + GISTENTRY *ent = GISTENTRYVEC(entryvec); + + int numranges, i; + IP6R *out = palloc(sizeof(IP6R)); + IP6R *tmp; + +#ifdef GIST_DEBUG + fprintf(stderr, "union\n"); +#endif + + numranges = GISTENTRYCOUNT(entryvec); + tmp = (IP6R *) DatumGetPointer(ent[0].key); + *sizep = sizeof(IP6R); + *out = *tmp; + + for (i = 1; i < numranges; i++) + { + tmp = (IP6R *) DatumGetPointer(ent[i].key); + if (ip6_lessthan(&tmp->lower,&out->lower)) + out->lower = tmp->lower; + if (ip6_lessthan(&out->upper,&tmp->upper)) + out->upper = tmp->upper; + } + + PG_RETURN_IP6R_P(out); +} + +/* +** GiST Compress and Decompress methods for IP ranges +** do not do anything. +*/ +PG_FUNCTION_INFO_V1(gip6r_compress); +Datum +gip6r_compress(PG_FUNCTION_ARGS) +{ + PG_RETURN_POINTER(PG_GETARG_POINTER(0)); +} + +PG_FUNCTION_INFO_V1(gip6r_decompress); +Datum +gip6r_decompress(PG_FUNCTION_ARGS) +{ + PG_RETURN_POINTER(PG_GETARG_POINTER(0)); +} + +PG_FUNCTION_INFO_V1(gip6r_fetch); +Datum +gip6r_fetch(PG_FUNCTION_ARGS) +{ + PG_RETURN_POINTER(PG_GETARG_POINTER(0)); +} + +/* +** The GiST Penalty method for IP ranges +** As in the R-tree paper, we use change in area as our penalty metric +*/ +PG_FUNCTION_INFO_V1(gip6r_penalty); +Datum +gip6r_penalty(PG_FUNCTION_ARGS) +{ + GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0); + GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1); + float *result = (float *) PG_GETARG_POINTER(2); + IP6R *key = (IP6R *) DatumGetPointer(origentry->key); + IP6R *newkey = (IP6R *) DatumGetPointer(newentry->key); + IP6R ud; + double tmp = 0.0; + + /* rather than subtract the sizes, which might lose due to rounding errors, + * we calculate the actual number of addresses added to the range. + */ + + if (ip6_lessthan(&newkey->lower,&key->lower)) + { + ud.lower = newkey->lower; + ud.upper = key->lower; + ip6_sub_int(&ud.upper,1,&ud.upper); + tmp = ip6r_metric(&ud); + } + if (ip6_lessthan(&key->upper,&newkey->upper)) + { + ud.lower = key->upper; + ud.upper = newkey->upper; + ip6_sub_int(&ud.upper,1,&ud.upper); + tmp += ip6r_metric(&ud); + } + + /* + * we want to scale the result a bit. For one thing, the gist code implicitly + * assigns a penalty of 1e10 for a union of null and non-null values, and we + * want to keep our values less than that. For another, the penalty is sometimes + * summed across columns of a multi-column index, and we don't want our huge + * metrics (>2^80) to completely swamp anything else. + * + * So, we scale as the fourth power of the log2 of the computed penalty, which + * gives us a range 0 - 268435456. + */ + + *result = (float) pow(log(tmp+1) / log(2), 4); + +#ifdef GIST_DEBUG + fprintf(stderr, "penalty\n"); + fprintf(stderr, "\t%g\n", *result); +#endif + + PG_RETURN_POINTER(result); +} + + +/* Helper functions for picksplit. We might need to sort a list of + * ranges by size; these are for that. + */ + +struct gip6r_sort +{ + IP6R *key; + OffsetNumber pos; +}; + +static int +gip6r_sort_compare(const void *a, const void *b) +{ + double sa = ip6r_metric(((struct gip6r_sort *)a)->key); + double sb = ip6r_metric(((struct gip6r_sort *)b)->key); + return (sa > sb) ? 1 : ((sa == sb) ? 0 : -1); +} + +/* +** The GiST PickSplit method for IP ranges +** This is a linear-time algorithm based on a left/right split, +** based on the box functions in rtree_gist simplified to one +** dimension +*/ +PG_FUNCTION_INFO_V1(gip6r_picksplit); +Datum +gip6r_picksplit(PG_FUNCTION_ARGS) +{ + GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0); + GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1); + GISTENTRY *ent = GISTENTRYVEC(entryvec); + OffsetNumber i; + int nbytes; + OffsetNumber maxoff; + OffsetNumber *listL; + OffsetNumber *listR; + bool allisequal = true; + IP6R pageunion; + IP6R *cur; + IP6R *unionL; + IP6R *unionR; + int posL = 0; + int posR = 0; + + posL = posR = 0; + maxoff = GISTENTRYCOUNT(entryvec) - 1; + + cur = (IP6R *) DatumGetPointer(ent[FirstOffsetNumber].key); + pageunion = *cur; + + /* find MBR */ + for (i = OffsetNumberNext(FirstOffsetNumber); i <= maxoff; i = OffsetNumberNext(i)) + { + cur = (IP6R *) DatumGetPointer(ent[i].key); + if (allisequal == true && !ip6r_equal(&pageunion,cur)) + allisequal = false; + + if (ip6_lessthan(&cur->lower,&pageunion.lower)) + pageunion.lower = cur->lower; + if (ip6_lessthan(&pageunion.upper,&cur->upper)) + pageunion.upper = cur->upper; + } + + nbytes = (maxoff + 2) * sizeof(OffsetNumber); + listL = (OffsetNumber *) palloc(nbytes); + listR = (OffsetNumber *) palloc(nbytes); + unionL = palloc(sizeof(IP6R)); + unionR = palloc(sizeof(IP6R)); + v->spl_ldatum = PointerGetDatum(unionL); + v->spl_rdatum = PointerGetDatum(unionR); + v->spl_left = listL; + v->spl_right = listR; + + if (allisequal) + { + cur = (IP6R *) DatumGetPointer(ent[OffsetNumberNext(FirstOffsetNumber)].key); + if (ip6r_equal(cur, &pageunion)) + { + OffsetNumber split_at = FirstOffsetNumber + (maxoff - FirstOffsetNumber + 1)/2; + v->spl_nleft = v->spl_nright = 0; + *unionL = pageunion; + *unionR = pageunion; + + for (i = FirstOffsetNumber; i < split_at; i = OffsetNumberNext(i)) + v->spl_left[v->spl_nleft++] = i; + for (; i <= maxoff; i = OffsetNumberNext(i)) + v->spl_right[v->spl_nright++] = i; + + PG_RETURN_POINTER(v); + } + } + +#define ADDLIST( list_, u_, pos_, num_ ) do { \ + if ( pos_ ) { \ + if ( ip6_lessthan(&(u_)->upper, &(cur)->upper) ) (u_)->upper = (cur)->upper; \ + if ( ip6_lessthan(&(cur)->lower, &(u_)->lower) ) (u_)->lower = (cur)->lower; \ + } else { \ + *(u_) = *(cur); \ + } \ + (list_)[(pos_)++] = (num_); \ +} while(0) + + for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) + { + IP6 diff1; + IP6 diff2; + + cur = (IP6R *) DatumGetPointer(ent[i].key); + ip6_sub(&cur->lower, &pageunion.lower, &diff1); + ip6_sub(&pageunion.upper, &cur->upper, &diff2); + if (ip6_lessthan(&diff1,&diff2)) + ADDLIST(listL, unionL, posL, i); + else + ADDLIST(listR, unionR, posR, i); + } + + /* bad disposition, sort by ascending size and resplit */ + if (posR == 0 || posL == 0) + { + struct gip6r_sort *arr = (struct gip6r_sort *) + palloc(sizeof(struct gip6r_sort) * (maxoff + FirstOffsetNumber)); + + for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) + { + arr[i].key = (IP6R *) DatumGetPointer(ent[i].key); + arr[i].pos = i; + } + + qsort(arr + FirstOffsetNumber, + maxoff - FirstOffsetNumber + 1, + sizeof(struct gip6r_sort), + gip6r_sort_compare); + + posL = posR = 0; + for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) + { + IP6 diff1; + IP6 diff2; + + cur = arr[i].key; + ip6_sub(&cur->lower, &pageunion.lower, &diff1); + ip6_sub(&pageunion.upper, &cur->upper, &diff2); + + if (ip6_lessthan(&diff1,&diff2)) + ADDLIST(listL, unionL, posL, arr[i].pos); + else if (ip6_equal(&diff1,&diff2)) + { + if (posL > posR) + ADDLIST(listR, unionR, posR, arr[i].pos); + else + ADDLIST(listL, unionL, posL, arr[i].pos); + } + else + ADDLIST(listR, unionR, posR, arr[i].pos); + } + pfree(arr); + } + + v->spl_nleft = posL; + v->spl_nright = posR; + + PG_RETURN_POINTER(v); +} + +#undef ADDLIST + +/* +** Equality methods +*/ +PG_FUNCTION_INFO_V1(gip6r_same); +Datum +gip6r_same(PG_FUNCTION_ARGS) +{ + IP6R *v1 = (IP6R *) PG_GETARG_POINTER(0); + IP6R *v2 = (IP6R *) PG_GETARG_POINTER(1); + bool *result = (bool *) PG_GETARG_POINTER(2); + + if (v1 && v2) + *result = ip6r_equal(v1,v2); + else + *result = (v1 == NULL && v2 == NULL); + +#ifdef GIST_DEBUG + fprintf(stderr, "same: %s\n", (*result ? "true" : "false")); +#endif + + PG_RETURN_POINTER(result); +} + + +/* + * Strategy numbers: + * OPERATOR 1 >>= , + * OPERATOR 2 <<= , + * OPERATOR 3 >> , + * OPERATOR 4 << , + * OPERATOR 5 && , + * OPERATOR 6 = , + */ + +/* +** SUPPORT ROUTINES +*/ +static bool +gip6r_leaf_consistent(IP6R * key, + IP6R * query, + StrategyNumber strategy) +{ +#ifdef GIST_QUERY_DEBUG + fprintf(stderr, "leaf_consistent, %d\n", strategy); +#endif + + switch (strategy) + { + case 1: /* left contains right nonstrict */ + return ip6r_contains_internal(key, query, true); + case 2: /* left contained in right nonstrict */ + return ip6r_contains_internal(query, key, true); + case 3: /* left contains right strict */ + return ip6r_contains_internal(key, query, false); + case 4: /* left contained in right strict */ + return ip6r_contains_internal(query, key, false); + case 5: /* left overlaps right */ + return ip6r_overlaps_internal(key, query); + case 6: /* left equal right */ + return ip6r_equal(key, query); + default: + return false; + } +} + +/* logic notes: + * If the union value we're looking at overlaps with our query value + * at all, then any of the values underneath it might overlap with us + * or be contained by us, so all the "contained by" and "overlaps" + * cases degenerate to "overlap". + * If the union value is equal to the query value, then none of the + * values under it can strictly contain the query value, so for + * "contained" queries the strictness is preserved. + * If we're looking for an "equal" value, then we have to enter any + * subtree whose union contains (not strictly) our query value. + */ + +bool +gip6r_internal_consistent(IP6R * key, + IP6R * query, + StrategyNumber strategy) +{ +#ifdef GIST_QUERY_DEBUG + fprintf(stderr, "internal_consistent, %d\n", strategy); +#endif + + switch (strategy) + { + case 2: /* left contained in right nonstrict */ + case 4: /* left contained in right strict */ + case 5: /* left overlaps right */ + return ip6r_overlaps_internal(key, query); + case 3: /* left contains right strict */ + return ip6r_contains_internal(key, query, false); + case 1: /* left contains right nonstrict */ + case 6: /* left equal right */ + return ip6r_contains_internal(key, query, true); + default: + return false; + } +} + +/* end */ diff -Nru ip4r-2.3/src/ip6r_funcs.h ip4r-2.4/src/ip6r_funcs.h --- ip4r-2.3/src/ip6r_funcs.h 1970-01-01 00:00:00.000000000 +0000 +++ ip4r-2.4/src/ip6r_funcs.h 2018-11-21 06:35:30.000000000 +0000 @@ -0,0 +1,472 @@ +/* ip6r_funcs.h */ + +/**************************************************************************/ +/* This part is the internal implementation of all functionality, with no + * reference to the interface with postgres. That part comes later and is + * implemented in terms of these functions. + */ + +static inline +uint64 hostmask6_hi(unsigned masklen) +{ + if (masklen >= 64) + return 0; + if (masklen == 0) + return ~((uint64)0); + return (((uint64)(1U)) << (64-masklen)) - 1U; +} + +static inline +uint64 hostmask6_lo(unsigned masklen) +{ + if (masklen <= 64) + return ~((uint64)0); + return (((uint64)(1U)) << (128-masklen)) - 1U; +} + +static inline +uint64 netmask6_hi(unsigned masklen) +{ + return ~hostmask6_hi(masklen); +} + +static inline +uint64 netmask6_lo(unsigned masklen) +{ + return ~hostmask6_lo(masklen); +} + +/* if LO and HI are ends of a CIDR prefix, return the mask length. + * If not, returns ~0. + */ + +static inline +unsigned masklen64(uint64 lo, uint64 hi, int offset) +{ + uint64 d = (lo ^ hi) + 1; + int t = 0; + int b; + + /* at this point, d can be: + * 0 if A and B have all bits different + * 1 if A and B are equal + * 1 << (64-masklen) + * some other value if A and B are not ends of a CIDR range + * but in any case, after extracting the masklen, we have to + * recheck because some non-CIDR ranges will produce the same + * results. + */ + if (d == 0) + return (lo == 0 && hi == ~((uint64)0)) ? offset : ~0; + if (d == 1) + return (lo == hi) ? 64+offset : ~0; + + if (!(d & 0xFFFFFFFFUL)) + { + t = 32; + d >>= 32; + } + + b = ffs((uint32) d); + if ((((uint32)1U) << (b-1)) != d) + return ~0; + + { + uint64 mask = ((uint64)(1U) << (t+b-1)) - 1U; + if ((lo & mask) == 0 && (hi & mask) == mask) + return 65-t-b + offset; + } + + return ~0; +} + +static inline +unsigned masklen6(IP6 *lo, IP6 *hi) +{ + if (lo->bits[0] == hi->bits[0]) /* masklen >= 64 */ + { + return masklen64(lo->bits[1], hi->bits[1], 64); + } + else /* masklen < 64 */ + { + if (lo->bits[1] != 0 || hi->bits[1] != ~((uint64)0)) + return ~0U; + return masklen64(lo->bits[0], hi->bits[0], 0); + } +} + +static inline +bool ip6_valid_netmask(uint64 maskhi, uint64 masklo) +{ + uint64 d; + int fbit; + + if (maskhi == ~((uint64)0)) + d = ~masklo + 1; + else if (masklo == 0) + d = ~maskhi + 1; + else + return false; + + /* at this point, d can be: + * 0 if mask was 0x00000000 (valid) + * 1 << (32-masklen) (valid) + * some other value (invalid) + */ + + if (!(d & 0xFFFFFFFFUL)) + d >>= 32; + if (!d) + return true; + + fbit = ffs((uint32)d); + return ((uint32)(1U) << (fbit-1)) == d; +} + +static inline +void ip6_serialize(IP6 *ip, void *dest) +{ + unsigned char *p = dest; + p[0] = (ip->bits[0] >> 56); + p[1] = (ip->bits[0] >> 48); + p[2] = (ip->bits[0] >> 40); + p[3] = (ip->bits[0] >> 32); + p[4] = (ip->bits[0] >> 24); + p[5] = (ip->bits[0] >> 16); + p[6] = (ip->bits[0] >> 8); + p[7] = (ip->bits[0]); + p[8] = (ip->bits[1] >> 56); + p[9] = (ip->bits[1] >> 48); + p[10] = (ip->bits[1] >> 40); + p[11] = (ip->bits[1] >> 32); + p[12] = (ip->bits[1] >> 24); + p[13] = (ip->bits[1] >> 16); + p[14] = (ip->bits[1] >> 8); + p[15] = (ip->bits[1]); +} + +static inline +void ip6_deserialize(const void *src, IP6 *ip) +{ + const unsigned char *p = src; + ip->bits[0] = (((uint64)p[0] << 56) + | ((uint64)p[1] << 48) + | ((uint64)p[2] << 40) + | ((uint64)p[3] << 32) + | ((uint64)p[4] << 24) + | ((uint64)p[5] << 16) + | ((uint64)p[6] << 8) + | p[7]); + ip->bits[1] = (((uint64)p[8] << 56) + | ((uint64)p[9] << 48) + | ((uint64)p[10] << 40) + | ((uint64)p[11] << 32) + | ((uint64)p[12] << 24) + | ((uint64)p[13] << 16) + | ((uint64)p[14] << 8) + | p[15]); +} + +static inline +bool ip6_equal(IP6 *a, IP6 *b) +{ + return (a->bits[0] == b->bits[0]) && (a->bits[1] == b->bits[1]); +} + +static inline +int ip6_compare(IP6 *a, IP6 *b) +{ + if (a->bits[0] != b->bits[0]) + return (a->bits[0] > b->bits[0]) ? 1 : -1; + if (a->bits[1] != b->bits[1]) + return (a->bits[1] > b->bits[1]) ? 1 : -1; + return 0; +} + +static inline +bool ip6_lessthan(IP6 *a, IP6 *b) +{ + return ( (a->bits[0] < b->bits[0]) + || ((a->bits[0] == b->bits[0]) && (a->bits[1] < b->bits[1])) ); +} + +static inline +void ip6_sub(IP6 *minuend, IP6 *subtrahend, IP6 *result) +{ + result->bits[1] = minuend->bits[1] - subtrahend->bits[1]; + result->bits[0] = minuend->bits[0] - subtrahend->bits[0] - (minuend->bits[1] < subtrahend->bits[1]); +} + +static inline +void ip6_sub_int(IP6 *minuend, int subtrahend, IP6 *result) +{ + uint64 res_lo; + + if (subtrahend >= 0) + { + res_lo = minuend->bits[1] - (uint64)(subtrahend); + result->bits[0] = minuend->bits[0] - (res_lo > minuend->bits[1]); + } + else + { + res_lo = minuend->bits[1] + (uint64)(-subtrahend); + result->bits[0] = minuend->bits[0] + (res_lo < minuend->bits[1]); + } + + result->bits[1] = res_lo; +} + +static inline +bool ip6_in_range_internal(IP6 *val, IP6 *base, IP6 *offset, bool sub, bool less) +{ + IP6 diff; + + /* + * offset cannot be negative here since IP6 is unsigned + * + * val CMP (base OP offset) is equivalent to: + * (val - base) CMP (offset) when OP=+, + * note that if (base > val) then + * (val - base) <= offset is known true, + * (val - base) >= offset is known false, + * (offset) CMP (base - val) when OP=-, + * note that if (val > base) then + * offset >= (base - val) is known true, + * offset <= (base - val) is known false, + * so we can choose to do all of these tests in a way that + * avoids underflow of val - base. + */ + if (sub) + { + if (ip6_lessthan(base, val)) + return !less; + ip6_sub(base, val, &diff); + less = !less; + } + else + { + if (ip6_lessthan(val, base)) + return less; + ip6_sub(val, base, &diff); + } + if (less) + return !ip6_lessthan(offset,&diff); + else + return !ip6_lessthan(&diff,offset); +} + +static inline +bool ip6_in_range_internal_bits(IP6 *val, IP6 *base, int bits, bool sub, bool less) +{ + IP6 newbase = *base; + if (sub) + { + newbase.bits[0] &= netmask6_hi(bits); + newbase.bits[1] &= netmask6_lo(bits); + } + else + { + newbase.bits[0] |= hostmask6_hi(bits); + newbase.bits[1] |= hostmask6_lo(bits); + } + if (less) + return !ip6_lessthan(&newbase,val); /* val <= newbase */ + else + return !ip6_lessthan(val,&newbase); /* val >= newbase */ +} + + +static inline +bool ip6r_from_cidr(IP6 *prefix, unsigned masklen, IP6R *ipr) +{ + uint64 mask_lo = hostmask6_lo(masklen); + uint64 mask_hi = hostmask6_hi(masklen); + if (masklen > 128) + return false; + if ((prefix->bits[0] & mask_hi) || (prefix->bits[1] & mask_lo)) + return false; + ipr->upper.bits[0] = (prefix->bits[0] | mask_hi); + ipr->upper.bits[1] = (prefix->bits[1] | mask_lo); + ipr->lower = *prefix; + return true; +} + +static inline +bool ip6r_from_inet(IP6 *addr, unsigned masklen, IP6R *ipr) +{ + uint64 mask_lo = hostmask6_lo(masklen); + uint64 mask_hi = hostmask6_hi(masklen); + if (masklen > 128) + return false; + ipr->lower.bits[0] = (addr->bits[0] & ~mask_hi); + ipr->lower.bits[1] = (addr->bits[1] & ~mask_lo); + ipr->upper.bits[0] = (addr->bits[0] | mask_hi); + ipr->upper.bits[1] = (addr->bits[1] | mask_lo); + return true; +} + +static inline +bool ip6r_split_cidr(IP6R *val, IP6R *res) +{ + IP6 lo = val->lower; + IP6 hi = val->upper; + int len = 128; + IP6 mask; + IP6 tmp = lo; + + res->lower = lo; + res->upper = hi; + + if (masklen6(&lo,&hi) <= 128U) + return true; + + /* + * We know that all these cases are impossible because the CIDR check + * would catch them: + * + * lo==hi + * lo==0 && hi==~0 + * lo==~0 + * + * Therefore this loop must terminate before the mask overflows + */ + for(;;) + { + mask.bits[0] = hostmask6_hi(len-1); + mask.bits[1] = hostmask6_lo(len-1); + + if ( ((lo.bits[0] & mask.bits[0]) | (lo.bits[1] & mask.bits[1])) != 0 ) + break; + + tmp.bits[0] |= mask.bits[0]; + tmp.bits[1] |= mask.bits[1]; + + if (ip6_lessthan(&hi, &tmp)) + break; + + --len; + } + + tmp.bits[0] = lo.bits[0] | hostmask6_hi(len); + tmp.bits[1] = lo.bits[1] | hostmask6_lo(len); + + res->upper = tmp; + ip6_sub_int(&tmp, -1, &val->lower); + + return false; +} + +/* helpers for union/intersection for indexing */ + +/* note that this function has to handle the case where RESULT aliases + * either of A or B + */ + +static inline +IP6R *ip6r_union_internal(IP6R *a, IP6R *b, IP6R *result) +{ + if (ip6_lessthan(&a->lower,&b->lower)) + result->lower = a->lower; + else + result->lower = b->lower; + + if (ip6_lessthan(&b->upper,&a->upper)) + result->upper = a->upper; + else + result->upper = b->upper; + + return result; +} + +static inline +IP6R *ip6r_inter_internal(IP6R *a, IP6R *b, IP6R *result) +{ + if (ip6_lessthan(&a->upper,&b->lower) || ip6_lessthan(&b->upper,&a->lower)) + { + /* disjoint */ + result->lower.bits[0] = 0; + result->lower.bits[1] = 1; + result->upper.bits[0] = 0; /* INVALID VALUE */ + result->upper.bits[1] = 0; /* INVALID VALUE */ + return NULL; + } + + if (ip6_lessthan(&a->upper,&b->upper)) + result->upper = a->upper; + else + result->upper = b->upper; + + if (ip6_lessthan(&b->lower,&a->lower)) + result->lower = a->lower; + else + result->lower = b->lower; + + return result; +} + +static inline +double ip6r_metric(IP6R *v) +{ + IP6 diff; + double res = 0.0; + if (!v) + return res; + + ip6_sub(&v->upper, &v->lower, &diff); + + return ( (ldexp((double)diff.bits[0],64)) + + (diff.bits[1] + 1.0) ); +} + +/* comparisons */ + +static inline +bool ip6_less_eq(IP6 *a, IP6 *b) +{ + return !ip6_lessthan(b,a); +} + +static inline +bool ip6r_equal(IP6R *a, IP6R *b) +{ + return ip6_equal(&a->lower,&b->lower) && ip6_equal(&a->upper,&b->upper); +} + +static inline +bool ip6r_lessthan(IP6R *a, IP6R *b) +{ + switch (ip6_compare(&a->lower,&b->lower)) + { + default: return ip6_lessthan(&a->upper,&b->upper); + case -1: return true; + case 1: return false; + } +} + +static inline +bool ip6r_less_eq(IP6R *a, IP6R *b) +{ + return !ip6r_lessthan(b,a); +} + +static inline +bool ip6r_contains_internal(IP6R *left, IP6R *right, bool eqval) +{ + if (ip6r_equal(left,right)) + return eqval; + return !ip6_lessthan(&right->lower,&left->lower) && !ip6_lessthan(&left->upper,&right->upper); +} + +static inline +bool ip6r_overlaps_internal(IP6R *left, IP6R *right) +{ + return !ip6_lessthan(&left->upper,&right->lower) && !ip6_lessthan(&right->upper,&left->lower); +} + +static inline +bool ip6_contains_internal(IP6R *left, IP6 *right) +{ + return !ip6_lessthan(right,&left->lower) && !ip6_lessthan(&left->upper,right); +} + +/* end */ diff -Nru ip4r-2.3/src/ipaddr.c ip4r-2.4/src/ipaddr.c --- ip4r-2.3/src/ipaddr.c 1970-01-01 00:00:00.000000000 +0000 +++ ip4r-2.4/src/ipaddr.c 2018-11-21 06:35:30.000000000 +0000 @@ -0,0 +1,835 @@ +/* ipaddr.c */ + +#include "postgres.h" + +#include +#include + +#include "fmgr.h" +#include "funcapi.h" + +#include "access/gist.h" +#include "access/hash.h" +#include "access/skey.h" +#include "libpq/pqformat.h" +#include "utils/builtins.h" +#include "utils/elog.h" +#include "utils/numeric.h" +#include "utils/palloc.h" +#include "utils/varbit.h" + +#include "ipr_internal.h" + +#include "ip4r_funcs.h" +#include "ip6r_funcs.h" + +void ipaddr_internal_error(void) +{ + elog(ERROR,"Invalid IP datum"); + + /* just to shut the compiler up */ + abort(); +} + + +/* + * generic transforms of IP values - apply the specified ip4 or ip6 function + * to the given args according to parameter type. Where the result type is an + * IP, it's the same family as the parameter IP. + */ + +/* func(IP) returns Datum */ + +static inline +Datum +ipaddr_transform_1d(Datum d, PGFunction ip4func, PGFunction ip6func) +{ + IP_P ipp = DatumGetIP_P(d); + IP ip; + int af = ip_unpack(ipp, &ip); + + switch (af) + { + case PGSQL_AF_INET: + return DirectFunctionCall1(ip4func, IP4GetDatum(ip.ip4)); + + case PGSQL_AF_INET6: + return DirectFunctionCall1(ip6func, IP6PGetDatum(&ip.ip6)); + } + + ipaddr_internal_error(); +} + + +/* func(IP) returns IP */ + +static inline +IP_P +ipaddr_transform_1(Datum d, PGFunction ip4func, PGFunction ip6func) +{ + IP_P ipp = DatumGetIP_P(d); + IP ip; + int af = ip_unpack(ipp, &ip); + + switch (af) + { + case PGSQL_AF_INET: + ip.ip4 = DatumGetIP4(DirectFunctionCall1(ip4func, IP4GetDatum(ip.ip4))); + break; + + case PGSQL_AF_INET6: + ip.ip6 = *(DatumGetIP6P(DirectFunctionCall1(ip6func, IP6PGetDatum(&ip.ip6)))); + break; + + default: + ipaddr_internal_error(); + } + + return ip_pack(af, &ip); +} + + +/* func(IP, Datum) returns IP */ + +static inline +IP_P +ipaddr_transform_2d(Datum d1, Datum d2, PGFunction ip4func, PGFunction ip6func) +{ + IP_P ipp = DatumGetIP_P(d1); + IP ip; + int af = ip_unpack(ipp, &ip); + + switch (af) + { + case PGSQL_AF_INET: + ip.ip4 = DatumGetIP4(DirectFunctionCall2(ip4func, IP4GetDatum(ip.ip4), d2)); + break; + + case PGSQL_AF_INET6: + ip.ip6 = *(DatumGetIP6P(DirectFunctionCall2(ip6func, IP6PGetDatum(&ip.ip6), d2))); + break; + + default: + ipaddr_internal_error(); + } + + return ip_pack(af, &ip); +} + +/* func(IP,IP) returns IP; it's an error for the source IPs to be in different families */ + +static inline +IP_P +ipaddr_transform_2(Datum d1, Datum d2, PGFunction ip4func, PGFunction ip6func) +{ + IP_P ipp1 = DatumGetIP_P(d1); + IP_P ipp2 = DatumGetIP_P(d2); + IP ip1; + IP ip2; + IP out; + int af1 = ip_unpack(ipp1, &ip1); + int af2 = ip_unpack(ipp2, &ip2); + + if (af1 != af2) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid mixing of IP address families"))); + + switch (af1) + { + case PGSQL_AF_INET: + out.ip4 = DatumGetIP4(DirectFunctionCall2(ip4func, IP4GetDatum(ip1.ip4), IP4GetDatum(ip2.ip4))); + break; + + case PGSQL_AF_INET6: + out.ip6 = *(DatumGetIP6P(DirectFunctionCall2(ip6func, IP6PGetDatum(&ip1.ip6), IP6PGetDatum(&ip2.ip6)))); + break; + + default: + ipaddr_internal_error(); + } + + return ip_pack(af1, &out); +} + + + + +/* +#define GIST_DEBUG +#define GIST_QUERY_DEBUG +*/ + +static +text * +make_text(char *str, int len) +{ + text *ret = (text *) palloc(len + VARHDRSZ); + SET_VARSIZE(ret, len + VARHDRSZ); + if (str) + memcpy(VARDATA(ret), str, len); + else + memset(VARDATA(ret), 0, len); + return ret; +} + +static inline +void +set_text_len(text *txt, int len) +{ + if ((len + VARHDRSZ) < VARSIZE(txt)) + SET_VARSIZE(txt, len + VARHDRSZ); +} + + +/* +** Input/Output routines +*/ + +PG_FUNCTION_INFO_V1(ipaddr_in); +Datum +ipaddr_in(PG_FUNCTION_ARGS) +{ + char *str = PG_GETARG_CSTRING(0); + IP ip; + + if (strchr(str,':')) + { + if (ip6_raw_input(str, ip.ip6.bits)) + PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET6, &ip)); + } + else + { + if (ip4_raw_input(str, &ip.ip4)) + PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET, &ip)); + } + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid IP value: '%s'", str))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(ipaddr_out); +Datum +ipaddr_out(PG_FUNCTION_ARGS) +{ + IP_P ipp = PG_GETARG_IP_P(0); + char *out = palloc(IP6_STRING_MAX); + IP ip; + + switch (ip_unpack(ipp, &ip)) + { + case PGSQL_AF_INET: + ip4_raw_output(ip.ip4, out, IP6_STRING_MAX); + break; + case PGSQL_AF_INET6: + ip6_raw_output(ip.ip6.bits, out, IP6_STRING_MAX); + break; + } + + PG_RETURN_CSTRING(out); +} + +PG_FUNCTION_INFO_V1(ipaddr_recv); +Datum +ipaddr_recv(PG_FUNCTION_ARGS) +{ + StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); + IP ip; + int af, bits, nbytes; + + /* we copy the external format used by inet/cidr, just because. */ + + af = pq_getmsgbyte(buf); + if (af != PGSQL_AF_INET && af != PGSQL_AF_INET6) + ereport(ERROR, + (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), + errmsg("invalid address family in external IP value"))); + bits = pq_getmsgbyte(buf); + if (bits != ipr_af_maxbits(af)) + ereport(ERROR, + (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), + errmsg("invalid bit length in external IP value"))); + (void) pq_getmsgbyte(buf); /* ignore flag */ + nbytes = pq_getmsgbyte(buf); + if (nbytes*8 != bits) + ereport(ERROR, + (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), + errmsg("invalid address length in external IP value"))); + + switch (af) + { + case PGSQL_AF_INET: + ip.ip4 = (IP4) pq_getmsgint(buf, sizeof(IP4)); + break; + + case PGSQL_AF_INET6: + ip.ip6.bits[0] = pq_getmsgint64(buf); + ip.ip6.bits[1] = pq_getmsgint64(buf); + break; + } + + PG_RETURN_IP_P(ip_pack(af, &ip)); +} + +PG_FUNCTION_INFO_V1(ipaddr_send); +Datum +ipaddr_send(PG_FUNCTION_ARGS) +{ + IP_P arg1 = PG_GETARG_IP_P(0); + StringInfoData buf; + IP ip; + int af = ip_unpack(arg1, &ip); + + pq_begintypsend(&buf); + pq_sendbyte(&buf, af); + pq_sendbyte(&buf, (int8) ipr_af_maxbits(af)); + pq_sendbyte(&buf, 1); + pq_sendbyte(&buf, ip_sizeof(af)); + + switch (af) + { + case PGSQL_AF_INET: + pq_sendint(&buf, ip.ip4, sizeof(IP4)); + break; + + case PGSQL_AF_INET6: + pq_sendint64(&buf, ip.ip6.bits[0]); + pq_sendint64(&buf, ip.ip6.bits[1]); + break; + } + + PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); +} + +PG_FUNCTION_INFO_V1(ipaddr_hash); +Datum +ipaddr_hash(PG_FUNCTION_ARGS) +{ + IP_P arg1 = PG_GETARG_IP_P(0); + + return hash_any((void*)(VARDATA_ANY(arg1)), VARSIZE_ANY_EXHDR(arg1)); +} + +PG_FUNCTION_INFO_V1(ipaddr_hash_extended); +Datum +ipaddr_hash_extended(PG_FUNCTION_ARGS) +{ + IP_P arg1 = PG_GETARG_IP_P(0); + uint64 seed = DatumGetUInt64(PG_GETARG_DATUM(1)); + + return hash_any_extended((void*)(VARDATA_ANY(arg1)), VARSIZE_ANY_EXHDR(arg1), seed); +} + +PG_FUNCTION_INFO_V1(ipaddr_cast_to_text); +Datum +ipaddr_cast_to_text(PG_FUNCTION_ARGS) +{ + IP_P ipp = PG_GETARG_IP_P(0); + IP ip; + int af = ip_unpack(ipp, &ip); + text *out = NULL; + + switch (af) + { + case PGSQL_AF_INET: + out = make_text(NULL, IP4_STRING_MAX); + set_text_len(out, ip4_raw_output(ip.ip4, VARDATA(out), IP4_STRING_MAX)); + break; + case PGSQL_AF_INET6: + out = make_text(NULL, IP6_STRING_MAX); + set_text_len(out, ip6_raw_output(ip.ip6.bits, VARDATA(out), IP6_STRING_MAX)); + break; + } + + PG_RETURN_TEXT_P(out); +} + +PG_FUNCTION_INFO_V1(ipaddr_cast_from_text); +Datum +ipaddr_cast_from_text(PG_FUNCTION_ARGS) +{ + text *txt = PG_GETARG_TEXT_PP(0); + int tlen = VARSIZE_ANY_EXHDR(txt); + char buf[IP6_STRING_MAX]; + + if (tlen < sizeof(buf)) + { + IP ip; + + memcpy(buf, VARDATA_ANY(txt), tlen); + buf[tlen] = 0; + + if (strchr(buf,':')) + { + if (ip6_raw_input(buf, ip.ip6.bits)) + PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET6, &ip)); + } + else + { + if (ip4_raw_input(buf, &ip.ip4)) + PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET, &ip)); + } + } + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid IP value in text"))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(ipaddr_cast_from_inet); +Datum +ipaddr_cast_from_inet(PG_FUNCTION_ARGS) +{ + inet *inetptr = PG_GETARG_INET_P(0); + inet_struct *in = INET_STRUCT_DATA(inetptr); + IP ip; + + switch (in->family) + { + case PGSQL_AF_INET: + ip.ip4 = DatumGetIP4(DirectFunctionCall1(ip4_cast_from_inet, InetPGetDatum(inetptr))); + PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET, &ip)); + case PGSQL_AF_INET6: + ip.ip6 = *(DatumGetIP6P(DirectFunctionCall1(ip6_cast_from_inet, InetPGetDatum(inetptr)))); + PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET6, &ip)); + } + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid INET value for conversion to IP"))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(ipaddr_cast_to_cidr); +Datum +ipaddr_cast_to_cidr(PG_FUNCTION_ARGS) +{ + PG_RETURN_DATUM(ipaddr_transform_1d(PG_GETARG_DATUM(0), ip4_cast_to_cidr, ip6_cast_to_cidr)); +} + + +PG_FUNCTION_INFO_V1(ipaddr_cast_to_numeric); +Datum +ipaddr_cast_to_numeric(PG_FUNCTION_ARGS) +{ + PG_RETURN_DATUM(ipaddr_transform_1d(PG_GETARG_DATUM(0), ip4_cast_to_numeric, ip6_cast_to_numeric)); +} + +PG_FUNCTION_INFO_V1(ipaddr_cast_from_ip4); +Datum +ipaddr_cast_from_ip4(PG_FUNCTION_ARGS) +{ + IP ip; + + ip.ip4 = PG_GETARG_IP4(0); + + PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET, &ip)); +} + +PG_FUNCTION_INFO_V1(ipaddr_cast_from_ip6); +Datum +ipaddr_cast_from_ip6(PG_FUNCTION_ARGS) +{ + IP6 *in = PG_GETARG_IP6_P(0); + IP ip; + + ip.ip6 = *in; + + PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET6, &ip)); +} + + +PG_FUNCTION_INFO_V1(ipaddr_cast_to_ip4); +Datum +ipaddr_cast_to_ip4(PG_FUNCTION_ARGS) +{ + IP_P ipp = PG_GETARG_IP_P(0); + IP ip; + + if (ip_unpack(ipp, &ip) == PGSQL_AF_INET) + { + PG_RETURN_IP4(ip.ip4); + } + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid IP value in cast to IP4"))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(ipaddr_cast_to_ip6); +Datum +ipaddr_cast_to_ip6(PG_FUNCTION_ARGS) +{ + IP_P ipp = PG_GETARG_IP_P(0); + IP ip; + + if (ip_unpack(ipp, &ip) == PGSQL_AF_INET6) + { + IP6 *out = palloc(sizeof(IP6)); + *out = ip.ip6; + PG_RETURN_IP6_P(out); + } + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid IP value in cast to IP4"))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(ipaddr_cast_from_bit); +Datum +ipaddr_cast_from_bit(PG_FUNCTION_ARGS) +{ + VarBit *val = PG_GETARG_VARBIT_P(0); + IP ip; + + switch (VARBITLEN(val)) + { + case 32: + ip.ip4 = DatumGetIP4(DirectFunctionCall1(ip4_cast_from_bit, VarBitPGetDatum(val))); + PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET, &ip)); + case 128: + ip.ip6 = *(DatumGetIP6P(DirectFunctionCall1(ip6_cast_from_bit, VarBitPGetDatum(val)))); + PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET6, &ip)); + } + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid BIT value for conversion to IPADDRESS"))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(ipaddr_cast_to_bit); +Datum +ipaddr_cast_to_bit(PG_FUNCTION_ARGS) +{ + PG_RETURN_DATUM(ipaddr_transform_1d(PG_GETARG_DATUM(0), ip4_cast_to_bit, ip6_cast_to_bit)); +} + +PG_FUNCTION_INFO_V1(ipaddr_cast_from_bytea); +Datum +ipaddr_cast_from_bytea(PG_FUNCTION_ARGS) +{ + void *val = PG_GETARG_BYTEA_PP(0); + IP ip; + + switch (VARSIZE_ANY_EXHDR(val)) + { + case 4: + ip.ip4 = DatumGetIP4(DirectFunctionCall1(ip4_cast_from_bytea, PointerGetDatum(val))); + PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET, &ip)); + case 16: + ip.ip6 = *(DatumGetIP6P(DirectFunctionCall1(ip6_cast_from_bytea, PointerGetDatum(val)))); + PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET6, &ip)); + } + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid BYTEA value for conversion to IPADDRESS"))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(ipaddr_cast_to_bytea); +Datum +ipaddr_cast_to_bytea(PG_FUNCTION_ARGS) +{ + PG_RETURN_DATUM(ipaddr_transform_1d(PG_GETARG_DATUM(0), ip4_cast_to_bytea, ip6_cast_to_bytea)); +} + + +PG_FUNCTION_INFO_V1(ipaddr_family); +Datum +ipaddr_family(PG_FUNCTION_ARGS) +{ + IP_P ipp = PG_GETARG_IP_P(0); + IP ip; + + if (ip_unpack(ipp, &ip) == PGSQL_AF_INET6) + PG_RETURN_INT32(6); + else + PG_RETURN_INT32(4); +} + + +PG_FUNCTION_INFO_V1(ipaddr_net_lower); +Datum +ipaddr_net_lower(PG_FUNCTION_ARGS) +{ + PG_RETURN_IP_P(ipaddr_transform_2d(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), ip4_net_lower, ip6_net_lower)); +} + +PG_FUNCTION_INFO_V1(ipaddr_net_upper); +Datum +ipaddr_net_upper(PG_FUNCTION_ARGS) +{ + PG_RETURN_IP_P(ipaddr_transform_2d(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), ip4_net_upper, ip6_net_upper)); +} + +PG_FUNCTION_INFO_V1(ipaddr_plus_int); +Datum +ipaddr_plus_int(PG_FUNCTION_ARGS) +{ + PG_RETURN_IP_P(ipaddr_transform_2d(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), ip4_plus_int, ip6_plus_int)); +} + +PG_FUNCTION_INFO_V1(ipaddr_plus_bigint); +Datum +ipaddr_plus_bigint(PG_FUNCTION_ARGS) +{ + PG_RETURN_IP_P(ipaddr_transform_2d(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), ip4_plus_bigint, ip6_plus_bigint)); +} + +PG_FUNCTION_INFO_V1(ipaddr_plus_numeric); +Datum +ipaddr_plus_numeric(PG_FUNCTION_ARGS) +{ + PG_RETURN_IP_P(ipaddr_transform_2d(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), ip4_plus_numeric, ip6_plus_numeric)); +} + +PG_FUNCTION_INFO_V1(ipaddr_minus_int); +Datum +ipaddr_minus_int(PG_FUNCTION_ARGS) +{ + PG_RETURN_IP_P(ipaddr_transform_2d(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), ip4_minus_int, ip6_minus_int)); +} + +PG_FUNCTION_INFO_V1(ipaddr_minus_bigint); +Datum +ipaddr_minus_bigint(PG_FUNCTION_ARGS) +{ + PG_RETURN_IP_P(ipaddr_transform_2d(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), ip4_minus_bigint, ip6_minus_bigint)); +} + +PG_FUNCTION_INFO_V1(ipaddr_minus_numeric); +Datum +ipaddr_minus_numeric(PG_FUNCTION_ARGS) +{ + PG_RETURN_IP_P(ipaddr_transform_2d(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), ip4_minus_numeric, ip6_minus_numeric)); +} + +PG_FUNCTION_INFO_V1(ipaddr_minus_ipaddr); +Datum +ipaddr_minus_ipaddr(PG_FUNCTION_ARGS) +{ + Datum minuend = PG_GETARG_DATUM(0); + Datum subtrahend = PG_GETARG_DATUM(1); + Datum res; + IP ip1; + IP ip2; + int af1 = ip_unpack(DatumGetIP_P(minuend), &ip1); + int af2 = ip_unpack(DatumGetIP_P(subtrahend), &ip2); + + if (af1 != af2) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid mixing of IP address families"))); + + switch (af1) + { + case PGSQL_AF_INET: + res = DirectFunctionCall2(numeric_sub, + DirectFunctionCall1(ip4_cast_to_numeric,IP4GetDatum(ip1.ip4)), + DirectFunctionCall1(ip4_cast_to_numeric,IP4GetDatum(ip2.ip4))); + break; + + case PGSQL_AF_INET6: + res = DirectFunctionCall2(numeric_sub, + DirectFunctionCall1(ip6_cast_to_numeric,IP6PGetDatum(&ip1.ip6)), + DirectFunctionCall1(ip6_cast_to_numeric,IP6PGetDatum(&ip2.ip6))); + break; + + default: + ipaddr_internal_error(); + } + + PG_RETURN_DATUM(res); +} + +PG_FUNCTION_INFO_V1(ipaddr_and); +Datum +ipaddr_and(PG_FUNCTION_ARGS) +{ + PG_RETURN_IP_P(ipaddr_transform_2(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), ip4_and, ip6_and)); +} + +PG_FUNCTION_INFO_V1(ipaddr_or); +Datum +ipaddr_or(PG_FUNCTION_ARGS) +{ + PG_RETURN_IP_P(ipaddr_transform_2(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), ip4_or, ip6_or)); +} + +PG_FUNCTION_INFO_V1(ipaddr_xor); +Datum +ipaddr_xor(PG_FUNCTION_ARGS) +{ + PG_RETURN_IP_P(ipaddr_transform_2(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), ip4_xor, ip6_xor)); +} + +PG_FUNCTION_INFO_V1(ipaddr_not); +Datum +ipaddr_not(PG_FUNCTION_ARGS) +{ + PG_RETURN_IP_P(ipaddr_transform_1(PG_GETARG_DATUM(0), ip4_not, ip6_not)); +} + + +/* + * generic boolean comparison of two IPs. If in the same family, then the + * passed-in comparison function is called; if in different families, then + * the result is mismatch_af1 or _af2 according to which of the first or + * second address is in the larger family. + */ + +static inline +bool +ipaddr_comparison_bool(Datum d1, Datum d2, + bool mismatch_af1, bool mismatch_af2, + PGFunction ip4func, PGFunction ip6func) +{ + IP_P ipp1 = DatumGetIP_P(d1); + IP_P ipp2 = DatumGetIP_P(d2); + IP ip1; + IP ip2; + int af1 = ip_unpack(ipp1, &ip1); + int af2 = ip_unpack(ipp2, &ip2); + bool retval; + + if (af1 != af2) + { + retval = (af1 > af2) ? mismatch_af1 : mismatch_af2; + } + else + { + switch (af1) + { + case PGSQL_AF_INET: + retval = DatumGetBool(DirectFunctionCall2(ip4func, IP4GetDatum(ip1.ip4), IP4GetDatum(ip2.ip4))); + break; + + case PGSQL_AF_INET6: + retval = DatumGetBool(DirectFunctionCall2(ip6func, IP6PGetDatum(&ip1.ip6), IP6PGetDatum(&ip2.ip6))); + break; + + default: + ipaddr_internal_error(); + } + } + + if ((Pointer)ipp1 != DatumGetPointer(d1)) + pfree(ipp1); + if ((Pointer)ipp2 != DatumGetPointer(d2)) + pfree(ipp2); + + return retval; +} + +PG_FUNCTION_INFO_V1(ipaddr_lt); +Datum +ipaddr_lt(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( + ipaddr_comparison_bool(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), + false, true, + ip4_lt, ip6_lt)); +} + +PG_FUNCTION_INFO_V1(ipaddr_le); +Datum +ipaddr_le(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( + ipaddr_comparison_bool(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), + false, true, + ip4_le, ip6_le)); +} + +PG_FUNCTION_INFO_V1(ipaddr_gt); +Datum +ipaddr_gt(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( + ipaddr_comparison_bool(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), + true, false, + ip4_gt, ip6_gt)); +} + +PG_FUNCTION_INFO_V1(ipaddr_ge); +Datum +ipaddr_ge(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( + ipaddr_comparison_bool(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), + true, false, + ip4_ge, ip6_ge)); +} + +PG_FUNCTION_INFO_V1(ipaddr_eq); +Datum +ipaddr_eq(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( + ipaddr_comparison_bool(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), + false, false, + ip4_eq, ip6_eq)); +} + +PG_FUNCTION_INFO_V1(ipaddr_neq); +Datum +ipaddr_neq(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( + ipaddr_comparison_bool(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1), + true, true, + ip4_neq, ip6_neq)); +} + + +/***************************************************************************** + * Btree functions + *****************************************************************************/ + +PG_FUNCTION_INFO_V1(ipaddr_cmp); +Datum +ipaddr_cmp(PG_FUNCTION_ARGS) +{ + IP_P ipp1 = PG_GETARG_IP_P(0); + IP_P ipp2 = PG_GETARG_IP_P(1); + IP ip1; + IP ip2; + int af1 = ip_unpack(ipp1, &ip1); + int af2 = ip_unpack(ipp2, &ip2); + int32 retval; + + if (af1 != af2) + { + retval = (af1 > af2) ? 1 : -1; + } + else + { + switch (af1) + { + case PGSQL_AF_INET: + retval = DatumGetInt32(DirectFunctionCall2(ip4_cmp, IP4GetDatum(ip1.ip4), IP4GetDatum(ip2.ip4))); + break; + + case PGSQL_AF_INET6: + retval = DatumGetInt32(DirectFunctionCall2(ip6_cmp, IP6PGetDatum(&ip1.ip6), IP6PGetDatum(&ip2.ip6))); + break; + + default: + ipaddr_internal_error(); + } + } + + PG_FREE_IF_COPY(ipp1,0); + PG_FREE_IF_COPY(ipp2,1); + + PG_RETURN_INT32(retval); +} + +/* end */ diff -Nru ip4r-2.3/src/iprange.c ip4r-2.4/src/iprange.c --- ip4r-2.3/src/iprange.c 1970-01-01 00:00:00.000000000 +0000 +++ ip4r-2.4/src/iprange.c 2018-11-21 06:35:30.000000000 +0000 @@ -0,0 +1,2443 @@ +/* iprange.c */ + +#include "postgres.h" + +#include +#include + +#include "fmgr.h" +#include "funcapi.h" + +#include "access/gist.h" +#include "access/hash.h" +#include "access/skey.h" +#include "libpq/pqformat.h" +#include "utils/builtins.h" +#include "utils/elog.h" +#include "utils/numeric.h" +#include "utils/palloc.h" +#include "utils/varbit.h" + +#include "ipr_internal.h" + +#include "ip4r_funcs.h" +#include "ip6r_funcs.h" + +/* + * Some C compilers including GCC really get confused by the use of the IP and + * IPR unions, generating a lot of completely spurious "may be used + * uninitialized" warnings. The various uses of IP*_INITIALIZER in this file + * ought to be unnecessary; so this macro is used to make them conditional for + * ease of experimentation. + */ + +#define XINIT(_i) = _i + +static void iprange_internal_error(void) __attribute__((noreturn,noinline)); +static void iprange_af_mismatch(void) __attribute__((noreturn,noinline)); + +static +void iprange_internal_error(void) +{ + elog(ERROR,"Invalid IPR datum"); + + /* just to shut the compiler up */ + abort(); +} + +static +void iprange_af_mismatch(void) +{ + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid mixing of IP address families"))); + /* just to shut the compiler up */ + abort(); +} + + +/* + * Rather than use 32 bytes + length for every IP range, we make the + * assumption that most ranges (at least in table data and hence gist + * leaf nodes) will be CIDRs, and many of those /64 or shorter. + * + * So we allow the following formats (excluding varlena header): + * + * 0 bytes - special 'match all' range (af==0) + * 8 bytes - IP4R + * 1 byte pfxlen + 8 bytes - IP6R cidr range /64 or shorter + * 1 byte pfxlen + 16 bytes - IP6R cidr range /65 or longer + * 32 bytes - arbitrary IP6R range + */ + +int ipr_unpack(IPR_P in, IPR *out) +{ + unsigned char *ptr = (unsigned char *) VARDATA_ANY(in); + + switch (VARSIZE_ANY_EXHDR(in)) + { + case 0: + return 0; + + case sizeof(IP4R): + memcpy(&out->ip4r, ptr, sizeof(IP4R)); + return PGSQL_AF_INET; + + case 1+sizeof(uint64): + { + unsigned pfxlen = *ptr++; + memcpy(out->ip6r.lower.bits, ptr, sizeof(uint64)); + out->ip6r.lower.bits[1] = 0; + out->ip6r.upper.bits[0] = out->ip6r.lower.bits[0] | hostmask6_hi(pfxlen); + out->ip6r.upper.bits[1] = hostmask6_lo(pfxlen); + return PGSQL_AF_INET6; + } + + case 1+sizeof(IP6): + { + unsigned pfxlen = *ptr++; + memcpy(&out->ip6r.lower, ptr, sizeof(IP6)); + out->ip6r.upper.bits[0] = out->ip6r.lower.bits[0] | hostmask6_hi(pfxlen); + out->ip6r.upper.bits[1] = out->ip6r.lower.bits[1] | hostmask6_lo(pfxlen); + return PGSQL_AF_INET6; + } + + case sizeof(IP6R): + memcpy(&out->ip6r, ptr, sizeof(IP6R)); + return PGSQL_AF_INET6; + + default: + iprange_internal_error(); + } +} + +IPR_P ipr_pack(int af, IPR *val) +{ + IPR_P out = palloc(VARHDRSZ + sizeof(IP6R)); + unsigned char *ptr = (unsigned char *) VARDATA(out); + + switch (af) + { + case 0: + SET_VARSIZE(out, VARHDRSZ); + break; + + case PGSQL_AF_INET: + memcpy(ptr, &val->ip4r, sizeof(IP4R)); + SET_VARSIZE(out, VARHDRSZ + sizeof(IP4R)); + break; + + case PGSQL_AF_INET6: + { + unsigned pfxlen = masklen6(&val->ip6r.lower, &val->ip6r.upper); + if (pfxlen <= 64) + { + *ptr++ = pfxlen; + memcpy(ptr, val->ip6r.lower.bits, sizeof(uint64)); + SET_VARSIZE(out, VARHDRSZ + 1 + sizeof(uint64)); + } + else if (pfxlen <= 128) + { + *ptr++ = pfxlen; + memcpy(ptr, &val->ip6r.lower, sizeof(IP6)); + SET_VARSIZE(out, VARHDRSZ + 1 + sizeof(IP6)); + } + else + { + memcpy(ptr, &val->ip6r, sizeof(IP6R)); + SET_VARSIZE(out, VARHDRSZ + sizeof(IP6R)); + } + break; + } + + default: + iprange_internal_error(); + } + + return out; +} + + +/**************************************************************************/ +/* This part handles all aspects of postgres interfacing. + */ + +/* +** Input/Output routines +*/ + +/*---- ipr ----*/ + +PG_FUNCTION_INFO_V1(iprange_in); +Datum +iprange_in(PG_FUNCTION_ARGS) +{ + char *str = PG_GETARG_CSTRING(0); + IPR ipr; + + if (str[0] == '-' && str[1] == 0) + { + PG_RETURN_IPR_P(ipr_pack(0, NULL)); + } + else if (strchr(str,':')) + { + ipr.ip6r = *DatumGetIP6RP(DirectFunctionCall1(ip6r_in,CStringGetDatum(str))); + PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET6, &ipr)); + } + else + { + ipr.ip4r = *DatumGetIP4RP(DirectFunctionCall1(ip4r_in,CStringGetDatum(str))); + PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET, &ipr)); + } +} + +PG_FUNCTION_INFO_V1(iprange_out); +Datum +iprange_out(PG_FUNCTION_ARGS) +{ + IPR_P *iprp = PG_GETARG_IPR_P(0); + IPR ipr; + int af = ipr_unpack(iprp, &ipr); + + switch (af) + { + case 0: + { + char *out = palloc(2); + strcpy(out,"-"); + PG_RETURN_CSTRING(out); + } + + case PGSQL_AF_INET: + PG_RETURN_DATUM(DirectFunctionCall1(ip4r_out,IP4RPGetDatum(&ipr.ip4r))); + + case PGSQL_AF_INET6: + PG_RETURN_DATUM(DirectFunctionCall1(ip6r_out,IP6RPGetDatum(&ipr.ip6r))); + + default: + iprange_internal_error(); + } +} + +PG_FUNCTION_INFO_V1(iprange_recv); +Datum +iprange_recv(PG_FUNCTION_ARGS) +{ + StringInfo buf = (StringInfo) PG_GETARG_POINTER(0); + IPR ipr; + unsigned af, bits, nbytes; + + /* + * This isn't quite the same format as inet/cidr but we keep reasonably + * close for no very good reason. + * + * 1 byte AF + * 1 byte pfx len (255 if the range is not a prefix) + * 1 byte flag (unused) + * 1 byte number of remaining bytes (0,4,8,16 or 32) + * + */ + + af = pq_getmsgbyte(buf); + if (af != 0 && af != PGSQL_AF_INET && af != PGSQL_AF_INET6) + ereport(ERROR, + (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), + errmsg("invalid address family in external IPR value"))); + bits = pq_getmsgbyte(buf); + if (bits != 255 && bits > ipr_af_maxbits(af)) + ereport(ERROR, + (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), + errmsg("invalid bit length in external IP value"))); + (void) pq_getmsgbyte(buf); /* ignore flag */ + nbytes = pq_getmsgbyte(buf); + + switch (af) + { + case 0: /* special 'match all' range */ + if (nbytes == 0) + PG_RETURN_IPR_P(ipr_pack(0,NULL)); + break; + + case PGSQL_AF_INET: + if (nbytes == sizeof(IP4) && bits <= ipr_af_maxbits(PGSQL_AF_INET)) + { + ipr.ip4r.lower = (IP4) pq_getmsgint(buf, sizeof(IP4)); + ipr.ip4r.upper = ipr.ip4r.lower | hostmask(bits); + PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET,&ipr)); + } + else if (nbytes == sizeof(IP4R)) + { + ipr.ip4r.lower = (IP4) pq_getmsgint(buf, sizeof(IP4)); + ipr.ip4r.upper = (IP4) pq_getmsgint(buf, sizeof(IP4)); + PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET,&ipr)); + } + break; + + case PGSQL_AF_INET6: + if (nbytes == sizeof(uint64) && bits <= 64) + { + ipr.ip6r.lower.bits[0] = (uint64) pq_getmsgint64(buf); + ipr.ip6r.lower.bits[1] = 0; + ipr.ip6r.upper.bits[0] = ipr.ip6r.lower.bits[0] | hostmask6_hi(bits); + ipr.ip6r.upper.bits[1] = ~(uint64)0; + PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET6,&ipr)); + } + else if (nbytes == sizeof(IP6) && bits <= ipr_af_maxbits(PGSQL_AF_INET6)) + { + ipr.ip6r.lower.bits[0] = (uint64) pq_getmsgint64(buf); + ipr.ip6r.lower.bits[1] = (uint64) pq_getmsgint64(buf); + ipr.ip6r.upper.bits[0] = ipr.ip6r.lower.bits[0] | hostmask6_hi(bits); + ipr.ip6r.upper.bits[1] = ipr.ip6r.lower.bits[1] | hostmask6_lo(bits); + PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET6,&ipr)); + } + else if (nbytes == sizeof(IP6R)) + { + ipr.ip6r.lower.bits[0] = (uint64) pq_getmsgint64(buf); + ipr.ip6r.lower.bits[1] = (uint64) pq_getmsgint64(buf); + ipr.ip6r.upper.bits[0] = (uint64) pq_getmsgint64(buf); + ipr.ip6r.upper.bits[1] = (uint64) pq_getmsgint64(buf); + PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET6,&ipr)); + } + break; + } + + ereport(ERROR, + (errcode(ERRCODE_INVALID_BINARY_REPRESENTATION), + errmsg("invalid address length in external IPR value"))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(iprange_send); +Datum +iprange_send(PG_FUNCTION_ARGS) +{ + IPR_P *iprp = PG_GETARG_IPR_P(0); + IPR ipr; + int af = ipr_unpack(iprp, &ipr); + StringInfoData buf; + unsigned bits = ~0; + + switch (af) + { + case PGSQL_AF_INET: + bits = masklen(ipr.ip4r.lower,ipr.ip4r.upper); + break; + case PGSQL_AF_INET6: + bits = masklen6(&ipr.ip6r.lower,&ipr.ip6r.upper); + break; + } + + pq_begintypsend(&buf); + pq_sendbyte(&buf, af); + pq_sendbyte(&buf, (int8) bits); + pq_sendbyte(&buf, 1); + + switch (af) + { + case 0: + pq_sendbyte(&buf,0); + break; + + case PGSQL_AF_INET: + if (bits <= ipr_af_maxbits(PGSQL_AF_INET)) + { + pq_sendbyte(&buf, sizeof(IP4)); + pq_sendint(&buf, ipr.ip4r.lower, sizeof(IP4)); + } + else + { + pq_sendbyte(&buf, sizeof(IP4R)); + pq_sendint(&buf, ipr.ip4r.lower, sizeof(IP4)); + pq_sendint(&buf, ipr.ip4r.upper, sizeof(IP4)); + } + break; + + case PGSQL_AF_INET6: + if (bits <= 64) + { + pq_sendbyte(&buf, sizeof(uint64)); + pq_sendint64(&buf, ipr.ip6r.lower.bits[0]); + } + else if (bits <= ipr_af_maxbits(PGSQL_AF_INET6)) + { + pq_sendbyte(&buf, sizeof(IP6)); + pq_sendint64(&buf, ipr.ip6r.lower.bits[0]); + pq_sendint64(&buf, ipr.ip6r.lower.bits[1]); + } + else + { + pq_sendbyte(&buf, sizeof(IP6R)); + pq_sendint64(&buf, ipr.ip6r.lower.bits[0]); + pq_sendint64(&buf, ipr.ip6r.lower.bits[1]); + pq_sendint64(&buf, ipr.ip6r.upper.bits[0]); + pq_sendint64(&buf, ipr.ip6r.upper.bits[1]); + } + break; + } + + PG_RETURN_BYTEA_P(pq_endtypsend(&buf)); +} + +/* Unfortunately due to a historical oversight, this function produces + * different hash values for ipv6 cidr ranges than ip6rhash. This is + * undesirable for a hash function since it would block future attempts to add + * cross-type comparisons, and if this behaviour were to be propagated into + * the extended hash function then it would become cast in stone, thanks to + * hash partitioning. + * + * So we make the old sql-callable function name keep using the old hash, so + * that anyone manually using iprangehash for partitioning or whatever is + * unaffected, but change the actual hash opclass to use new names. + */ + +PG_FUNCTION_INFO_V1(iprange_hash); +Datum +iprange_hash(PG_FUNCTION_ARGS) +{ + IPR_P arg1 = PG_GETARG_IPR_P(0); + + return hash_any((void *) VARDATA_ANY(arg1), VARSIZE_ANY_EXHDR(arg1)); +} + +/* below are the fixed hash functions + */ + +PG_FUNCTION_INFO_V1(iprange_hash_new); +Datum +iprange_hash_new(PG_FUNCTION_ARGS) +{ + IPR_P arg1 = PG_GETARG_IPR_P(0); + IPR tmp; + uint32 vsize = VARSIZE_ANY_EXHDR(arg1); + + if (vsize <= sizeof(IP4R) || vsize == sizeof(IP6R)) + return hash_any((void *) VARDATA_ANY(arg1), vsize); + + if (ipr_unpack(arg1,&tmp) != PGSQL_AF_INET6) + iprange_internal_error(); + + return hash_any((void *) &tmp, sizeof(IP6R)); +} + +PG_FUNCTION_INFO_V1(iprange_hash_extended); +Datum +iprange_hash_extended(PG_FUNCTION_ARGS) +{ + IPR_P arg1 = PG_GETARG_IPR_P(0); + IPR tmp; + uint32 vsize = VARSIZE_ANY_EXHDR(arg1); + uint32 seed = DatumGetUInt32(PG_GETARG_DATUM(1)); + + if (vsize <= sizeof(IP4R) || vsize == sizeof(IP6R)) + return hash_any_extended((void *) VARDATA_ANY(arg1), vsize, seed); + + if (ipr_unpack(arg1,&tmp) != PGSQL_AF_INET6) + iprange_internal_error(); + + return hash_any_extended((void *) &tmp, sizeof(IP6R), seed); +} + +PG_FUNCTION_INFO_V1(iprange_cast_to_text); +Datum +iprange_cast_to_text(PG_FUNCTION_ARGS) +{ + IPR_P iprp = PG_GETARG_IPR_P(0); + IPR ipr; + int af = ipr_unpack(iprp,&ipr); + + switch (af) + { + case 0: + { + text *out = cstring_to_text_with_len("-",1); + PG_RETURN_TEXT_P(out); + } + + case PGSQL_AF_INET: + PG_RETURN_DATUM(DirectFunctionCall1(ip4r_cast_to_text,IP4RPGetDatum(&ipr.ip4r))); + + case PGSQL_AF_INET6: + PG_RETURN_DATUM(DirectFunctionCall1(ip6r_cast_to_text,IP6RPGetDatum(&ipr.ip6r))); + + default: + iprange_internal_error(); + } +} + +PG_FUNCTION_INFO_V1(iprange_cast_from_text); +Datum +iprange_cast_from_text(PG_FUNCTION_ARGS) +{ + text *txt = PG_GETARG_TEXT_PP(0); + int tlen = VARSIZE_ANY_EXHDR(txt); + char buf[IP6R_STRING_MAX]; + + if (tlen < sizeof(buf)) + { + memcpy(buf, VARDATA_ANY(txt), tlen); + buf[tlen] = 0; + + PG_RETURN_DATUM(DirectFunctionCall1(iprange_in, CStringGetDatum(buf))); + } + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid IPR value in text"))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(iprange_cast_from_cidr); +Datum +iprange_cast_from_cidr(PG_FUNCTION_ARGS) +{ + inet *inetptr = PG_GETARG_INET_P(0); + inet_struct *in = INET_STRUCT_DATA(inetptr); + unsigned char *p = in->ipaddr; + IPR ipr; + + if (in->bits <= ipr_af_maxbits(in->family)) + { + switch (in->family) + { + case PGSQL_AF_INET: + { + IP4 ip = (p[0] << 24)|(p[1] << 16)|(p[2] << 8)|p[3]; + if (ip4r_from_cidr(ip, in->bits, &ipr.ip4r)) + PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET,&ipr)); + } + break; + + case PGSQL_AF_INET6: + { + IP6 ip; + ip.bits[0] = (((uint64)p[0] << 56) + | ((uint64)p[1] << 48) + | ((uint64)p[2] << 40) + | ((uint64)p[3] << 32) + | ((uint64)p[4] << 24) + | ((uint64)p[5] << 16) + | ((uint64)p[6] << 8) + | p[7]); + ip.bits[1] = (((uint64)p[8] << 56) + | ((uint64)p[9] << 48) + | ((uint64)p[10] << 40) + | ((uint64)p[11] << 32) + | ((uint64)p[12] << 24) + | ((uint64)p[13] << 16) + | ((uint64)p[14] << 8) + | p[15]); + if (ip6r_from_cidr(&ip, in->bits, &ipr.ip6r)) + PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET6,&ipr)); + } + break; + } + } + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid CIDR value for conversion to IPR"))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(iprange_cast_to_cidr); +Datum +iprange_cast_to_cidr(PG_FUNCTION_ARGS) +{ + IPR_P iprp = PG_GETARG_IPR_P(0); + IPR ipr; + int af = ipr_unpack(iprp, &ipr); + inet *res; + inet_struct *in; + unsigned bits; + + switch (af) + { + case 0: + PG_RETURN_NULL(); + + case PGSQL_AF_INET: + bits = masklen(ipr.ip4r.lower, ipr.ip4r.upper); + if (bits > ipr_af_maxbits(PGSQL_AF_INET)) + PG_RETURN_NULL(); + + res = palloc0(VARHDRSZ + sizeof(inet_struct)); + SET_VARSIZE(res, VARHDRSZ + offsetof(inet_struct, ipaddr) + 4); + + in = ((inet_struct *)VARDATA(res)); + in->bits = bits; + in->family = PGSQL_AF_INET; + { + unsigned char *p = in->ipaddr; + IP4 ip = ipr.ip4r.lower; + p[0] = (ip >> 24); + p[1] = (ip >> 16); + p[2] = (ip >> 8); + p[3] = (ip ); + } + + PG_RETURN_INET_P(res); + + case PGSQL_AF_INET6: + bits = masklen6(&ipr.ip6r.lower, &ipr.ip6r.upper); + if (bits > ipr_af_maxbits(PGSQL_AF_INET6)) + PG_RETURN_NULL(); + + res = palloc0(VARHDRSZ + sizeof(inet_struct)); + SET_VARSIZE(res, VARHDRSZ + offsetof(inet_struct, ipaddr) + 16); + + in = ((inet_struct *)VARDATA(res)); + in->bits = bits; + in->family = PGSQL_AF_INET6; + { + unsigned char *p = in->ipaddr; + uint64 b = ipr.ip6r.lower.bits[0]; + p[0] = (b >> 56); + p[1] = (b >> 48); + p[2] = (b >> 40); + p[3] = (b >> 32); + p[4] = (b >> 24); + p[5] = (b >> 16); + p[6] = (b >> 8); + p[7] = (b); + b = ipr.ip6r.lower.bits[1]; + p[8] = (b >> 56); + p[9] = (b >> 48); + p[10] = (b >> 40); + p[11] = (b >> 32); + p[12] = (b >> 24); + p[13] = (b >> 16); + p[14] = (b >> 8); + p[15] = (b); + } + + PG_RETURN_INET_P(res); + + default: + iprange_internal_error(); + } +} + +PG_FUNCTION_INFO_V1(iprange_cast_from_ip4); +Datum +iprange_cast_from_ip4(PG_FUNCTION_ARGS) +{ + IP4 ip = PG_GETARG_IP4(0); + IPR res; + + if (ip4r_from_inet(ip, 32, &res.ip4r)) + PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET, &res)); + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid IP4 value for conversion to IPR (shouldn't be possible)"))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(iprange_cast_from_ip6); +Datum +iprange_cast_from_ip6(PG_FUNCTION_ARGS) +{ + IP6 *ip = PG_GETARG_IP6_P(0); + IPR res; + + if (ip6r_from_inet(ip, 128, &res.ip6r)) + PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET6, &res)); + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid IP6 value for conversion to IPR (shouldn't be possible)"))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(iprange_cast_from_ipaddr); +Datum +iprange_cast_from_ipaddr(PG_FUNCTION_ARGS) +{ + IP_P ipp = PG_GETARG_IP_P(0); + IP ip; + IPR res; + int af = ip_unpack(ipp, &ip); + + switch (af) + { + case PGSQL_AF_INET: + if (ip4r_from_inet(ip.ip4, 32, &res.ip4r)) + PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET, &res)); + break; + + case PGSQL_AF_INET6: + if (ip6r_from_inet(&ip.ip6, 128, &res.ip6r)) + PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET6, &res)); + break; + } + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid IP6 value for conversion to IPR (shouldn't be possible)"))); + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(iprange_cast_from_ip4r); +Datum +iprange_cast_from_ip4r(PG_FUNCTION_ARGS) +{ + IP4R *ipr = PG_GETARG_IP4R_P(0); + IPR res; + + res.ip4r = *ipr; + PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET, &res)); +} + +PG_FUNCTION_INFO_V1(iprange_cast_from_ip6r); +Datum +iprange_cast_from_ip6r(PG_FUNCTION_ARGS) +{ + IP6R *ipr = PG_GETARG_IP6R_P(0); + IPR res; + + res.ip6r = *ipr; + PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET6, &res)); +} + +PG_FUNCTION_INFO_V1(iprange_cast_to_ip4r); +Datum +iprange_cast_to_ip4r(PG_FUNCTION_ARGS) +{ + IPR_P iprp = PG_GETARG_IPR_P(0); + IPR ipr; + int af = ipr_unpack(iprp,&ipr); + IP4R *res; + + if (af != PGSQL_AF_INET) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid IPR value for conversion to IP4R"))); + + res = palloc(sizeof(IP4R)); + *res = ipr.ip4r; + + PG_RETURN_IP4R_P(res); +} + +PG_FUNCTION_INFO_V1(iprange_cast_to_ip6r); +Datum +iprange_cast_to_ip6r(PG_FUNCTION_ARGS) +{ + IPR_P iprp = PG_GETARG_IPR_P(0); + IPR ipr; + int af = ipr_unpack(iprp,&ipr); + IP6R *res; + + if (af != PGSQL_AF_INET6) + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid IPR value for conversion to IP6R"))); + + res = palloc(sizeof(IP6R)); + *res = ipr.ip6r; + + PG_RETURN_IP6R_P(res); +} + +PG_FUNCTION_INFO_V1(iprange_cast_to_bit); +Datum +iprange_cast_to_bit(PG_FUNCTION_ARGS) +{ + IPR_P iprp = PG_GETARG_IPR_P(0); + IPR ipr; + int af = ipr_unpack(iprp, &ipr); + unsigned bits; + VarBit *res; + int len; + unsigned char buf[16]; + + switch (af) + { + case 0: + PG_RETURN_NULL(); + + case PGSQL_AF_INET: + bits = masklen(ipr.ip4r.lower, ipr.ip4r.upper); + if (bits > ipr_af_maxbits(PGSQL_AF_INET)) + PG_RETURN_NULL(); + + { + IP4 ip = ipr.ip4r.lower; + buf[0] = (ip >> 24); + buf[1] = (ip >> 16); + buf[2] = (ip >> 8); + buf[3] = (ip ); + } + break; + + case PGSQL_AF_INET6: + bits = masklen6(&ipr.ip6r.lower, &ipr.ip6r.upper); + if (bits > ipr_af_maxbits(PGSQL_AF_INET6)) + PG_RETURN_NULL(); + + ip6_serialize(&ipr.ip6r.lower, buf); + break; + + default: + iprange_internal_error(); + } + + len = VARBITTOTALLEN(bits); + res = palloc0(len); + SET_VARSIZE(res, len); + VARBITLEN(res) = bits; + + memcpy(VARBITS(res), buf, VARBITBYTES(res)); + PG_RETURN_VARBIT_P(res); +} + + +static +Datum +iprange_from_ipaddrs_internal(int af, IP4 a4, IP4 b4, IP6 *a6, IP6 *b6) +{ + IPR res; + + switch (af) + { + case PGSQL_AF_INET: + if (ip4_lessthan(a4,b4)) + res.ip4r.lower = a4, res.ip4r.upper = b4; + else + res.ip4r.lower = b4, res.ip4r.upper = a4; + PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET,&res)); + + case PGSQL_AF_INET6: + if (ip6_lessthan(a6,b6)) + res.ip6r.lower = *a6, res.ip6r.upper = *b6; + else + res.ip6r.lower = *b6, res.ip6r.upper = *a6; + PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET6,&res)); + + default: + iprange_internal_error(); + } +} + +PG_FUNCTION_INFO_V1(iprange_from_ip4s); +Datum +iprange_from_ip4s(PG_FUNCTION_ARGS) +{ + IP4 a = PG_GETARG_IP4(0); + IP4 b = PG_GETARG_IP4(1); + + PG_RETURN_DATUM(iprange_from_ipaddrs_internal(PGSQL_AF_INET, a, b, NULL, NULL)); +} + +PG_FUNCTION_INFO_V1(iprange_from_ip6s); +Datum +iprange_from_ip6s(PG_FUNCTION_ARGS) +{ + IP6 *a = PG_GETARG_IP6_P(0); + IP6 *b = PG_GETARG_IP6_P(1); + + PG_RETURN_DATUM(iprange_from_ipaddrs_internal(PGSQL_AF_INET6, 0, 0, a, b)); +} + +PG_FUNCTION_INFO_V1(iprange_from_ipaddrs); +Datum +iprange_from_ipaddrs(PG_FUNCTION_ARGS) +{ + IP_P ap = PG_GETARG_IP_P(0); + IP_P bp = PG_GETARG_IP_P(1); + IP a,b; + int af_a = ip_unpack(ap,&a); + int af_b = ip_unpack(bp,&b); + + if (af_a != af_b) + iprange_af_mismatch(); + + PG_RETURN_DATUM(iprange_from_ipaddrs_internal(af_a, a.ip4, b.ip4, &a.ip6, &b.ip6)); +} + + +static Datum +iprange_net_prefix_internal(int af, IP4 ip4, IP6 *ip6, int pfxlen) +{ + IPR res; + + if (pfxlen < 0 || pfxlen > ipr_af_maxbits(af)) + { + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("prefix length out of range"))); + } + + switch (af) + { + case PGSQL_AF_INET: + ip4r_from_inet(ip4, (unsigned)pfxlen, &res.ip4r); + break; + case PGSQL_AF_INET6: + ip6r_from_inet(ip6, (unsigned)pfxlen, &res.ip6r); + break; + default: + iprange_internal_error(); + } + + PG_RETURN_IPR_P(ipr_pack(af,&res)); +} + +PG_FUNCTION_INFO_V1(iprange_net_prefix_ip4); +Datum +iprange_net_prefix_ip4(PG_FUNCTION_ARGS) +{ + IP4 ip = PG_GETARG_IP4(0); + int pfxlen = PG_GETARG_INT32(1); + + PG_RETURN_DATUM(iprange_net_prefix_internal(PGSQL_AF_INET, ip, NULL, pfxlen)); +} + +PG_FUNCTION_INFO_V1(iprange_net_prefix_ip6); +Datum +iprange_net_prefix_ip6(PG_FUNCTION_ARGS) +{ + IP6 *ip = PG_GETARG_IP6_P(0); + int pfxlen = PG_GETARG_INT32(1); + + PG_RETURN_DATUM(iprange_net_prefix_internal(PGSQL_AF_INET6, 0, ip, pfxlen)); +} + +PG_FUNCTION_INFO_V1(iprange_net_prefix); +Datum +iprange_net_prefix(PG_FUNCTION_ARGS) +{ + IP_P ipp = PG_GETARG_IP_P(0); + IP ip; + int pfxlen = PG_GETARG_INT32(1); + int af = ip_unpack(ipp,&ip); + + PG_RETURN_DATUM(iprange_net_prefix_internal(af, ip.ip4, &ip.ip6, pfxlen)); +} + +static Datum +iprange_net_mask_internal(int af, IP4 ip4, IP6 *ip6, IP4 mask4, IP6 *mask6) +{ + IPR res; + + switch (af) + { + case PGSQL_AF_INET: + if (!ip4_valid_netmask(mask4)) + break; + + res.ip4r.lower = ip4 & mask4; + res.ip4r.upper = ip4 | ~mask4; + + PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET,&res)); + + case PGSQL_AF_INET6: + if (!ip6_valid_netmask(mask6->bits[0], mask6->bits[1])) + break; + + res.ip6r.lower.bits[0] = ip6->bits[0] & mask6->bits[0]; + res.ip6r.lower.bits[1] = ip6->bits[1] & mask6->bits[1]; + res.ip6r.upper.bits[0] = ip6->bits[0] | ~(mask6->bits[0]); + res.ip6r.upper.bits[1] = ip6->bits[1] | ~(mask6->bits[1]); + + PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET6,&res)); + } + + ereport(ERROR, + (errcode(ERRCODE_INVALID_PARAMETER_VALUE), + errmsg("invalid netmask"))); + PG_RETURN_VOID(); +} + +PG_FUNCTION_INFO_V1(iprange_net_mask_ip4); +Datum +iprange_net_mask_ip4(PG_FUNCTION_ARGS) +{ + IP4 ip = PG_GETARG_IP4(0); + IP4 mask = PG_GETARG_IP4(1); + + PG_RETURN_DATUM(iprange_net_mask_internal(PGSQL_AF_INET, ip, NULL, mask, NULL)); +} + +PG_FUNCTION_INFO_V1(iprange_net_mask_ip6); +Datum +iprange_net_mask_ip6(PG_FUNCTION_ARGS) +{ + IP6 *ip = PG_GETARG_IP6_P(0); + IP6 *mask = PG_GETARG_IP6_P(1); + + PG_RETURN_DATUM(iprange_net_mask_internal(PGSQL_AF_INET6, 0, ip, 0, mask)); +} + +PG_FUNCTION_INFO_V1(iprange_net_mask); +Datum +iprange_net_mask(PG_FUNCTION_ARGS) +{ + IP_P ipp = PG_GETARG_IP_P(0); + IP_P maskp = PG_GETARG_IP_P(1); + IP ip XINIT(IP_INITIALIZER); + IP mask XINIT(IP_INITIALIZER); + int af1 = ip_unpack(ipp,&ip); + int af2 = ip_unpack(maskp,&mask); + + if (af1 != af2) + iprange_af_mismatch(); + + PG_RETURN_DATUM(iprange_net_mask_internal(af1, ip.ip4, &ip.ip6, mask.ip4, &mask.ip6)); +} + +PG_FUNCTION_INFO_V1(iprange_lower); +Datum +iprange_lower(PG_FUNCTION_ARGS) +{ + IPR_P iprp = PG_GETARG_IPR_P(0); + IPR ipr; + IP ip; + int af = ipr_unpack(iprp,&ipr); + + switch (af) + { + case 0: + ip.ip4 = 0; + PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET,&ip)); + + case PGSQL_AF_INET: + ip.ip4 = ipr.ip4r.lower; + PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET,&ip)); + + case PGSQL_AF_INET6: + ip.ip6 = ipr.ip6r.lower; + PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET6,&ip)); + + default: + iprange_internal_error(); + } +} + +PG_FUNCTION_INFO_V1(iprange_upper); +Datum +iprange_upper(PG_FUNCTION_ARGS) +{ + IPR_P iprp = PG_GETARG_IPR_P(0); + IPR ipr; + IP ip; + int af = ipr_unpack(iprp,&ipr); + + switch (af) + { + case 0: + ip.ip6.bits[0] = ip.ip6.bits[1] = ~(uint64)0; + PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET6,&ip)); + + case PGSQL_AF_INET: + ip.ip4 = ipr.ip4r.upper; + PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET,&ip)); + + case PGSQL_AF_INET6: + ip.ip6 = ipr.ip6r.upper; + PG_RETURN_IP_P(ip_pack(PGSQL_AF_INET6,&ip)); + + default: + iprange_internal_error(); + } +} + +PG_FUNCTION_INFO_V1(iprange_is_cidr); +Datum +iprange_is_cidr(PG_FUNCTION_ARGS) +{ + IPR_P iprp = PG_GETARG_IPR_P(0); + IPR ipr; + int af = ipr_unpack(iprp,&ipr); + + switch (af) + { + case 0: + PG_RETURN_BOOL(false); + + case PGSQL_AF_INET: + PG_RETURN_BOOL( (masklen(ipr.ip4r.lower,ipr.ip4r.upper) <= 32U) ); + + case PGSQL_AF_INET6: + PG_RETURN_BOOL( (masklen6(&ipr.ip6r.lower,&ipr.ip6r.upper) <= 128U) ); + + default: + iprange_internal_error(); + } +} + +PG_FUNCTION_INFO_V1(iprange_family); +Datum +iprange_family(PG_FUNCTION_ARGS) +{ + IPR_P iprp = PG_GETARG_IPR_P(0); + IPR ipr; + int af = ipr_unpack(iprp,&ipr); + + switch (af) + { + case 0: + PG_RETURN_NULL(); + + case PGSQL_AF_INET: + PG_RETURN_INT32(4); + + case PGSQL_AF_INET6: + PG_RETURN_INT32(6); + + default: + iprange_internal_error(); + } +} + +/* + * Decompose an arbitrary range into CIDRs + */ +PG_FUNCTION_INFO_V1(iprange_cidr_split); +Datum +iprange_cidr_split(PG_FUNCTION_ARGS) +{ + FuncCallContext *funcctx; + IPR *val; + IPR res; + int af; + + if (SRF_IS_FIRSTCALL()) + { + IPR_P *in = PG_GETARG_IPR_P(0); + + funcctx = SRF_FIRSTCALL_INIT(); + val = MemoryContextAlloc(funcctx->multi_call_memory_ctx, + sizeof(IPR)); + af = ipr_unpack(in, val); + funcctx->user_fctx = val; + /* + * We abuse max_calls, which is ignored by the api and only exists as + * a convenience variable, to store the current address family. But + * out of sheer aesthetics (and for debugging purposes) we store a + * value that does actually represent a (loose) upper bound on the row + * count. + */ + funcctx->max_calls = af ? 2*ipr_af_maxbits(af) : 2; + } + + funcctx = SRF_PERCALL_SETUP(); + + val = funcctx->user_fctx; + if (!val) + SRF_RETURN_DONE(funcctx); + Assert(funcctx->call_cntr < funcctx->max_calls); + + switch (funcctx->max_calls) + { + case 2: + /* + * We're splitting '-' into '0.0.0.0/0' and '::/0'. + */ + if (funcctx->call_cntr == 0) + { + res.ip4r.lower = netmask(0); + res.ip4r.upper = hostmask(0); + af = PGSQL_AF_INET; + } + else + { + funcctx->user_fctx = NULL; /* this is the last row */ + res.ip6r.lower.bits[0] = netmask6_hi(0); + res.ip6r.lower.bits[1] = netmask6_lo(0); + res.ip6r.upper.bits[0] = hostmask6_hi(0); + res.ip6r.upper.bits[1] = hostmask6_lo(0); + af = PGSQL_AF_INET6; + } + break; + + case 2*ipr_af_maxbits(PGSQL_AF_INET): + if (ip4r_split_cidr(&val->ip4r, &res.ip4r)) + funcctx->user_fctx = NULL; + af = PGSQL_AF_INET; + break; + + case 2*ipr_af_maxbits(PGSQL_AF_INET6): + if (ip6r_split_cidr(&val->ip6r, &res.ip6r)) + funcctx->user_fctx = NULL; + af = PGSQL_AF_INET6; + break; + + default: + iprange_internal_error(); + } + + SRF_RETURN_NEXT(funcctx, IPR_PGetDatum(ipr_pack(af, &res))); +} + +/* + * comparisons and indexing + */ + +static int +iprange_cmp_internal(Datum d1, Datum d2) +{ + IPR_P ipp1 = DatumGetIPR_P(d1); + IPR_P ipp2 = DatumGetIPR_P(d2); + IPR ipr1 XINIT(IPR_INITIALIZER); + IPR ipr2 XINIT(IPR_INITIALIZER); + int af1 = ipr_unpack(ipp1, &ipr1); + int af2 = ipr_unpack(ipp2, &ipr2); + int retval = 0; + + if (af1 == af2) + { + switch (af1) + { + case 0: + break; + + case PGSQL_AF_INET: + if (ip4r_lessthan(&ipr1.ip4r,&ipr2.ip4r)) + retval = -1; + else if (ip4r_lessthan(&ipr2.ip4r,&ipr1.ip4r)) + retval = 1; + break; + + case PGSQL_AF_INET6: + if (ip6r_lessthan(&ipr1.ip6r,&ipr2.ip6r)) + retval = -1; + else if (ip6r_lessthan(&ipr2.ip6r,&ipr1.ip6r)) + retval = 1; + break; + + default: + iprange_internal_error(); + } + } + else if (af1 < af2) + retval = -1; + else + retval = 1; + + if ((Pointer)ipp1 != DatumGetPointer(d1)) + pfree(ipp1); + if ((Pointer)ipp2 != DatumGetPointer(d2)) + pfree(ipp2); + + return retval; +} + +PG_FUNCTION_INFO_V1(iprange_lt); +Datum +iprange_lt(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( iprange_cmp_internal(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1)) < 0 ); +} + +PG_FUNCTION_INFO_V1(iprange_le); +Datum +iprange_le(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( iprange_cmp_internal(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1)) <= 0 ); +} + +PG_FUNCTION_INFO_V1(iprange_gt); +Datum +iprange_gt(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( iprange_cmp_internal(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1)) > 0 ); +} + +PG_FUNCTION_INFO_V1(iprange_ge); +Datum +iprange_ge(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( iprange_cmp_internal(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1)) >= 0 ); +} + +PG_FUNCTION_INFO_V1(iprange_eq); +Datum +iprange_eq(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( iprange_cmp_internal(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1)) == 0 ); +} + +PG_FUNCTION_INFO_V1(iprange_neq); +Datum +iprange_neq(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( iprange_cmp_internal(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1)) != 0 ); +} + +static bool +iprange_overlaps_internal(Datum d1, Datum d2) +{ + IPR_P ipp1 = DatumGetIPR_P(d1); + IPR_P ipp2 = DatumGetIPR_P(d2); + IPR ipr1 XINIT(IPR_INITIALIZER); + IPR ipr2 XINIT(IPR_INITIALIZER); + int af1 = ipr_unpack(ipp1, &ipr1); + int af2 = ipr_unpack(ipp2, &ipr2); + bool retval; + + if (af1 == af2) + { + switch (af1) + { + case 0: + retval = true; + break; + + case PGSQL_AF_INET: + retval = ip4r_overlaps_internal(&ipr1.ip4r,&ipr2.ip4r); + break; + + case PGSQL_AF_INET6: + retval = ip6r_overlaps_internal(&ipr1.ip6r,&ipr2.ip6r); + break; + + default: + iprange_internal_error(); + } + } + else + retval = (af1 == 0) || (af2 == 0); + + if ((Pointer)ipp1 != DatumGetPointer(d1)) + pfree(ipp1); + if ((Pointer)ipp2 != DatumGetPointer(d2)) + pfree(ipp2); + + return retval; +} + +static int +iprange_contains_internal(Datum d1, Datum d2, bool eqval) +{ + IPR_P ipp1 = DatumGetIPR_P(d1); + IPR_P ipp2 = DatumGetIPR_P(d2); + IPR ipr1 XINIT(IPR_INITIALIZER); + IPR ipr2 XINIT(IPR_INITIALIZER); + int af1 = ipr_unpack(ipp1, &ipr1); + int af2 = ipr_unpack(ipp2, &ipr2); + bool retval; + + if (af1 == af2) + { + switch (af1) + { + case 0: + retval = eqval; + break; + + case PGSQL_AF_INET: + retval = ip4r_contains_internal(&ipr1.ip4r,&ipr2.ip4r,eqval); + break; + + case PGSQL_AF_INET6: + retval = ip6r_contains_internal(&ipr1.ip6r,&ipr2.ip6r,eqval); + break; + + default: + iprange_internal_error(); + } + } + else + retval = (af1 == 0); + + if ((Pointer)ipp1 != DatumGetPointer(d1)) + pfree(ipp1); + if ((Pointer)ipp2 != DatumGetPointer(d2)) + pfree(ipp2); + + return retval; +} + +static int +iprange_contains_ip_internal(Datum d1, int af2, IP4 ip4, IP6 *ip6) +{ + IPR_P ipp1 = DatumGetIPR_P(d1); + IPR ipr1 XINIT(IPR_INITIALIZER); + int af1 = ipr_unpack(ipp1, &ipr1); + bool retval; + + if (af1 == af2) + { + switch (af1) + { + case 0: + retval = true; + break; + + case PGSQL_AF_INET: + retval = ip4_contains_internal(&ipr1.ip4r,ip4); + break; + + case PGSQL_AF_INET6: + retval = ip6_contains_internal(&ipr1.ip6r,ip6); + break; + + default: + iprange_internal_error(); + } + } + else + retval = (af1 == 0); + + if ((Pointer)ipp1 != DatumGetPointer(d1)) + pfree(ipp1); + + return retval; +} + +PG_FUNCTION_INFO_V1(iprange_overlaps); +Datum +iprange_overlaps(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( iprange_overlaps_internal(PG_GETARG_DATUM(0), + PG_GETARG_DATUM(1)) ); +} + +PG_FUNCTION_INFO_V1(iprange_contains); +Datum +iprange_contains(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( iprange_contains_internal(PG_GETARG_DATUM(0), + PG_GETARG_DATUM(1), + true) ); +} + +PG_FUNCTION_INFO_V1(iprange_contains_strict); +Datum +iprange_contains_strict(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( iprange_contains_internal(PG_GETARG_DATUM(0), + PG_GETARG_DATUM(1), + false) ); +} + +PG_FUNCTION_INFO_V1(iprange_contained_by); +Datum +iprange_contained_by(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( iprange_contains_internal(PG_GETARG_DATUM(1), + PG_GETARG_DATUM(0), + true) ); +} + +PG_FUNCTION_INFO_V1(iprange_contained_by_strict); +Datum +iprange_contained_by_strict(PG_FUNCTION_ARGS) +{ + PG_RETURN_BOOL( iprange_contains_internal(PG_GETARG_DATUM(1), + PG_GETARG_DATUM(0), + false) ); +} + +PG_FUNCTION_INFO_V1(iprange_contains_ip); +Datum +iprange_contains_ip(PG_FUNCTION_ARGS) +{ + IP_P ipp = PG_GETARG_IP_P(1); + IP ip XINIT(IP_INITIALIZER); + int af = ip_unpack(ipp,&ip); + bool retval = iprange_contains_ip_internal(PG_GETARG_DATUM(0), af, ip.ip4, &ip.ip6); + + PG_FREE_IF_COPY(ipp,1); + PG_RETURN_BOOL(retval); +} + +PG_FUNCTION_INFO_V1(iprange_contains_ip4); +Datum +iprange_contains_ip4(PG_FUNCTION_ARGS) +{ + IP4 ip = PG_GETARG_IP4(1); + PG_RETURN_BOOL(iprange_contains_ip_internal(PG_GETARG_DATUM(0), PGSQL_AF_INET, ip, NULL)); +} + +PG_FUNCTION_INFO_V1(iprange_contains_ip6); +Datum +iprange_contains_ip6(PG_FUNCTION_ARGS) +{ + IP6 *ip = PG_GETARG_IP6_P(1); + PG_RETURN_BOOL(iprange_contains_ip_internal(PG_GETARG_DATUM(0), PGSQL_AF_INET6, 0, ip)); +} + +PG_FUNCTION_INFO_V1(iprange_ip6_contained_by); +Datum +iprange_ip6_contained_by(PG_FUNCTION_ARGS) +{ + IP6 *ip = PG_GETARG_IP6_P(0); + PG_RETURN_BOOL( iprange_contains_ip_internal(PG_GETARG_DATUM(1), PGSQL_AF_INET6, 0, ip) ); +} + +PG_FUNCTION_INFO_V1(iprange_ip4_contained_by); +Datum +iprange_ip4_contained_by(PG_FUNCTION_ARGS) +{ + IP4 ip = PG_GETARG_IP4(0); + PG_RETURN_BOOL( iprange_contains_ip_internal(PG_GETARG_DATUM(1), PGSQL_AF_INET, ip, NULL) ); +} + +PG_FUNCTION_INFO_V1(iprange_ip_contained_by); +Datum +iprange_ip_contained_by(PG_FUNCTION_ARGS) +{ + IP_P ipp = PG_GETARG_IP_P(0); + IP ip XINIT(IP_INITIALIZER); + int af = ip_unpack(ipp,&ip); + bool retval = iprange_contains_ip_internal(PG_GETARG_DATUM(1), af, ip.ip4, &ip.ip6); + + PG_FREE_IF_COPY(ipp,0); + PG_RETURN_BOOL(retval); +} + +PG_FUNCTION_INFO_V1(iprange_union); +Datum +iprange_union(PG_FUNCTION_ARGS) +{ + IPR_P ipp1 = PG_GETARG_IPR_P(0); + IPR_P ipp2 = PG_GETARG_IPR_P(1); + IPR ipr1; + IPR ipr2; + int af1 = ipr_unpack(ipp1, &ipr1); + int af2 = ipr_unpack(ipp2, &ipr2); + IPR res; + + if (af1 == af2) + { + switch (af1) + { + case 0: + PG_RETURN_IPR_P(ipr_pack(0,NULL)); + + case PGSQL_AF_INET: + ip4r_union_internal(&ipr1.ip4r,&ipr2.ip4r,&res.ip4r); + PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET,&res)); + + case PGSQL_AF_INET6: + ip6r_union_internal(&ipr1.ip6r,&ipr2.ip6r,&res.ip6r); + PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET6,&res)); + + default: + iprange_internal_error(); + } + } + else + PG_RETURN_IPR_P(ipr_pack(0,NULL)); +} + +PG_FUNCTION_INFO_V1(iprange_inter); +Datum +iprange_inter(PG_FUNCTION_ARGS) +{ + IPR_P ipp1 = PG_GETARG_IPR_P(0); + IPR_P ipp2 = PG_GETARG_IPR_P(1); + IPR ipr1; + IPR ipr2; + int af1 = ipr_unpack(ipp1, &ipr1); + int af2 = ipr_unpack(ipp2, &ipr2); + IPR res; + + if (af1 == af2) + { + switch (af1) + { + case 0: + PG_RETURN_IPR_P(ipr_pack(0,NULL)); + + case PGSQL_AF_INET: + if (ip4r_inter_internal(&ipr1.ip4r,&ipr2.ip4r,&res.ip4r)) + PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET,&res)); + break; + + case PGSQL_AF_INET6: + if (ip6r_inter_internal(&ipr1.ip6r,&ipr2.ip6r,&res.ip6r)) + PG_RETURN_IPR_P(ipr_pack(PGSQL_AF_INET6,&res)); + break; + + default: + iprange_internal_error(); + } + } + else if (af1 == 0) + PG_RETURN_IPR_P(ipr_pack(af2,&ipr2)); + else if (af2 == 0) + PG_RETURN_IPR_P(ipr_pack(af1,&ipr1)); + + PG_RETURN_NULL(); +} + +PG_FUNCTION_INFO_V1(iprange_size); +Datum +iprange_size(PG_FUNCTION_ARGS) +{ + IPR_P ipp = PG_GETARG_IPR_P(0); + IPR ipr; + int af = ipr_unpack(ipp, &ipr); + + switch (af) + { + case 0: + PG_RETURN_FLOAT8(ldexp(1.0, 129)); + + case PGSQL_AF_INET: + PG_RETURN_FLOAT8(ip4r_metric(&ipr.ip4r)); + + case PGSQL_AF_INET6: + PG_RETURN_FLOAT8(ip6r_metric(&ipr.ip6r)); + + default: + iprange_internal_error(); + } +} + +PG_FUNCTION_INFO_V1(iprange_size_exact); +Datum +iprange_size_exact(PG_FUNCTION_ARGS) +{ + IPR_P ipp = PG_GETARG_IPR_P(0); + IPR ipr; + int af = ipr_unpack(ipp, &ipr); + Datum u,l,d,s; + + switch (af) + { + case 0: + s = DirectFunctionCall3(numeric_in, CStringGetDatum("680564733841876926926749214863536422912"), 0, Int32GetDatum(-1)); + PG_RETURN_DATUM(s); + + case PGSQL_AF_INET: + l = DirectFunctionCall1(ip4_cast_to_numeric, IP4GetDatum(ipr.ip4r.lower)); + u = DirectFunctionCall1(ip4_cast_to_numeric, IP4GetDatum(ipr.ip4r.upper)); + break; + + case PGSQL_AF_INET6: + l = DirectFunctionCall1(ip6_cast_to_numeric, IP6PGetDatum(&ipr.ip6r.lower)); + u = DirectFunctionCall1(ip6_cast_to_numeric, IP6PGetDatum(&ipr.ip6r.upper)); + break; + + default: + iprange_internal_error(); + } + + d = DirectFunctionCall2(numeric_sub, u, l); + s = DirectFunctionCall1(numeric_inc, d); + PG_RETURN_DATUM(s); +} + +PG_FUNCTION_INFO_V1(iprange_prefixlen); +Datum +iprange_prefixlen(PG_FUNCTION_ARGS) +{ + IPR_P iprp = PG_GETARG_IPR_P(0); + IPR ipr; + int af = ipr_unpack(iprp,&ipr); + unsigned len = ~0; + unsigned maxbits = 0; + + if (af == PGSQL_AF_INET) + maxbits = 32, len = masklen(ipr.ip4r.lower, ipr.ip4r.upper); + else if (af == PGSQL_AF_INET6) + maxbits = 128, len = masklen6(&ipr.ip6r.lower, &ipr.ip6r.upper); + + if (len <= maxbits) + PG_RETURN_INT32((int32) len); + + PG_RETURN_NULL(); +} + + +/***************************************************************************** + * Btree functions + *****************************************************************************/ + +PG_FUNCTION_INFO_V1(iprange_cmp); +Datum +iprange_cmp(PG_FUNCTION_ARGS) +{ + PG_RETURN_INT32( iprange_cmp_internal(PG_GETARG_DATUM(0), PG_GETARG_DATUM(1)) ); +} + + +/***************************************************************************** + * GiST functions + *****************************************************************************/ + +/* +** GiST support methods +*/ + +Datum gipr_consistent(PG_FUNCTION_ARGS); +Datum gipr_compress(PG_FUNCTION_ARGS); +Datum gipr_decompress(PG_FUNCTION_ARGS); +Datum gipr_penalty(PG_FUNCTION_ARGS); +Datum gipr_picksplit(PG_FUNCTION_ARGS); +Datum gipr_union(PG_FUNCTION_ARGS); +Datum gipr_same(PG_FUNCTION_ARGS); +Datum gipr_fetch(PG_FUNCTION_ARGS); + +typedef struct { + int32 vl_len_; + int32 af; + IPR ipr; +} IPR_KEY; + +static bool gipr_leaf_consistent(IPR_KEY *key, IPR_P query, StrategyNumber strategy); +static bool gipr_internal_consistent(IPR_KEY *key, IPR_P query, StrategyNumber strategy); + + +/* + * compress is passed a GISTENTRY* containing a leaf or nonleaf key, and is + * expected to return either the same entry or a new one containing the data to + * be actually written to the index tuple. The key is a leaf key if and only if + * it came from outside GiST (via insert or bulkinsert). + */ + +PG_FUNCTION_INFO_V1(gipr_compress); +Datum +gipr_compress(PG_FUNCTION_ARGS) +{ + GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); + GISTENTRY *retval = entry; + + if (!entry->leafkey) + { + IPR_KEY *key = (IPR_KEY *) DatumGetPointer(entry->key); + + retval = palloc(sizeof(GISTENTRY)); + + Assert(!VARATT_IS_EXTENDED(key) && VARSIZE(key) == sizeof(IPR_KEY)); + Assert(key->af == 0 || key->af == PGSQL_AF_INET || key->af == PGSQL_AF_INET6); + + gistentryinit(*retval, PointerGetDatum(ipr_pack(key->af, &key->ipr)), + entry->rel, entry->page, + entry->offset, false); + } + + PG_RETURN_POINTER(retval); +} + +PG_FUNCTION_INFO_V1(gipr_decompress); +Datum +gipr_decompress(PG_FUNCTION_ARGS) +{ + GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); + GISTENTRY *retval = palloc(sizeof(GISTENTRY)); + IPR_KEY *key = palloc(sizeof(IPR_KEY)); + + SET_VARSIZE(key, sizeof(IPR_KEY)); + key->af = ipr_unpack((IPR_P) DatumGetPointer(entry->key), &key->ipr); + + gistentryinit(*retval, PointerGetDatum(key), + entry->rel, entry->page, + entry->offset, false); + + PG_RETURN_POINTER(retval); +} + +PG_FUNCTION_INFO_V1(gipr_fetch); +Datum +gipr_fetch(PG_FUNCTION_ARGS) +{ + PG_RETURN_POINTER(PG_GETARG_POINTER(0)); +} + + +/* +** The GiST Consistent method for IP ranges +** Should return false if for all data items x below entry, +** the predicate x op query == false, where op is the oper +** corresponding to strategy in the pg_amop table. +*/ + +PG_FUNCTION_INFO_V1(gipr_consistent); +Datum +gipr_consistent(PG_FUNCTION_ARGS) +{ + GISTENTRY *entry = (GISTENTRY *) PG_GETARG_POINTER(0); + IPR_P query = (IPR_P) PG_GETARG_POINTER(1); + StrategyNumber strategy = (StrategyNumber) PG_GETARG_UINT16(2); + bool *recheck = (bool *) PG_GETARG_POINTER(4); + IPR_KEY *key = (IPR_KEY *) DatumGetPointer(entry->key); + bool retval; + + /* recheck is never needed with this type */ + if (recheck) + *recheck = false; + + /* + * * if entry is not leaf, use gipr_internal_consistent, * else use + * gipr_leaf_consistent + */ + + if (GIST_LEAF(entry)) + retval = gipr_leaf_consistent(key, query, strategy); + else + retval = gipr_internal_consistent(key, query, strategy); + + PG_RETURN_BOOL(retval); +} + +/* +** The GiST Union method for IP ranges +** returns the minimal bounding IPR that encloses all the entries in entryvec +*/ + +static void +gipr_union_internal_1(IPR_KEY *out, IPR_KEY *tmp) +{ + if (out->af != tmp->af) + out->af = 0; + + switch (out->af) + { + case 0: + break; + + case PGSQL_AF_INET: + { + if (ip4_lessthan(tmp->ipr.ip4r.lower,out->ipr.ip4r.lower)) + out->ipr.ip4r.lower = tmp->ipr.ip4r.lower; + if (ip4_lessthan(out->ipr.ip4r.upper,tmp->ipr.ip4r.upper)) + out->ipr.ip4r.upper = tmp->ipr.ip4r.upper; + break; + } + + case PGSQL_AF_INET6: + { + if (ip6_lessthan(&tmp->ipr.ip6r.lower,&out->ipr.ip6r.lower)) + out->ipr.ip6r.lower = tmp->ipr.ip6r.lower; + if (ip6_lessthan(&out->ipr.ip6r.upper,&tmp->ipr.ip6r.upper)) + out->ipr.ip6r.upper = tmp->ipr.ip6r.upper; + break; + } + + default: + iprange_internal_error(); + } +} + +static void +gipr_union_internal(IPR_KEY *out, bool *allequalp, bool *afequalp, + GISTENTRY *ent, int numranges) +{ + int i; + bool allequal = true; + bool afequal = true; + IPR_KEY *tmp; + + tmp = (IPR_KEY *) DatumGetPointer(ent[0].key); + *out = *tmp; + + for (i = 1; out->af != 0 && i < numranges; ++i) + { + tmp = (IPR_KEY *) DatumGetPointer(ent[i].key); + if (tmp->af != out->af) + { + out->af = 0; + afequal = allequal = false; + } + } + + switch (out->af) + { + case 0: + break; + + case PGSQL_AF_INET: + { + tmp = (IPR_KEY *) DatumGetPointer(ent[0].key); + out->ipr.ip4r = tmp->ipr.ip4r; + + for (i = 1; i < numranges; i++) + { + tmp = (IPR_KEY *) DatumGetPointer(ent[i].key); + + if (allequal && !ip4r_equal(&tmp->ipr.ip4r, &out->ipr.ip4r)) + allequal = false; + + if (ip4_lessthan(tmp->ipr.ip4r.lower,out->ipr.ip4r.lower)) + out->ipr.ip4r.lower = tmp->ipr.ip4r.lower; + if (ip4_lessthan(out->ipr.ip4r.upper,tmp->ipr.ip4r.upper)) + out->ipr.ip4r.upper = tmp->ipr.ip4r.upper; + } + break; + } + + case PGSQL_AF_INET6: + { + tmp = (IPR_KEY *) DatumGetPointer(ent[0].key); + out->ipr.ip4r = tmp->ipr.ip4r; + + for (i = 1; i < numranges; i++) + { + tmp = (IPR_KEY *) DatumGetPointer(ent[i].key); + + if (allequal && !ip6r_equal(&tmp->ipr.ip6r, &out->ipr.ip6r)) + allequal = false; + + if (ip6_lessthan(&tmp->ipr.ip6r.lower,&out->ipr.ip6r.lower)) + out->ipr.ip6r.lower = tmp->ipr.ip6r.lower; + if (ip6_lessthan(&out->ipr.ip6r.upper,&tmp->ipr.ip6r.upper)) + out->ipr.ip6r.upper = tmp->ipr.ip6r.upper; + } + break; + } + + default: + iprange_internal_error(); + } + + if (afequalp) + *afequalp = afequal; + if (allequalp) + *allequalp = allequal; +} + + +PG_FUNCTION_INFO_V1(gipr_union); +Datum +gipr_union(PG_FUNCTION_ARGS) +{ + GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0); + int *sizep = (int *) PG_GETARG_POINTER(1); + GISTENTRY *ent = GISTENTRYVEC(entryvec); + int numranges; + IPR_KEY *out = palloc(sizeof(IPR_KEY)); + +#ifdef GIST_DEBUG + fprintf(stderr, "union\n"); +#endif + + numranges = GISTENTRYCOUNT(entryvec); + + gipr_union_internal(out, NULL, NULL, ent, numranges); + + *sizep = sizeof(IPR_KEY); + + PG_RETURN_POINTER(out); +} + + +/* +** The GiST Penalty method for IP ranges +** As in the R-tree paper, we use change in area as our penalty metric +*/ +PG_FUNCTION_INFO_V1(gipr_penalty); +Datum +gipr_penalty(PG_FUNCTION_ARGS) +{ + GISTENTRY *origentry = (GISTENTRY *) PG_GETARG_POINTER(0); + GISTENTRY *newentry = (GISTENTRY *) PG_GETARG_POINTER(1); + float *result = (float *) PG_GETARG_POINTER(2); + IPR_KEY *key = (IPR_KEY *) DatumGetPointer(origentry->key); + IPR_KEY *newkey = (IPR_KEY *) DatumGetPointer(newentry->key); + IP4R ud4; + IP6R ud6; + double tmp = 0.0; + + if (key->af != newkey->af) + { + if (key->af != 0 && newkey->af != 0) + tmp = 1e10; + } + else + { + switch (key->af) + { + case 0: + break; + + /* + * rather than subtract the sizes, which might lose + * due to rounding errors in v6, we calculate the + * actual number of addresses added to the range. + */ + + case PGSQL_AF_INET: + if (newkey->ipr.ip4r.lower < key->ipr.ip4r.lower) + { + ud4.lower = newkey->ipr.ip4r.lower; + ud4.upper = key->ipr.ip4r.lower - 1; + tmp = ip4r_metric(&ud4); + } + if (key->ipr.ip4r.upper < newkey->ipr.ip4r.upper) + { + ud4.lower = key->ipr.ip4r.upper; + ud4.upper = newkey->ipr.ip4r.upper - 1; + tmp += ip4r_metric(&ud4); + } + break; + + case PGSQL_AF_INET6: + if (ip6_lessthan(&newkey->ipr.ip6r.lower,&key->ipr.ip6r.lower)) + { + ud6.lower = newkey->ipr.ip6r.lower; + ud6.upper = key->ipr.ip6r.lower; + ip6_sub_int(&ud6.upper,1,&ud6.upper); + tmp = ip6r_metric(&ud6); + } + if (ip6_lessthan(&key->ipr.ip6r.upper,&newkey->ipr.ip6r.upper)) + { + ud6.lower = key->ipr.ip6r.upper; + ud6.upper = newkey->ipr.ip6r.upper; + ip6_sub_int(&ud6.upper,1,&ud6.upper); + tmp += ip6r_metric(&ud6); + } + + /* + * we want to scale the result a bit. For one thing, the gist code implicitly + * assigns a penalty of 1e10 for a union of null and non-null values, and we + * want to keep our values less than that. For another, the penalty is sometimes + * summed across columns of a multi-column index, and we don't want our huge + * metrics (>2^80) to completely swamp anything else. + * + * So, we scale as the fourth power of the log2 of the computed penalty, which + * gives us a range 0 - 268435456. + */ + + tmp = pow(log(tmp+1) / log(2), 4); + break; + + default: + iprange_internal_error(); + } + } + + *result = (float) tmp; + +#ifdef GIST_DEBUG + fprintf(stderr, "penalty\n"); + fprintf(stderr, "\t%g\n", *result); +#endif + + PG_RETURN_POINTER(result); +} + + +/* Helper functions for picksplit. We might need to sort a list of + * ranges by size; these are for that. We don't ever need to sort + * mixed address families though. + */ + +struct gipr_sort +{ + IPR_KEY *key; + OffsetNumber pos; +}; + +static int +gipr_sort_compare_v4(const void *av, const void *bv) +{ + IPR_KEY *a = ((struct gipr_sort *)av)->key; + IPR_KEY *b = ((struct gipr_sort *)bv)->key; + double sa = ip4r_metric(&a->ipr.ip4r); + double sb = ip4r_metric(&b->ipr.ip4r); + return (sa > sb) ? 1 : ((sa == sb) ? 0 : -1); +} + +static int +gipr_sort_compare_v6(const void *av, const void *bv) +{ + IPR_KEY *a = ((struct gipr_sort *)av)->key; + IPR_KEY *b = ((struct gipr_sort *)bv)->key; + double sa = ip6r_metric(&a->ipr.ip6r); + double sb = ip6r_metric(&b->ipr.ip6r); + return (sa > sb) ? 1 : ((sa == sb) ? 0 : -1); +} + +/* +** The GiST PickSplit method for IP ranges +** This is a linear-time algorithm based on a left/right split, +** based on the box functions in rtree_gist simplified to one +** dimension +*/ +PG_FUNCTION_INFO_V1(gipr_picksplit); +Datum +gipr_picksplit(PG_FUNCTION_ARGS) +{ + GistEntryVector *entryvec = (GistEntryVector *) PG_GETARG_POINTER(0); + GIST_SPLITVEC *v = (GIST_SPLITVEC *) PG_GETARG_POINTER(1); + GISTENTRY *ent = GISTENTRYVEC(entryvec); + OffsetNumber i; + int nbytes; + OffsetNumber maxoff; + OffsetNumber *listL; + OffsetNumber *listR; + bool allisequal = true; + bool allafequal = true; + IPR_KEY pageunion; + IPR_KEY *cur; + IPR_KEY *unionL; + IPR_KEY *unionR; + int posL = 0; + int posR = 0; + + posL = posR = 0; + maxoff = GISTENTRYCOUNT(entryvec) - 1; + + gipr_union_internal(&pageunion, &allisequal, &allafequal, + &ent[FirstOffsetNumber], maxoff); + + nbytes = (maxoff + 2) * sizeof(OffsetNumber); + listL = (OffsetNumber *) palloc(nbytes); + listR = (OffsetNumber *) palloc(nbytes); + unionL = palloc(sizeof(IPR_KEY)); + unionR = palloc(sizeof(IPR_KEY)); + v->spl_ldatum = PointerGetDatum(unionL); + v->spl_rdatum = PointerGetDatum(unionR); + v->spl_left = listL; + v->spl_right = listR; + + if (allisequal) + { + OffsetNumber split_at = FirstOffsetNumber + (maxoff - FirstOffsetNumber + 1)/2; + v->spl_nleft = v->spl_nright = 0; + *unionL = pageunion; + *unionR = pageunion; + + for (i = FirstOffsetNumber; i < split_at; i = OffsetNumberNext(i)) + v->spl_left[v->spl_nleft++] = i; + for (; i <= maxoff; i = OffsetNumberNext(i)) + v->spl_right[v->spl_nright++] = i; + + PG_RETURN_POINTER(v); + } + + /* + * if we have a mix of address families present, then we split by AF regardless + * of all other factors, since the penalty for mixing them is so high. If there's + * at least one universal range, we split those into the right page and leave + * everything else in the left page; otherwise, we split ivp6 into the right page. + * We accept a bad split ratio here in the interests of keeping AFs separate. + */ + +#define ADDLIST( list_, u_, pos_, num_ ) do { \ + if ( pos_ ) { \ + gipr_union_internal_1(u_, cur); \ + } else { \ + *(u_) = *(cur); \ + } \ + (list_)[(pos_)++] = (num_); \ +} while(0) + + if (!allafequal) + { + int right_af = PGSQL_AF_INET6; + + for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) + if ( ((IPR_KEY *)DatumGetPointer(ent[i].key))->af == 0) + break; + + if (i <= maxoff) + right_af = 0; + + for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) + { + cur = (IPR_KEY *)DatumGetPointer(ent[i].key); + if (cur->af != right_af) + ADDLIST(listL, unionL, posL, i); + else + ADDLIST(listR, unionR, posR, i); + } + } + else if (pageunion.af == PGSQL_AF_INET) + { + for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) + { + cur = (IPR_KEY *) DatumGetPointer(ent[i].key); + if ((cur->ipr.ip4r.upper - pageunion.ipr.ip4r.lower) + < (pageunion.ipr.ip4r.upper - cur->ipr.ip4r.lower)) + ADDLIST(listL, unionL, posL, i); + else + ADDLIST(listR, unionR, posR, i); + } + } + else + { + for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) + { + IP6 diff1; + IP6 diff2; + + cur = (IPR_KEY *) DatumGetPointer(ent[i].key); + ip6_sub(&cur->ipr.ip6r.upper, &pageunion.ipr.ip6r.lower, &diff1); + ip6_sub(&pageunion.ipr.ip6r.upper, &cur->ipr.ip6r.lower, &diff2); + if (ip6_lessthan(&diff1,&diff2)) + ADDLIST(listL, unionL, posL, i); + else + ADDLIST(listR, unionR, posR, i); + } + } + + /* bad disposition, sort by ascending size and resplit */ + if (posR == 0 || posL == 0) + { + struct gipr_sort *arr = (struct gipr_sort *) + palloc(sizeof(struct gipr_sort) * (maxoff + FirstOffsetNumber)); + + Assert(allafequal); + + for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) + { + arr[i].key = (IPR_KEY *) DatumGetPointer(ent[i].key); + arr[i].pos = i; + } + + qsort(arr + FirstOffsetNumber, + maxoff - FirstOffsetNumber + 1, + sizeof(struct gipr_sort), + (pageunion.af == PGSQL_AF_INET6) ? gipr_sort_compare_v6 : gipr_sort_compare_v4); + + posL = posR = 0; + + for (i = FirstOffsetNumber; i <= maxoff; i = OffsetNumberNext(i)) + { + IP6 diff1; + IP6 diff2; + + cur = arr[i].key; + if (pageunion.af == PGSQL_AF_INET) + { + diff1.bits[0] = (cur->ipr.ip4r.upper - pageunion.ipr.ip4r.lower); + diff2.bits[0] = (pageunion.ipr.ip4r.upper - cur->ipr.ip4r.lower); + diff1.bits[1] = diff2.bits[1] = 0; + } + else + { + ip6_sub(&cur->ipr.ip6r.upper, &pageunion.ipr.ip6r.lower, &diff1); + ip6_sub(&pageunion.ipr.ip6r.upper, &cur->ipr.ip6r.lower, &diff2); + } + switch (ip6_compare(&diff1,&diff2)) + { + case -1: + ADDLIST(listL, unionL, posL, arr[i].pos); + break; + case 0: + if (posL > posR) + ADDLIST(listR, unionR, posR, arr[i].pos); + else + ADDLIST(listL, unionL, posL, arr[i].pos); + break; + case 1: + ADDLIST(listR, unionR, posR, arr[i].pos); + break; + } + } + + pfree(arr); + } + + v->spl_nleft = posL; + v->spl_nright = posR; + + PG_RETURN_POINTER(v); +} + +#undef ADDLIST + +/* +** Equality methods +*/ +PG_FUNCTION_INFO_V1(gipr_same); +Datum +gipr_same(PG_FUNCTION_ARGS) +{ + IPR_KEY *v1 = (IPR_KEY *) PG_GETARG_POINTER(0); + IPR_KEY *v2 = (IPR_KEY *) PG_GETARG_POINTER(1); + bool *result = (bool *) PG_GETARG_POINTER(2); + + if (!v1 || !v2) + *result = (v1 == NULL && v2 == NULL); + if (v1->af != v2->af) + *result = false; + else + { + switch (v1->af) + { + case 0: + *result = true; + break; + + case PGSQL_AF_INET: + *result = ip4r_equal(&v1->ipr.ip4r,&v2->ipr.ip4r); + break; + + case PGSQL_AF_INET6: + *result = ip6r_equal(&v1->ipr.ip6r,&v2->ipr.ip6r); + break; + } + } + +#ifdef GIST_DEBUG + fprintf(stderr, "same: %s\n", (*result ? "true" : "false")); +#endif + + PG_RETURN_POINTER(result); +} + + +/* + * Strategy numbers: + * OPERATOR 1 >>= , + * OPERATOR 2 <<= , + * OPERATOR 3 >> , + * OPERATOR 4 << , + * OPERATOR 5 && , + * OPERATOR 6 = , + */ + +/* +** SUPPORT ROUTINES +*/ + +static bool +gipr_leaf_consistent(IPR_KEY *key, + IPR_P queryp, + StrategyNumber strategy) +{ + IPR query; + int af = ipr_unpack(queryp, &query); + +#ifdef GIST_QUERY_DEBUG + fprintf(stderr, "leaf_consistent, %d\n", strategy); +#endif + + if (key->af == 0) + { + switch (strategy) + { + case 1: /* left contains right nonstrict */ + return true; + case 2: /* left contained in right nonstrict */ + return (af == 0); + case 3: /* left contains right strict */ + return !(af == 0); + case 4: /* left contained in right strict */ + return false; + case 5: /* left overlaps right */ + return true; + case 6: /* left equal right */ + return (af == 0); + } + } + else if (af == 0) + { + switch (strategy) + { + case 1: /* left contains right nonstrict */ + return false; + case 2: /* left contained in right nonstrict */ + return true; + case 3: /* left contains right strict */ + return false; + case 4: /* left contained in right strict */ + return true; + case 5: /* left overlaps right */ + return true; + case 6: /* left equal right */ + return false; + } + } + else if (af != key->af) + return false; + else if (af == PGSQL_AF_INET) + { + switch (strategy) + { + case 1: /* left contains right nonstrict */ + return ip4r_contains_internal(&key->ipr.ip4r, &query.ip4r, true); + case 2: /* left contained in right nonstrict */ + return ip4r_contains_internal(&query.ip4r, &key->ipr.ip4r, true); + case 3: /* left contains right strict */ + return ip4r_contains_internal(&key->ipr.ip4r, &query.ip4r, false); + case 4: /* left contained in right strict */ + return ip4r_contains_internal(&query.ip4r, &key->ipr.ip4r, false); + case 5: /* left overlaps right */ + return ip4r_overlaps_internal(&key->ipr.ip4r, &query.ip4r); + case 6: /* left equal right */ + return ip4r_equal(&key->ipr.ip4r, &query.ip4r); + } + } + else if (af == PGSQL_AF_INET6) + { + switch (strategy) + { + case 1: /* left contains right nonstrict */ + return ip6r_contains_internal(&key->ipr.ip6r, &query.ip6r, true); + case 2: /* left contained in right nonstrict */ + return ip6r_contains_internal(&query.ip6r, &key->ipr.ip6r, true); + case 3: /* left contains right strict */ + return ip6r_contains_internal(&key->ipr.ip6r, &query.ip6r, false); + case 4: /* left contained in right strict */ + return ip6r_contains_internal(&query.ip6r, &key->ipr.ip6r, false); + case 5: /* left overlaps right */ + return ip6r_overlaps_internal(&key->ipr.ip6r, &query.ip6r); + case 6: /* left equal right */ + return ip6r_equal(&key->ipr.ip6r, &query.ip6r); + } + } + return false; +} + +/* logic notes: + * If the union value we're looking at overlaps with our query value + * at all, then any of the values underneath it might overlap with us + * or be contained by us, so all the "contained by" and "overlaps" + * cases degenerate to "overlap". + * If the union value is equal to the query value, then none of the + * values under it can strictly contain the query value, so for + * "contained" queries the strictness is preserved. + * If we're looking for an "equal" value, then we have to enter any + * subtree whose union contains (not strictly) our query value. + */ + +static bool +gipr_internal_consistent(IPR_KEY *key, + IPR_P queryp, + StrategyNumber strategy) +{ + IPR query; + int af = ipr_unpack(queryp, &query); + +#ifdef GIST_QUERY_DEBUG + fprintf(stderr, "leaf_consistent, %d\n", strategy); +#endif + + if (af == 0 && strategy == 4) + return false; + else if (key->af == 0 || af == 0) + return true; + else if (af != key->af) + return false; + else if (af == PGSQL_AF_INET) + { + switch (strategy) + { + case 2: /* left contained in right nonstrict */ + case 4: /* left contained in right strict */ + case 5: /* left overlaps right */ + return ip4r_overlaps_internal(&key->ipr.ip4r, &query.ip4r); + case 3: /* left contains right strict */ + return ip4r_contains_internal(&key->ipr.ip4r, &query.ip4r, false); + case 1: /* left contains right nonstrict */ + case 6: /* left equal right */ + return ip4r_contains_internal(&key->ipr.ip4r, &query.ip4r, true); + } + } + else if (af == PGSQL_AF_INET6) + { + switch (strategy) + { + case 2: /* left contained in right nonstrict */ + case 4: /* left contained in right strict */ + case 5: /* left overlaps right */ + return ip6r_overlaps_internal(&key->ipr.ip6r, &query.ip6r); + case 3: /* left contains right strict */ + return ip6r_contains_internal(&key->ipr.ip6r, &query.ip6r, false); + case 1: /* left contains right nonstrict */ + case 6: /* left equal right */ + return ip6r_contains_internal(&key->ipr.ip6r, &query.ip6r, true); + } + } + return false; +} + +/* end */ diff -Nru ip4r-2.3/src/ipr.h ip4r-2.4/src/ipr.h --- ip4r-2.3/src/ipr.h 1970-01-01 00:00:00.000000000 +0000 +++ ip4r-2.4/src/ipr.h 2018-11-21 06:35:30.000000000 +0000 @@ -0,0 +1,151 @@ +/* ipr.h */ +#ifndef IPR_H +#define IPR_H + +#include +#include + +#include "fmgr.h" + +#include "utils/inet.h" +#include "utils/palloc.h" + +#if !defined(PG_VERSION_NUM) +#error "Unknown or unsupported postgresql version" +#endif +#if PG_VERSION_NUM < 80400 +#error "Unknown or unsupported postgresql version" +#endif + +#ifndef PGDLLEXPORT +#define PGDLLEXPORT +#endif + +PGDLLEXPORT bool ip4_raw_input(const char *src, uint32 *dst); +PGDLLEXPORT bool ip6_raw_input(const char *src, uint64 *dst); +PGDLLEXPORT int ip4_raw_output(uint32 ip, char *str, int len); +PGDLLEXPORT int ip6_raw_output(uint64 *ip, char *str, int len); + +/* IP4 = uint32, stored in host-order. fixed-length and pass by value. */ +typedef uint32 IP4; + +#define IP4_INITIALIZER 0 + +/* IP4R = range of IP4, stored in host-order. fixed-length by reference */ +typedef struct IP4R { + IP4 lower; + IP4 upper; +} IP4R; + +#define IP4R_INITIALIZER {0,0} + +/* + * IP6 = 2 x uint64, stored hi to lo, each stored in host-order. + * fixed-length and pass by reference. + */ +typedef struct IP6 { + uint64 bits[2]; +} IP6; + +#define IP6_INITIALIZER {{0,0}} + +/* IP6R = range of IP6. fixed-length by reference */ +typedef struct IP6R { + IP6 lower; + IP6 upper; +} IP6R; + +#define IP6R_INITIALIZER {IP6_INITIALIZER,IP6_INITIALIZER} + +#define IP6_STRING_MAX (sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255")+2) +#define IP6R_STRING_MAX (2*IP6_STRING_MAX) + +#define IP4_STRING_MAX (sizeof("255.255.255.255")) +#define IP4R_STRING_MAX (2*IP4_STRING_MAX) + +typedef union IP { + IP6 ip6; + IP4 ip4; +} IP; + +#define IP_INITIALIZER {IP6_INITIALIZER} + +#define ipr_af_maxbits(af_) ((af_) == PGSQL_AF_INET ? 32 : 128) +#define ip_sizeof(af_) ((af_) == PGSQL_AF_INET ? sizeof(IP4) : sizeof(IP6)) +#define ipr_sizeof(af_) ((af_) == PGSQL_AF_INET ? sizeof(IP4R) : sizeof(IP6R)) + +typedef void *IP_P; /* unaligned! */ + +PGDLLEXPORT void ipaddr_internal_error(void) __attribute__((noreturn)); + +static inline +int ip_unpack(IP_P in, IP *out) +{ + switch (VARSIZE_ANY_EXHDR(in)) + { + case sizeof(IP4): + memcpy(&out->ip4, VARDATA_ANY(in), sizeof(IP4)); + return PGSQL_AF_INET; + case sizeof(IP6): + memcpy(&out->ip6, VARDATA_ANY(in), sizeof(IP6)); + return PGSQL_AF_INET6; + default: + ipaddr_internal_error(); + } +} + +static inline +IP_P ip_pack(int af, IP *val) +{ + int sz = ip_sizeof(af); + IP_P out = palloc(VARHDRSZ + sz); + + SET_VARSIZE(out, VARHDRSZ + sz); + memcpy(VARDATA(out), val, sz); + return out; +} + +typedef union IPR { + IP6R ip6r; + IP4R ip4r; +} IPR; + +#define IPR_INITIALIZER {IP6R_INITIALIZER} + +typedef void *IPR_P; /* unaligned! */ + +PGDLLEXPORT int ipr_unpack(IPR_P in, IPR *out); +PGDLLEXPORT IPR_P ipr_pack(int af, IPR *val); + +#define DatumGetIP4RP(X) ((IP4R *) DatumGetPointer(X)) +#define IP4RPGetDatum(X) PointerGetDatum(X) +#define PG_GETARG_IP4R_P(n) DatumGetIP4RP(PG_GETARG_DATUM(n)) +#define PG_RETURN_IP4R_P(x) return IP4RPGetDatum(x) + +#define DatumGetIP4(X) DatumGetUInt32(X) +#define IP4GetDatum(X) UInt32GetDatum(X) +#define PG_GETARG_IP4(n) PG_GETARG_UINT32(n) +#define PG_RETURN_IP4(x) PG_RETURN_UINT32(x) + +#define DatumGetIP6RP(X) ((IP6R *) DatumGetPointer(X)) +#define IP6RPGetDatum(X) PointerGetDatum(X) +#define PG_GETARG_IP6R_P(n) DatumGetIP6RP(PG_GETARG_DATUM(n)) +#define PG_RETURN_IP6R_P(x) return IP6RPGetDatum(x) + +#define DatumGetIP6P(X) ((IP6 *) DatumGetPointer(X)) +#define IP6PGetDatum(X) PointerGetDatum(X) +#define PG_GETARG_IP6_P(n) DatumGetIP6P(PG_GETARG_DATUM(n)) +#define PG_RETURN_IP6_P(x) return IP6PGetDatum(x) + +#define DatumGetIP_P(X) ((IP_P) PG_DETOAST_DATUM_PACKED(X)) +#define IP_PGetDatum(X) PointerGetDatum(X) +#define PG_GETARG_IP_P(n) DatumGetIP_P(PG_GETARG_DATUM(n)) +#define PG_RETURN_IP_P(x) return IP_PGetDatum(x) + +#define DatumGetIPR_P(X) ((IP_P) PG_DETOAST_DATUM_PACKED(X)) +#define IPR_PGetDatum(X) PointerGetDatum(X) +#define PG_GETARG_IPR_P(n) DatumGetIPR_P(PG_GETARG_DATUM(n)) +#define PG_RETURN_IPR_P(x) return IPR_PGetDatum(x) + +#endif +/* end */ diff -Nru ip4r-2.3/src/ipr_internal.h ip4r-2.4/src/ipr_internal.h --- ip4r-2.3/src/ipr_internal.h 1970-01-01 00:00:00.000000000 +0000 +++ ip4r-2.4/src/ipr_internal.h 2018-11-21 06:35:30.000000000 +0000 @@ -0,0 +1,312 @@ +/* ipr_internal.h */ +#ifndef IPR_INTERNAL_H +#define IPR_INTERNAL_H + +#include "ipr.h" + +#define IP4R_VERSION_STR "2.4.0" +#define IP4R_VERSION_NUM 20400 + +/* PG version dependencies */ + +#define INET_STRUCT_DATA(is_) ((inet_struct *)VARDATA_ANY(is_)) + +#define GISTENTRYCOUNT(v) ((v)->n) +#define GISTENTRYVEC(v) ((v)->vector) + +/* hash_any_extended is new in pg11. On older pg, we don't care about what the + * extended hash functions return, so just fake it. + */ + +#if PG_VERSION_NUM < 110000 + +#ifndef ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE +#define ERRCODE_INVALID_PRECEDING_OR_FOLLOWING_SIZE MAKE_SQLSTATE('2','2','0','1','3') +#endif + +#ifndef DatumGetUInt64 +#define DatumGetUInt64(d_) ((uint64) DatumGetInt64(d_)) +#endif + +#include "access/hash.h" + +static inline +Datum hash_any_extended(register const unsigned char *k, + register int keylen, uint64 seed) +{ + Datum d = hash_any(k, keylen); + PG_RETURN_INT64((int64)(uint32) DatumGetInt32(d)); +} + +#endif + +/* funcs */ + +Datum ip4_in(PG_FUNCTION_ARGS); +Datum ip4_out(PG_FUNCTION_ARGS); +Datum ip4_recv(PG_FUNCTION_ARGS); +Datum ip4_send(PG_FUNCTION_ARGS); +Datum ip4hash(PG_FUNCTION_ARGS); +Datum ip4_hash_extended(PG_FUNCTION_ARGS); +Datum ip4_cast_to_text(PG_FUNCTION_ARGS); +Datum ip4_cast_from_text(PG_FUNCTION_ARGS); +Datum ip4_cast_from_bit(PG_FUNCTION_ARGS); +Datum ip4_cast_to_bit(PG_FUNCTION_ARGS); +Datum ip4_cast_from_bytea(PG_FUNCTION_ARGS); +Datum ip4_cast_to_bytea(PG_FUNCTION_ARGS); +Datum ip4_cast_from_inet(PG_FUNCTION_ARGS); +Datum ip4_cast_to_cidr(PG_FUNCTION_ARGS); +Datum ip4_cast_to_bigint(PG_FUNCTION_ARGS); +Datum ip4_cast_to_numeric(PG_FUNCTION_ARGS); +Datum ip4_cast_from_bigint(PG_FUNCTION_ARGS); +Datum ip4_cast_from_numeric(PG_FUNCTION_ARGS); +Datum ip4_cast_to_double(PG_FUNCTION_ARGS); +Datum ip4_cast_from_double(PG_FUNCTION_ARGS); +Datum ip4r_in(PG_FUNCTION_ARGS); +Datum ip4r_out(PG_FUNCTION_ARGS); +Datum ip4r_recv(PG_FUNCTION_ARGS); +Datum ip4r_send(PG_FUNCTION_ARGS); +Datum ip4rhash(PG_FUNCTION_ARGS); +Datum ip4r_hash_extended(PG_FUNCTION_ARGS); +Datum ip4r_cast_to_text(PG_FUNCTION_ARGS); +Datum ip4r_cast_from_text(PG_FUNCTION_ARGS); +Datum ip4r_cast_from_bit(PG_FUNCTION_ARGS); +Datum ip4r_cast_to_bit(PG_FUNCTION_ARGS); +Datum ip4r_cast_from_cidr(PG_FUNCTION_ARGS); +Datum ip4r_cast_to_cidr(PG_FUNCTION_ARGS); +Datum ip4r_cast_from_ip4(PG_FUNCTION_ARGS); +Datum ip4r_from_ip4s(PG_FUNCTION_ARGS); +Datum ip4r_net_prefix(PG_FUNCTION_ARGS); +Datum ip4r_net_mask(PG_FUNCTION_ARGS); +Datum ip4r_lower(PG_FUNCTION_ARGS); +Datum ip4r_upper(PG_FUNCTION_ARGS); +Datum ip4r_is_cidr(PG_FUNCTION_ARGS); +Datum ip4r_cidr_split(PG_FUNCTION_ARGS); +Datum ip4_netmask(PG_FUNCTION_ARGS); +Datum ip4_net_lower(PG_FUNCTION_ARGS); +Datum ip4_net_upper(PG_FUNCTION_ARGS); +Datum ip4_plus_int(PG_FUNCTION_ARGS); +Datum ip4_plus_bigint(PG_FUNCTION_ARGS); +Datum ip4_plus_numeric(PG_FUNCTION_ARGS); +Datum ip4_minus_int(PG_FUNCTION_ARGS); +Datum ip4_minus_bigint(PG_FUNCTION_ARGS); +Datum ip4_minus_numeric(PG_FUNCTION_ARGS); +Datum ip4_minus_ip4(PG_FUNCTION_ARGS); +Datum ip4_and(PG_FUNCTION_ARGS); +Datum ip4_or(PG_FUNCTION_ARGS); +Datum ip4_xor(PG_FUNCTION_ARGS); +Datum ip4_not(PG_FUNCTION_ARGS); +Datum ip4_lt(PG_FUNCTION_ARGS); +Datum ip4_le(PG_FUNCTION_ARGS); +Datum ip4_gt(PG_FUNCTION_ARGS); +Datum ip4_ge(PG_FUNCTION_ARGS); +Datum ip4_eq(PG_FUNCTION_ARGS); +Datum ip4_neq(PG_FUNCTION_ARGS); +Datum ip4r_lt(PG_FUNCTION_ARGS); +Datum ip4r_le(PG_FUNCTION_ARGS); +Datum ip4r_gt(PG_FUNCTION_ARGS); +Datum ip4r_ge(PG_FUNCTION_ARGS); +Datum ip4r_eq(PG_FUNCTION_ARGS); +Datum ip4r_neq(PG_FUNCTION_ARGS); +Datum ip4r_overlaps(PG_FUNCTION_ARGS); +Datum ip4r_contains(PG_FUNCTION_ARGS); +Datum ip4r_contains_strict(PG_FUNCTION_ARGS); +Datum ip4r_contained_by(PG_FUNCTION_ARGS); +Datum ip4r_contained_by_strict(PG_FUNCTION_ARGS); +Datum ip4_contains(PG_FUNCTION_ARGS); +Datum ip4_contained_by(PG_FUNCTION_ARGS); +Datum ip4r_union(PG_FUNCTION_ARGS); +Datum ip4r_inter(PG_FUNCTION_ARGS); +Datum ip4r_size(PG_FUNCTION_ARGS); +Datum ip4r_size_exact(PG_FUNCTION_ARGS); +Datum ip4r_prefixlen(PG_FUNCTION_ARGS); +Datum ip4r_cmp(PG_FUNCTION_ARGS); +Datum ip4_cmp(PG_FUNCTION_ARGS); +Datum ip4_in_range_bigint(PG_FUNCTION_ARGS); +Datum ip4_in_range_ip4(PG_FUNCTION_ARGS); +Datum ip4r_left_of(PG_FUNCTION_ARGS); +Datum ip4r_right_of(PG_FUNCTION_ARGS); + +Datum ip6_in(PG_FUNCTION_ARGS); +Datum ip6_out(PG_FUNCTION_ARGS); +Datum ip6_recv(PG_FUNCTION_ARGS); +Datum ip6_send(PG_FUNCTION_ARGS); +Datum ip6hash(PG_FUNCTION_ARGS); +Datum ip6_hash_extended(PG_FUNCTION_ARGS); +Datum ip6_cast_to_text(PG_FUNCTION_ARGS); +Datum ip6_cast_from_text(PG_FUNCTION_ARGS); +Datum ip6_cast_from_bit(PG_FUNCTION_ARGS); +Datum ip6_cast_to_bit(PG_FUNCTION_ARGS); +Datum ip6_cast_from_bytea(PG_FUNCTION_ARGS); +Datum ip6_cast_to_bytea(PG_FUNCTION_ARGS); +Datum ip6_cast_from_inet(PG_FUNCTION_ARGS); +Datum ip6_cast_to_cidr(PG_FUNCTION_ARGS); +Datum ip6_cast_to_numeric(PG_FUNCTION_ARGS); +Datum ip6_cast_from_numeric(PG_FUNCTION_ARGS); +Datum ip6r_in(PG_FUNCTION_ARGS); +Datum ip6r_out(PG_FUNCTION_ARGS); +Datum ip6r_recv(PG_FUNCTION_ARGS); +Datum ip6r_send(PG_FUNCTION_ARGS); +Datum ip6rhash(PG_FUNCTION_ARGS); +Datum ip6r_hash_extended(PG_FUNCTION_ARGS); +Datum ip6r_cast_to_text(PG_FUNCTION_ARGS); +Datum ip6r_cast_from_text(PG_FUNCTION_ARGS); +Datum ip6r_cast_from_bit(PG_FUNCTION_ARGS); +Datum ip6r_cast_to_bit(PG_FUNCTION_ARGS); +Datum ip6r_cast_from_cidr(PG_FUNCTION_ARGS); +Datum ip6r_cast_to_cidr(PG_FUNCTION_ARGS); +Datum ip6r_cast_from_ip6(PG_FUNCTION_ARGS); +Datum ip6r_from_ip6s(PG_FUNCTION_ARGS); +Datum ip6r_net_prefix(PG_FUNCTION_ARGS); +Datum ip6r_net_mask(PG_FUNCTION_ARGS); +Datum ip6r_lower(PG_FUNCTION_ARGS); +Datum ip6r_upper(PG_FUNCTION_ARGS); +Datum ip6r_is_cidr(PG_FUNCTION_ARGS); +Datum ip6r_cidr_split(PG_FUNCTION_ARGS); +Datum ip6_netmask(PG_FUNCTION_ARGS); +Datum ip6_net_lower(PG_FUNCTION_ARGS); +Datum ip6_net_upper(PG_FUNCTION_ARGS); +Datum ip6_plus_int(PG_FUNCTION_ARGS); +Datum ip6_plus_bigint(PG_FUNCTION_ARGS); +Datum ip6_plus_numeric(PG_FUNCTION_ARGS); +Datum ip6_minus_int(PG_FUNCTION_ARGS); +Datum ip6_minus_bigint(PG_FUNCTION_ARGS); +Datum ip6_minus_numeric(PG_FUNCTION_ARGS); +Datum ip6_minus_ip6(PG_FUNCTION_ARGS); +Datum ip6_and(PG_FUNCTION_ARGS); +Datum ip6_or(PG_FUNCTION_ARGS); +Datum ip6_xor(PG_FUNCTION_ARGS); +Datum ip6_not(PG_FUNCTION_ARGS); +Datum ip6_lt(PG_FUNCTION_ARGS); +Datum ip6_le(PG_FUNCTION_ARGS); +Datum ip6_gt(PG_FUNCTION_ARGS); +Datum ip6_ge(PG_FUNCTION_ARGS); +Datum ip6_eq(PG_FUNCTION_ARGS); +Datum ip6_neq(PG_FUNCTION_ARGS); +Datum ip6r_lt(PG_FUNCTION_ARGS); +Datum ip6r_le(PG_FUNCTION_ARGS); +Datum ip6r_gt(PG_FUNCTION_ARGS); +Datum ip6r_ge(PG_FUNCTION_ARGS); +Datum ip6r_eq(PG_FUNCTION_ARGS); +Datum ip6r_neq(PG_FUNCTION_ARGS); +Datum ip6r_overlaps(PG_FUNCTION_ARGS); +Datum ip6r_contains(PG_FUNCTION_ARGS); +Datum ip6r_contains_strict(PG_FUNCTION_ARGS); +Datum ip6r_contained_by(PG_FUNCTION_ARGS); +Datum ip6r_contained_by_strict(PG_FUNCTION_ARGS); +Datum ip6_contains(PG_FUNCTION_ARGS); +Datum ip6_contained_by(PG_FUNCTION_ARGS); +Datum ip6r_union(PG_FUNCTION_ARGS); +Datum ip6r_inter(PG_FUNCTION_ARGS); +Datum ip6r_size(PG_FUNCTION_ARGS); +Datum ip6r_size_exact(PG_FUNCTION_ARGS); +Datum ip6r_prefixlen(PG_FUNCTION_ARGS); +Datum ip6r_cmp(PG_FUNCTION_ARGS); +Datum ip6_cmp(PG_FUNCTION_ARGS); +Datum ip6_in_range_bigint(PG_FUNCTION_ARGS); +Datum ip6_in_range_ip6(PG_FUNCTION_ARGS); +#if 0 +Datum ip6_in_range_numeric(PG_FUNCTION_ARGS); +#endif +Datum ip6r_left_of(PG_FUNCTION_ARGS); +Datum ip6r_right_of(PG_FUNCTION_ARGS); + +Datum ipaddr_in(PG_FUNCTION_ARGS); +Datum ipaddr_out(PG_FUNCTION_ARGS); +Datum ipaddr_recv(PG_FUNCTION_ARGS); +Datum ipaddr_send(PG_FUNCTION_ARGS); +Datum ipaddr_hash(PG_FUNCTION_ARGS); +Datum ipaddr_hash_extended(PG_FUNCTION_ARGS); +Datum ipaddr_cast_to_text(PG_FUNCTION_ARGS); +Datum ipaddr_cast_from_text(PG_FUNCTION_ARGS); +Datum ipaddr_cast_from_bit(PG_FUNCTION_ARGS); +Datum ipaddr_cast_to_bit(PG_FUNCTION_ARGS); +Datum ipaddr_cast_from_bytea(PG_FUNCTION_ARGS); +Datum ipaddr_cast_to_bytea(PG_FUNCTION_ARGS); +Datum ipaddr_cast_from_inet(PG_FUNCTION_ARGS); +Datum ipaddr_cast_to_cidr(PG_FUNCTION_ARGS); +Datum ipaddr_cast_to_numeric(PG_FUNCTION_ARGS); +Datum ipaddr_cast_from_ip4(PG_FUNCTION_ARGS); +Datum ipaddr_cast_from_ip6(PG_FUNCTION_ARGS); +Datum ipaddr_cast_to_ip4(PG_FUNCTION_ARGS); +Datum ipaddr_cast_to_ip6(PG_FUNCTION_ARGS); +Datum ipaddr_net_lower(PG_FUNCTION_ARGS); +Datum ipaddr_net_upper(PG_FUNCTION_ARGS); +Datum ipaddr_family(PG_FUNCTION_ARGS); +Datum ipaddr_plus_int(PG_FUNCTION_ARGS); +Datum ipaddr_plus_bigint(PG_FUNCTION_ARGS); +Datum ipaddr_plus_numeric(PG_FUNCTION_ARGS); +Datum ipaddr_minus_int(PG_FUNCTION_ARGS); +Datum ipaddr_minus_bigint(PG_FUNCTION_ARGS); +Datum ipaddr_minus_numeric(PG_FUNCTION_ARGS); +Datum ipaddr_minus_ipaddr(PG_FUNCTION_ARGS); +Datum ipaddr_and(PG_FUNCTION_ARGS); +Datum ipaddr_or(PG_FUNCTION_ARGS); +Datum ipaddr_xor(PG_FUNCTION_ARGS); +Datum ipaddr_not(PG_FUNCTION_ARGS); +Datum ipaddr_lt(PG_FUNCTION_ARGS); +Datum ipaddr_le(PG_FUNCTION_ARGS); +Datum ipaddr_gt(PG_FUNCTION_ARGS); +Datum ipaddr_ge(PG_FUNCTION_ARGS); +Datum ipaddr_eq(PG_FUNCTION_ARGS); +Datum ipaddr_neq(PG_FUNCTION_ARGS); +Datum ipaddr_cmp(PG_FUNCTION_ARGS); + +Datum iprange_in(PG_FUNCTION_ARGS); +Datum iprange_out(PG_FUNCTION_ARGS); +Datum iprange_recv(PG_FUNCTION_ARGS); +Datum iprange_send(PG_FUNCTION_ARGS); +Datum iprange_hash(PG_FUNCTION_ARGS); +Datum iprange_hash_new(PG_FUNCTION_ARGS); +Datum iprange_hash_extended(PG_FUNCTION_ARGS); +Datum iprange_cast_to_text(PG_FUNCTION_ARGS); +Datum iprange_cast_from_text(PG_FUNCTION_ARGS); +Datum iprange_cast_from_cidr(PG_FUNCTION_ARGS); +Datum iprange_cast_to_cidr(PG_FUNCTION_ARGS); +Datum iprange_cast_to_bit(PG_FUNCTION_ARGS); +Datum iprange_cast_from_ip4(PG_FUNCTION_ARGS); +Datum iprange_cast_from_ip6(PG_FUNCTION_ARGS); +Datum iprange_cast_from_ipaddr(PG_FUNCTION_ARGS); +Datum iprange_cast_from_ip4r(PG_FUNCTION_ARGS); +Datum iprange_cast_from_ip6r(PG_FUNCTION_ARGS); +Datum iprange_cast_to_ip4r(PG_FUNCTION_ARGS); +Datum iprange_cast_to_ip6r(PG_FUNCTION_ARGS); +Datum iprange_from_ip4s(PG_FUNCTION_ARGS); +Datum iprange_from_ip6s(PG_FUNCTION_ARGS); +Datum iprange_from_ipaddrs(PG_FUNCTION_ARGS); +Datum iprange_net_prefix_ip4(PG_FUNCTION_ARGS); +Datum iprange_net_prefix_ip6(PG_FUNCTION_ARGS); +Datum iprange_net_prefix(PG_FUNCTION_ARGS); +Datum iprange_net_mask_ip4(PG_FUNCTION_ARGS); +Datum iprange_net_mask_ip6(PG_FUNCTION_ARGS); +Datum iprange_net_mask(PG_FUNCTION_ARGS); +Datum iprange_lower(PG_FUNCTION_ARGS); +Datum iprange_upper(PG_FUNCTION_ARGS); +Datum iprange_is_cidr(PG_FUNCTION_ARGS); +Datum iprange_family(PG_FUNCTION_ARGS); +Datum iprange_cidr_split(PG_FUNCTION_ARGS); +Datum iprange_lt(PG_FUNCTION_ARGS); +Datum iprange_le(PG_FUNCTION_ARGS); +Datum iprange_gt(PG_FUNCTION_ARGS); +Datum iprange_ge(PG_FUNCTION_ARGS); +Datum iprange_eq(PG_FUNCTION_ARGS); +Datum iprange_neq(PG_FUNCTION_ARGS); +Datum iprange_overlaps(PG_FUNCTION_ARGS); +Datum iprange_contains(PG_FUNCTION_ARGS); +Datum iprange_contains_strict(PG_FUNCTION_ARGS); +Datum iprange_contained_by(PG_FUNCTION_ARGS); +Datum iprange_contained_by_strict(PG_FUNCTION_ARGS); +Datum iprange_contains_ip(PG_FUNCTION_ARGS); +Datum iprange_contains_ip4(PG_FUNCTION_ARGS); +Datum iprange_contains_ip6(PG_FUNCTION_ARGS); +Datum iprange_ip_contained_by(PG_FUNCTION_ARGS); +Datum iprange_ip4_contained_by(PG_FUNCTION_ARGS); +Datum iprange_ip6_contained_by(PG_FUNCTION_ARGS); +Datum iprange_union(PG_FUNCTION_ARGS); +Datum iprange_inter(PG_FUNCTION_ARGS); +Datum iprange_size(PG_FUNCTION_ARGS); +Datum iprange_size_exact(PG_FUNCTION_ARGS); +Datum iprange_prefixlen(PG_FUNCTION_ARGS); +Datum iprange_cmp(PG_FUNCTION_ARGS); + +#endif diff -Nru ip4r-2.3/src/raw_io.c ip4r-2.4/src/raw_io.c --- ip4r-2.3/src/raw_io.c 1970-01-01 00:00:00.000000000 +0000 +++ ip4r-2.4/src/raw_io.c 2018-11-21 06:35:30.000000000 +0000 @@ -0,0 +1,271 @@ +/* raw_io.c */ + +#include "postgres.h" + +#include +#include + +#include "ipr_internal.h" + +bool ip4_raw_input(const char *osrc, uint32 *dst) +{ + const unsigned char *src = (const unsigned char *)osrc; + int digits = 0; + int octets = 0; + int ch; + uint32 octet = 0; + uint32 tmp = 0; + + for (;;) + { + switch ((ch = *src++)) + { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + if (digits++ && octet == 0) + return false; /* must have been a leading 0, reject */ + octet = (octet * 10) + (ch - '0'); + if (octet > 255) + return false; + break; + + case '.': + if (!digits || ++octets > 3) + return false; + tmp = (tmp << 8) | octet; + digits = 0; + octet = 0; + break; + + case 0: + if (!digits || octets != 3) + return false; + tmp = (tmp << 8) | octet; + *dst = tmp; + return true; + + default: + return false; + } + } +} + +bool ip6_raw_input(const char *osrc, uint64 *dst) +{ + const unsigned char *src = (const unsigned char *)osrc; + const unsigned char *backtrack = src; + int ch; + int digits = 0; + int words = 0; + int gap = -1; + uint16 word = 0; + uint16 tmp[8]; + + /* leading :: needs a special case */ + if (*src == ':') + if (*++src != ':') + return false; + + for (;;) + { + switch ((ch = *src++)) + { + case '0': case '1': case '2': case '3': case '4': + case '5': case '6': case '7': case '8': case '9': + word = (word << 4) | (ch - '0'); + break; + + case 'a': case 'b': case 'c': case 'd': case 'e': case 'f': + word = (word << 4) | ((ch - 'a') + 10); + break; + + case 'A': case 'B': case 'C': case 'D': case 'E': case 'F': + word = (word << 4) | ((ch - 'A') + 10); + break; + + case ':': + if (digits == 0) + { + if (gap >= 0) + return false; + gap = words; + } + else if (!*src) + return false; /* trailing : not valid except as :: */ + + tmp[words++] = word; + if (words > 7 && *src) + return false; + backtrack = src; + word = 0; + digits = 0; + continue; + + case '.': + if (words < 1 || words > 6) + return false; + + { + uint32 ip4val; + if (!ip4_raw_input((const char *)backtrack, &ip4val)) + return false; + tmp[words++] = (ip4val >> 16); + word = (ip4val & 0xffff); + digits = 4; + } + + /* FALLTHROUGH */ + case 0: + if (digits) + tmp[words++] = word; + if (words < 8) + { + int i,d; + if (gap < 0) + return false; + d = 8 - words; + for (i = 7; i > gap+d; --i) + tmp[i] = tmp[i-d]; + for (; i > gap; --i) + tmp[i] = 0; + } + dst[0] = (((uint64)(tmp[0]) << 48) | ((uint64)(tmp[1]) << 32) + | ((uint64)(tmp[2]) << 16) | tmp[3]); + dst[1] = (((uint64)(tmp[4]) << 48) | ((uint64)(tmp[5]) << 32) + | ((uint64)(tmp[6]) << 16) | tmp[7]); + return true; + + default: + return false; + } + + if (++digits > 4) + return false; + } +} + +int ip4_raw_output(uint32 ip, char *str, int len) +{ + return snprintf(str, len, "%u.%u.%u.%u", + (ip >> 24)&0xff, (ip >> 16)&0xff, (ip >> 8)&0xff, (ip)&0xff); +} + +int ip6_raw_output(uint64 *ip, char *str, int len) +{ + uint16 tmp[8]; + char buf[sizeof("ffff:ffff:ffff:ffff:ffff:ffff:255.255.255.255") + 2]; + char *ptr = buf; + unsigned flags = (1 << 8); + int best = -1; + int best_len = 1; + int best_end; + uint16 word; + int i,j; + + tmp[0] = ip[0] >> 48; + tmp[1] = ip[0] >> 32; + tmp[2] = ip[0] >> 16; + tmp[3] = ip[0]; + tmp[4] = ip[1] >> 48; + tmp[5] = ip[1] >> 32; + tmp[6] = ip[1] >> 16; + tmp[7] = ip[1]; + + /* + * Find the best place to put :: in the output. Per RFC5952, we must: + * - not use :: to replace a single 0 word + * - use :: to replace the longest string of 0 words + * - use :: to replace the leftmost candidate string of equal length + * + * The bitmask we construct here has the least significant bit + * representing the leftmost word, and we process the bitmask by + * shifting right, therefore we are processing the original words + * left to right. Thus we take a new best position only if it is + * strictly better than the previous one. + * + * best = -1 implies that there is no position to use :: + */ + + for (i = 0; i < 8; ++i) + flags |= (tmp[i] ? (1 << i) : 0); + for (i = 0; i < 8; ++i, flags >>= 1) + if ((flags & 1) == 0 && (ffs(flags)-1) > best_len) + best = i, best_len = ffs(flags)-1; + + best_end = best + best_len - 1; + + /* + * If we're starting with a string of more than one zero word, process + * the special cases: + * + * all zeros (8 zero words) - '::' + * 6 zero words followed by a non-zero word - '::1.2.3.4' + * 5 zero words followed by 0xffff - '::ffff:1.2.3.4' + * 4 zero words followed by ffff:0 - '::ffff:0:1.2.3.4' [rfc2765] + * + * The case of 7 zero words we leave alone; that avoids trying to output + * '::1' as '::0.0.0.1'. We assume that '0.0.x.y' will never be a valid + * IPv4 address used in an IPv4-compatible IPv6 address (which are in any + * event deprecated). + */ + + if (best == 0) + { + if (best_len == 6 + || (best_len == 5 && tmp[5] == 0xffff) + || (best_len == 4 && tmp[4] == 0xffff && tmp[5] == 0)) + { + ip4_raw_output(((uint32)(tmp[6]) << 16) | tmp[7], buf, sizeof(buf)-2); + return snprintf(str, len, ":%s%s:%s", + (best_len != 6) ? ":ffff" : "", + (best_len == 4) ? ":0" : "", + buf); + } + else if (best_len == 8) + return snprintf(str, len, "::"); + } + + for (i = 0; i < 8; ++i) + { + if (i >= best && i <= best_end) + { + if (i == best_end) + *ptr++ = ':'; + continue; + } + + if (i > 0) + *ptr++ = ':'; + + word = tmp[i]; + + /* + * canonicalization rules: + * + * leading zeros must be suppressed. + * output must be lowercase. + */ + + if (!word) + *ptr++ = '0'; + else + { + word = (word >> 8) | (word << 8); + word = ((word & 0xf0f0) >> 4) | ((word & 0x0f0f) << 4); + for (j = 0; j < 3; ++j, word >>= 4) + if (word & 0xf) + break; + for (; j < 4; ++j, word >>= 4) + *ptr++ = ((word & 0xf) > 9) ? ((word & 0xf) + 'a' - 10) : ((word & 0xf) + '0'); + } + } + + if (best_end == 7) + *ptr++ = ':'; + + *ptr = 0; + + return snprintf(str, len, "%s", buf); +} + +/* end */ diff -Nru ip4r-2.3/tools/legacy-r.sed ip4r-2.4/tools/legacy-r.sed --- ip4r-2.3/tools/legacy-r.sed 1970-01-01 00:00:00.000000000 +0000 +++ ip4r-2.4/tools/legacy-r.sed 2018-11-21 06:35:30.000000000 +0000 @@ -0,0 +1,7 @@ +# +/^..CUT-HERE/,/^..CUT-END/c\ +SET client_min_messages = warning;\ +\\set ECHO none\ +\\i ip4r.sql\ +\\set ECHO all\ +RESET client_min_messages; diff -Nru ip4r-2.3/tools/legacy.sed ip4r-2.4/tools/legacy.sed --- ip4r-2.3/tools/legacy.sed 1970-01-01 00:00:00.000000000 +0000 +++ ip4r-2.4/tools/legacy.sed 2018-11-21 06:35:30.000000000 +0000 @@ -0,0 +1,22 @@ +# +/^-- complain.*CREATE EXTENSION/,/^$/c\ +-- Adjust this setting to control where the objects get created.\ +SET search_path = public;\ +\ + +# +/^-- Type definitions/a\ +\ +BEGIN; +# +/^-- type creation is needlessly chatty/a\ +\ +SET LOCAL client_min_messages = warning; + +# +/^COMMENT ON TYPE iprange/a\ +\ +COMMIT; +# +/^CREATE TYPE [^()]*;/,/^$/d +/^CREATE FUNCTION/s/CREATE FUNCTION/CREATE OR REPLACE FUNCTION/ diff -Nru ip4r-2.3/.travis.yml ip4r-2.4/.travis.yml --- ip4r-2.3/.travis.yml 2018-05-24 21:30:28.000000000 +0000 +++ ip4r-2.4/.travis.yml 2018-11-21 06:35:30.000000000 +0000 @@ -1,24 +1,29 @@ +addons: + apt: + sources: + - sourceline: "deb http://apt.postgresql.org/pub/repos/apt/ trusty-pgdg main 11" + key_url: "https://www.postgresql.org/media/keys/ACCC4CF8.asc" + before_install: - sudo /etc/init.d/postgresql stop - sudo apt-get -y --purge remove postgresql libpq-dev libpq5 postgresql-client-common postgresql-common - sudo rm -rf /var/lib/postgresql - - wget --quiet -O - https://www.postgresql.org/media/keys/ACCC4CF8.asc | sudo apt-key add - - - sudo sh -c "echo deb http://apt.postgresql.org/pub/repos/apt/ trusty-pgdg main $PGVERSION >> /etc/apt/sources.list.d/postgresql.list" - sudo apt-get update -qq - - sudo apt-get -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::="--force-confnew" install postgresql-$PGVERSION postgresql-server-dev-$PGVERSION + - sudo apt-get -y -o Dpkg::Options::=--force-confdef -o Dpkg::Options::="--force-confnew" install postgresql-${PG:?} postgresql-server-dev-${PG:?} before_script: - sudo -u postgres createuser -s "$USER" env: matrix: - - PGVERSION=9.2 - - PGVERSION=9.3 - - PGVERSION=9.4 - - PGVERSION=9.5 - - PGVERSION=9.6 - - PGVERSION=10 + - PG=9.2 + - PG=9.3 + - PG=9.4 + - PG=9.5 + - PG=9.6 + - PG=10 + - PG=11 dist: trusty