Jag tror att jag hittat lösningen. Det innebär att först modifiera data och sedan massera ingången. Här är vad som fungerade.
Först måste data konverteras så att alla adresser är fulla, utan förkortning, med semikolonseparatorer borttagna. Exempeldata som visas i min fråga konverteras till:
t_start | t_end | t_country_code
----------------------------------+----------------------------------+----------------
00000000000000000000000000000000 | 00ffffffffffffffffffffffffffffff | ZZ
01000000000000000000000000000000 | 01ffffffffffffffffffffffffffffff | ZZ
...
20000000000000000000000000000000 | 2000ffffffffffffffffffffffffffff | ZZ
...
20011200000000000000000000000000 | 20011200ffffffffffffffffffffffff | MX
...
Detta är vad som lagras i databasen.
Nästa steg var att konvertera IP-adressen som tas emot i koden till samma format. Detta görs i PHP med följande kod (antag att $ip_address
är den inkommande IPv6-adressen):
$addr_bin = inet_pton($ip_address);
$bytes = unpack('n*', $addr_bin);
$ip_address = implode('', array_map(function ($b) {return sprintf("%04x", $b); }, $bytes));
Nu variabel $ip_adress
kommer att innehålla hela IPv6-adressen, till exempel
:: => 00000000000000000000000000000000
2001:1200::ab => 200112000000000000000000000000ab
och så vidare.
Nu kan du helt enkelt jämföra denna fullständiga adress med intervallen i databasen. Jag lade till en andra funktion till databasen för att hantera IPv6-adresser, som ser ut så här:
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;
Slutligen, i min php-kod lade jag till koden som anropar den ena eller andra Postgres-funktionen baserat på inmatningen ip_address.