Вярвам, че намерих решението. Това включва първо модифициране на данните и след това известно масажиране на входа. Ето какво проработи.
Първо, данните трябва да бъдат конвертирани, така че всички адреси да са пълни, без съкращения, с премахнати разделители точка и запетая. Примерните данни, показани в моя въпрос, се преобразуват в:
t_start | t_end | t_country_code
----------------------------------+----------------------------------+----------------
00000000000000000000000000000000 | 00ffffffffffffffffffffffffffffff | ZZ
01000000000000000000000000000000 | 01ffffffffffffffffffffffffffffff | ZZ
...
20000000000000000000000000000000 | 2000ffffffffffffffffffffffffffff | ZZ
...
20011200000000000000000000000000 | 20011200ffffffffffffffffffffffff | MX
...
Това е, което се съхранява в базата данни.
Следващата стъпка беше преобразуването на IP адреса, получен в кода, в същия формат. Това се прави в PHP със следния код (да приемем, че $ip_address
е входящият IPv6 адрес):
$addr_bin = inet_pton($ip_address);
$bytes = unpack('n*', $addr_bin);
$ip_address = implode('', array_map(function ($b) {return sprintf("%04x", $b); }, $bytes));
Сега променлива $ip_adress
ще съдържа пълния IPv6 адрес, например
:: => 00000000000000000000000000000000
2001:1200::ab => 200112000000000000000000000000ab
и така нататък.
Сега можете просто да сравните този пълен адрес с диапазоните в базата данни. Добавих втора функция към базата данни за работа с IPv6 адреси, която изглежда така:
CREATE OR REPLACE FUNCTION get_country_for_ipv6(character varying)
RETURNS character varying AS
$BODY$
declare
ip ALIAS for $1;
ccode varchar;
begin
select into ccode t_country_code from ipv6_to_country where addr between n_from and n_to limit 1;
if ccode is null then
ccode := '';
end if;
return ccode;
end;$BODY$
LANGUAGE plpgsql VOLATILE
COST 100;
И накрая, в моя php код добавих кода, който извиква една или друга функция на Postgres въз основа на входния ip_address.