sql >> Database >  >> RDS >> PostgreSQL

Land bepalen vanaf IP - IPv6

Ik geloof dat ik de oplossing heb gevonden. Het gaat om het eerst aanpassen van de gegevens en vervolgens wat masseren van de invoer. Dit is wat werkte.

Eerst moeten de gegevens worden geconverteerd, zodat alle adressen vol zijn, zonder verkorting, zonder puntkommascheidingstekens. De voorbeeldgegevens die in mijn vraag worden getoond, zijn geconverteerd naar:

 t_start                          | t_end                            | t_country_code
----------------------------------+----------------------------------+----------------
 00000000000000000000000000000000 | 00ffffffffffffffffffffffffffffff | ZZ
 01000000000000000000000000000000 | 01ffffffffffffffffffffffffffffff | ZZ
...
 20000000000000000000000000000000 | 2000ffffffffffffffffffffffffffff | ZZ
...
 20011200000000000000000000000000 | 20011200ffffffffffffffffffffffff | MX
...

Dit is wat er in de database wordt opgeslagen.

De volgende stap was om het IP-adres dat in de code werd ontvangen om te zetten in hetzelfde formaat. Dit gebeurt in PHP met de volgende code (neem aan dat $ip_address is het inkomende IPv6-adres):

$addr_bin = inet_pton($ip_address);                                                                                                              
$bytes = unpack('n*', $addr_bin);
$ip_address = implode('', array_map(function ($b) {return sprintf("%04x", $b); }, $bytes));

Nu variabele $ip_adress zal het volledige IPv6-adres bevatten, bijvoorbeeld

:: => 00000000000000000000000000000000
2001:1200::ab => 200112000000000000000000000000ab

enzovoort.

Nu kunt u dit volledige adres eenvoudig vergelijken met de bereiken in de database. Ik heb een tweede functie aan de database toegevoegd om met IPv6-adressen om te gaan, die er als volgt uitziet:

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;

Ten slotte heb ik in mijn php-code de code toegevoegd die de ene of de andere Postgres-functie aanroept op basis van de invoer ip_address.



  1. Gaat java.net.Inet6Address.getByName letterlijk naar buiten en kijk of het adres bestaat

  2. Java voert geen instructies uit met parameter

  3. Hoe geef ik een record door aan een PL/pgSQL-functie?

  4. Hoe een geparametriseerde Oracle Insert-query te schrijven?