私は解決策を見つけたと信じています。これには、最初にデータを変更してから、入力をマッサージすることが含まれます。うまくいったのは次のとおりです。
まず、セミコロン区切り文字を削除して、短縮せずにすべてのアドレスがいっぱいになるようにデータを変換する必要があります。私の質問に示されているサンプルデータは次のように変換されます:
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アドレスを処理するために、データベースに2番目の関数を追加しました。これは次のようになります。
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コードに、入力ip_addressに基づいていずれかのPostgres関数を呼び出すコードを追加しました。