sql >> Databasteknik >  >> RDS >> PostgreSQL

Bestäm land från IP - IPv6

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.



  1. MySQL InnoDB låser på sammanfogade rader

  2. SQL Server delad med kommatecken

  3. efterföljande nollor går inte in i databasen

  4. Hur man arbetar med PostgreSQL-databaser