I would like to convert an inet formatted IPv4 address into the integer components.
For example, turn '101.255.30.40' into oct1=101, oct2=255, oct3=30, and oct4=40.
There are regex expressions that should do this if I cast the inet as a varchar, but that seems inelegant. Is there a 1-line function for returning the nth octet of an inet?
select inet_to_octet('101.255.30.40', 4) as temp; -- returns temp=40?
I finally got an excellent answer from a co-worker...
For some flavors of sql, use "split_part" along with host(inet) to get the text field.
select split_part(host('101.255.30.40'::inet), '.', 1);
select split_part(host('101.255.30.40'::inet), '.', 2);
select split_part(host('101.255.30.40'::inet), '.', 3);
select split_part(host('101.255.30.40'::inet), '.', 4);
results in
101
255
30
40
If you want to get trickier and handle IPv6, use a mask to speed up the operation along with case statements to get the IP version:
select
(case
when family('101.255.30.40'::inet) = 4 then split_part(host(broadcast(set_masklen('101.255.30.40'::inet, 32))), '.', 4)::varchar
when family('101.255.30.40'::inet) = 6 then split_part(host(broadcast(set_masklen('101.255.30.40'::inet, 64))), ':', 4)::varchar
else null end)::varchar as octet4;
select
(case
when family('2604:8f00:4:80b0:3925:c69c:458:3f7b'::inet) = 4 then split_part(host(broadcast(set_masklen('2604:8f00:4:80b0:3925:c69c:458:3f7b'::inet, 32))), '.', 4)::varchar
when family('2604:8f00:4:80b0:3925:c69c:458:3f7b'::inet) = 6 then split_part(host(broadcast(set_masklen('2604:8f00:4:80b0:3925:c69c:458:3f7b'::inet, 64))), ':', 4)::varchar
else null end)::varchar as octet4;
results in
40
80b0
you can then add in a hex-to-int conversion into the case statement if you want to cast the IPv6 as a number instead.
Unless you want to try to contribute the function to the inet datatype, you'll need to rely on a string based version. Maybe put something like this (but with some error checking) into an SQL function for easy access?:
CREATE OR REPLACE FUNCTION extract_octet(inet, integer) RETURNS integer AS $$
SELECT ((regexp_split_to_array(host($1), E'\\.'))[$2])::int;
$$ LANGUAGE SQL;
select extract_octet(inet '192.26.22.2', 2)
Output: 26
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With