Saya percaya saya menemukan solusinya. Ini melibatkan modifikasi data terlebih dahulu dan kemudian beberapa pemijatan input. Inilah yang berhasil.
Pertama, data perlu dikonversi sehingga semua alamat penuh, tanpa memperpendek, dengan pemisah titik koma dihilangkan. Data sampel yang ditampilkan dalam pertanyaan saya diubah menjadi:
t_start | t_end | t_country_code
----------------------------------+----------------------------------+----------------
00000000000000000000000000000000 | 00ffffffffffffffffffffffffffffff | ZZ
01000000000000000000000000000000 | 01ffffffffffffffffffffffffffffff | ZZ
...
20000000000000000000000000000000 | 2000ffffffffffffffffffffffffffff | ZZ
...
20011200000000000000000000000000 | 20011200ffffffffffffffffffffffff | MX
...
Inilah yang disimpan dalam database.
Langkah selanjutnya adalah mengubah alamat IP yang diterima dalam kode menjadi format yang sama. Hal ini dilakukan dalam PHP dengan kode berikut (asumsikan bahwa $ip_address
adalah alamat IPv6 yang masuk):
$addr_bin = inet_pton($ip_address);
$bytes = unpack('n*', $addr_bin);
$ip_address = implode('', array_map(function ($b) {return sprintf("%04x", $b); }, $bytes));
Sekarang variabel $ip_adress
wil berisi alamat IPv6 lengkap, misalnya
:: => 00000000000000000000000000000000
2001:1200::ab => 200112000000000000000000000000ab
dan seterusnya.
Sekarang Anda cukup membandingkan alamat lengkap ini dengan rentang dalam database. Saya menambahkan fungsi kedua ke database untuk menangani alamat IPv6, yang terlihat seperti ini:
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;
Terakhir, dalam kode php saya, saya menambahkan kode yang memanggil satu atau fungsi Postgres lainnya berdasarkan input ip_address.