
-- types

CREATE TYPE city AS (
	ip_addr inet,
	city_name text,
	city_geo_id int,
	postal_code text,
	country_name text,
	country_iso_code text,
	country_geo_id int,
	subdivision_names text[],
	subdivision_geo_ids int[],
	continent_name text,
	continent_code text,
	continent_geo_id int,
	registered_country_name text,
	registered_country_iso_code text,
	registered_country_geo_id int
);

CREATE TYPE isp AS (
	ip_addr inet,
	isp text,
	organization text,
	autononous_system_number text,
	autonomous_system_organization text
);

CREATE TYPE country AS (
	ip_addr inet,
	name text,
	iso_code text,
	geo_id int,
	continent_name text,
	continent_code text,
	continent_geo_id int,
	registered_country_name text,
	registered_country_iso_code text,
	registered_country_geo_id int
);

CREATE TYPE anonymous_ip AS (
	ip_addr inet,
	is_anonymous bool,
	is_tor_exit_node bool,
	is_hosting_provider bool,
	is_anonymous_vpn bool,
	is_public_proxy bool
);

CREATE TYPE connection_type AS (
	ip_addr inet,
	connection_type text
);

-- raw function

CREATE FUNCTION raw_geoip2_json(in_ipaddr inet, in_db text, in_path text) returns jsonb
language plperlu as $_$
use JSON;
use MaxMind::DB::Reader;
use strict;
use warnings;

my ($ip, $dbname, $path) = @_;

my $db = MaxMind::DB::Reader->new( file => "${path}/GeoIP2-${dbname}.mmdb");
return JSON::to_json($db->record_for_address($ip) // {});
$_$;

CREATE FUNCTION raw_geoip2_json(in_ipaddr inet, in_db text) returns jsonb
language sql as
$$
select raw_geoip2_json($1, $2, current_setting('geoip2lookup.path'));
$$ SET search_path FROM CURRENT;

-- tuple functions


CREATE FUNCTION isp(in_addr inet, in_path text)
RETURNS isp LANGUAGE PLPERLU
AS $_$
use MaxMind::DB::Reader;
use strict;
use warnings;

my ($ip, $path) = @_;

my $db = MaxMind::DB::Reader->new( file => "${path}/GeoIP2-ISP.mmdb");
my $record = $db->record_for_address($ip);
return {
    ip_addr => $ip,
    isp => $record->{isp},
    organization => $record->{organization},
    autononous_system_number => $record->{autonomous_system_number},
    autonomous_system_organization => $record->{autonomous_system_organization} };
$_$;

CREATE FUNCTION isp(in_addr inet) RETURNS isp LANGUAGE SQL AS
$$ SELECT isp($1, current_setting('geoip2lookup.path')); $$ SET search_path FROM CURRENT;

CREATE FUNCTION connection_type(in_addr inet, in_path text) 
RETURNS connection_type
language plperlu as $_$
use MaxMind::DB::Reader;
use strict;
use warnings;

my ($ip, $path) = @_;

my $db = MaxMind::DB::Reader->new( file => "${path}/GeoIP2-Connection-Type.mmdb");
my $record = $db->record_for_address($ip);
return {
    ip_addr => $ip,
    connection_type => $record->{connection_type},
    };
$_$;

CREATE FUNCTION connection_type(in_addr inet) RETURNS connection_type 
LANGUAGE SQL AS
$$ SELECT connection_type($1, current_setting('geoip2lookup.path')); $$ SET search_path FROM CURRENT;

CREATE FUNCTION anonymous_ip(in_addr inet, in_path text) RETURNS anonymous_ip
    LANGUAGE plperlu
    AS $_$
use MaxMind::DB::Reader;
use strict;
use warnings;

my ($ip, $path) = @_;

my $db = MaxMind::DB::Reader->new( file => "${path}/GeoIP2-Anonymous-IP.mmdb");
my $record = $db->record_for_address($ip);
return {
    ip_addr => $ip,
    is_anonymous => ($record->{is_anonymous} // '0'),
    is_anonymous_vpn => ($record->{is_anonymous_vpn} // '0'),
    is_hosting_provider => ($record->{is_hosting_provider} // '0'),
    is_public_proxy => ($record->{is_public_proxy} // '0'),
    is_tor_exit_node => ($record->{is_tor_exit_node} // '0'), };
$_$;

CREATE FUNCTION anonymous_id(in_addr inet) RETURNS anonymous_ip 
LANGUAGE SQL AS
$$ SELECT anonymous_ip($1, current_setting('geoip2lookup.path')); $$ SET search_path FROM CURRENT;


CREATE FUNCTION city(in_addr inet, in_path text, in_lang text) RETURNS city
    LANGUAGE plperlu
    AS $_$
use MaxMind::DB::Reader;
use strict;
use warnings;

my ($ip, $path, $lang) = @_;

my $db = MaxMind::DB::Reader->new( file => "${path}/GeoIP2-City.mmdb");
my $record = $db->record_for_address($ip);
return {
    ip_addr => $ip,
    city_name => $record->{city}->{names}->{$lang},
    city_geo_id => $record->{city}->{geoname_id},
    postal_code => $record->{postal}->{code},
    country_name => $record->{country}->{names}->{$lang}, 
    country_iso_code => $record->{country}->{iso_code},
    country_geo_id => $record->{country}->{geoname_id},
    subdivision_names => [map { $_->{names}->{$lang} }  @{$record->{subdivisions}}],
    subdivision_geo_ids => [map { $_->{geoname_id} }  @{$record->{subdivisions}}],
    continent_name => $record->{continent}->{names}->{$lang},
    continent_code => $record->{continent}->{code},
    continent_geo_id => $record->{continent}->{geoname_id},
    registered_country_name => $record->{registered_country}->{names}->{$lang}, 
    registered_country_iso_code => $record->{registered_country}->{iso_code}, 
    registered_country_geo_id => $record->{registered_country}->{geoname_id}, };
$_$;

CREATE FUNCTION city(in_addr inet) RETURNS city
LANGUAGE SQL AS
$$ SELECT city($1, current_setting('geoip2lookup.path'), current_setting('geoip2lookup.language')); $$ SET search_path FROM CURRENT;


CREATE FUNCTION country(in_addr inet, in_path text, in_lang text) 
RETURNS country
    LANGUAGE plperlu
    AS $_$
use MaxMind::DB::Reader;
use strict;
use warnings;

my ($ip, $path, $lang) = @_;

my $db = MaxMind::DB::Reader->new( file => "${path}/GeoIP2-Country.mmdb");
my $record = $db->record_for_address($ip);
return {
    ip_addr => $ip,
    name => $record->{country}->{names}->{$lang}, 
    iso_code => $record->{country}->{iso_code},
    geo_id => $record->{country}->{geoname_id},
    continent_name => $record->{continent}->{names}->{$lang},
    continent_code => $record->{continent}->{code},
    continent_geo_id => $record->{continent}->{geoname_id},
    registered_country_name => $record->{registered_country}->{names}->{$lang}, 
    registered_country_iso_code => $record->{registered_country}->{iso_code}, 
    registered_country_geo_id => $record->{registered_country}->{geoname_id}, };
$_$;

CREATE FUNCTION country(in_addr inet) RETURNS country
LANGUAGE SQL AS
$$ SELECT country($1, current_setting('geoip2lookup.path'), current_setting('geoip2lookup.language')); $$ SET search_path FROM CURRENT;



-- forthcoming, full scans
