Jeg tror, jeg har fundet løsningen. Det indebærer først at ændre dataene og derefter massere inputtet. Her er, hvad der virkede.
Først skal dataene konverteres, så alle adresser er fyldte, uden afkortning, med semikolonseparatorer fjernet. Eksempeldataene vist i mit spørgsmål er konverteret til:
t_start | t_end | t_country_code
----------------------------------+----------------------------------+----------------
00000000000000000000000000000000 | 00ffffffffffffffffffffffffffffff | ZZ
01000000000000000000000000000000 | 01ffffffffffffffffffffffffffffff | ZZ
...
20000000000000000000000000000000 | 2000ffffffffffffffffffffffffffff | ZZ
...
20011200000000000000000000000000 | 20011200ffffffffffffffffffffffff | MX
...
Dette er hvad der er gemt i databasen.
Det næste trin var at konvertere IP-adressen modtaget i koden til at være i samme format. Dette gøres i PHP med følgende kode (antag at $ip_address
er den indgående IPv6-adresse):
$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
vil indeholde den fulde IPv6-adresse, for eksempel
:: => 00000000000000000000000000000000
2001:1200::ab => 200112000000000000000000000000ab
og så videre.
Nu kan du blot sammenligne denne fulde adresse med intervallerne i databasen. Jeg tilføjede en anden funktion til databasen til at håndtere IPv6-adresser, som ser sådan ud:
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;
Til sidst tilføjede jeg i min php-kode koden, der kalder den ene eller den anden Postgres-funktion baseret på input ip_address.