Storing IPv6 Addresses in MySQL
Last year when I was searching for ways to overcome the lack of built-in IPv6 functions in MySQL, I was curious how other people were solving the problem. There are solutions out there that store IPv6 addresses across two database fields, but I find this unwieldy and prefer storing them as a single value. This was by far the most elegant solution I found that doesn’t rely on external dependencies (like writing special functions for your program to handle the two-value method):
http://oierud.name/bliki/IPv6AdressesAndMysql.html
Basically, it duplicates the capabilities of the built-in IPv4 INET_ATON() and INET_NTOA() counterparts. And case the URL ever goes dead:
INET_ATON6
DELIMITER // CREATE FUNCTION INET_ATON6(n CHAR(39)) RETURNS DECIMAL(39) UNSIGNED DETERMINISTIC BEGIN RETURN CAST(CONV(SUBSTRING(n FROM 1 FOR 4), 16, 10) AS DECIMAL(39)) * 5192296858534827628530496329220096 -- 65536 ^ 7 + CAST(CONV(SUBSTRING(n FROM 6 FOR 4), 16, 10) AS DECIMAL(39)) * 79228162514264337593543950336 -- 65536 ^ 6 + CAST(CONV(SUBSTRING(n FROM 11 FOR 4), 16, 10) AS DECIMAL(39)) * 1208925819614629174706176 -- 65536 ^ 5 + CAST(CONV(SUBSTRING(n FROM 16 FOR 4), 16, 10) AS DECIMAL(39)) * 18446744073709551616 -- 65536 ^ 4 + CAST(CONV(SUBSTRING(n FROM 21 FOR 4), 16, 10) AS DECIMAL(39)) * 281474976710656 -- 65536 ^ 3 + CAST(CONV(SUBSTRING(n FROM 26 FOR 4), 16, 10) AS DECIMAL(39)) * 4294967296 -- 65536 ^ 2 + CAST(CONV(SUBSTRING(n FROM 31 FOR 4), 16, 10) AS DECIMAL(39)) * 65536 -- 65536 ^ 1 + CAST(CONV(SUBSTRING(n FROM 36 FOR 4), 16, 10) AS DECIMAL(39)) ; END; // DELIMITER ;
INET_NTOA6
DELIMITER // CREATE FUNCTION INET_NTOA6(n DECIMAL(39) UNSIGNED) RETURNS CHAR(39) DETERMINISTIC BEGIN DECLARE a CHAR(39) DEFAULT ''; DECLARE i INT DEFAULT 7; DECLARE q DECIMAL(39) UNSIGNED DEFAULT 0; DECLARE r INT DEFAULT 0; WHILE i DO -- DIV doesn't work with nubers > bigint SET q := FLOOR(n / 65536); SET r := n MOD 65536; SET n := q; SET a := CONCAT_WS(':', LPAD(CONV(r, 10, 16), 4, '0'), a); SET i := i - 1; END WHILE; SET a := TRIM(TRAILING ':' FROM CONCAT_WS(':', LPAD(CONV(n, 10, 16), 4, '0'), a)); RETURN a; END; // DELIMITER ;
[…] Storing IPv6 Addresses in MySQL […]