Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 1c0de61

Browse files
authored
is_inet speed improved
1 parent d52c1d6 commit 1c0de61

File tree

1 file changed

+81
-16
lines changed

1 file changed

+81
-16
lines changed

‎functions/is_inet.sql‎

Lines changed: 81 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,57 @@
1-
-- check IP syntax exactly in your PostgreSQL version
2-
create or replace function is_inet(str text, is_notice boolean default false)
3-
RETURNS boolean
1+
create or replace function public.is_inet(str text, is_notice boolean default false)
2+
returns boolean
43
returns null on null input
54
parallel unsafe --(ERROR: cannot start subtransactions during a parallel operation)
65
stable
76
language plpgsql
7+
cost 5
88
as
9-
$$
9+
$func$
1010
DECLARE
1111
exception_sqlstate text;
1212
exception_message text;
1313
exception_context text;
14+
oct_length constant int default octet_length(str);
15+
1416
BEGIN
17+
--https://en.wikipedia.org/wiki/Classless_Inter-Domain_Routing
18+
19+
--try to detect IPv4
20+
if oct_length between 7 --0.0.0.0
21+
and 18 --255.255.255.255/32
22+
and str like '%.%.%.%'
23+
and exists(
24+
select
25+
from regexp_matches(str,
26+
$regexp$
27+
^
28+
(\d{1,3}) \. (\d{1,3}) \. (\d{1,3}) \. (\d{1,3}) #1-4 addr 1..255
29+
(?:
30+
/ (\d{1,2}) #5 mask 0..32
31+
)?
32+
$
33+
$regexp,ドル 'x') as t(m)
34+
where not exists(select
35+
from unnest(m[1:4]) u(e)
36+
where e::int > 255)
37+
and (m[5] is null or m[5]::int < 33)
38+
)
39+
then
40+
return true;
41+
end if;
42+
43+
--try to detect IPv6
44+
--https://stackoverflow.com/questions/166132/maximum-length-of-the-textual-representation-of-an-ipv6-address
45+
--https://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses
46+
if not (oct_length between 2 --::
47+
and 45 --0000:0000:0000:0000:0000:ffff:255.255.255.255
48+
and str like '%:%:%') then
49+
return false;
50+
end if;
51+
52+
--slow exception block
1553
BEGIN
16-
RETURN (str::inet is not null);
54+
return (str::inet is not null);
1755
EXCEPTION WHEN others THEN
1856
IF is_notice THEN
1957
GET STACKED DIAGNOSTICS
@@ -27,18 +65,45 @@ BEGIN
2765
RETURN FALSE;
2866
END;
2967
END;
30-
$$;
68+
$func$;
69+
70+
comment on function public.is_inet(str text, is_notice boolean) is 'Check IPv4 or IPv6 host address, and optionally its subnet';
3171

3272
--TEST
33-
do $$
73+
do $do$
3474
begin
35-
--positive
36-
assert is_inet('0.0.0.0');
37-
assert is_inet('255.255.255.255');
38-
assert is_inet('192.168.0.1/24');
39-
--negative
40-
assert not is_inet('0.0.0');
41-
assert not is_inet('255.255.255.256');
42-
assert not is_inet('192.168.0.1/244');
75+
--positive IPv4
76+
assert public.is_inet('0.0.0.0');
77+
assert public.is_inet('1.2.3.4');
78+
assert public.is_inet('11.22.33.44');
79+
assert public.is_inet('255.255.255.255');
80+
assert public.is_inet('1.2.3.4/0');
81+
assert public.is_inet('1.2.3.4/32');
82+
83+
--positive IPv6
84+
assert public.is_inet('::');
85+
assert public.is_inet('1::');
86+
assert public.is_inet('::1');
87+
assert public.is_inet('1:2:3:4:5:6:7:8');
88+
assert public.is_inet('::255.255.255.255');
89+
assert public.is_inet('::ffff:0:255.255.255.255');
90+
assert public.is_inet('0000:0000:0000:0000:0000:ffff:255.255.255.255');
91+
assert public.is_inet('1:2:3:4:5:6:7:8/0');
92+
assert public.is_inet('1:2:3:4:5:6:7:8/128');
93+
94+
--negative IPv4
95+
assert not public.is_inet('1.2.3.4.');
96+
assert not public.is_inet('.1.2.3.4');
97+
assert not public.is_inet('1:2:3.4');
98+
assert not public.is_inet('0.0.0');
99+
assert not public.is_inet('255.255.255.256');
100+
assert not public.is_inet('192.168.0.1/-1');
101+
assert not public.is_inet('192.168.0.1/33');
102+
103+
--negative IPv6
104+
assert not public.is_inet(':1:2:3:4:5:6:7:8');
105+
assert not public.is_inet('1:2:3:4:5:6:7:8:');
106+
assert not public.is_inet('1:2:3:4:5:6:7:8/-1');
107+
assert not public.is_inet('1:2:3:4:5:6:7:8/129');
43108
end
44-
$$;
109+
$do$;

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /