Skip to content
Advertisement

GeoIP2 Snowflake Java UDF Integration issue

I want to create a Java UDF in a snowflake worksheet in order to query GeoIp2 library and get the ISO code of a given IP. I have ‘@AWS_CSV_STAGE/lib/geoip2-2.8.0.jar’,’@AWS_CSV_STAGE/geodata/GeoLite2-City.mmdb’ already staged. How can i direct the function handler to the method that creates the Database Reader as explained here in the documentation for Java: https://dev.maxmind.com/geoip/geolocate-an-ip/databases?lang=en#1-install-the-geoip2-client-library in general how can i achieve this whole thing below in my udf?

File database = new File("/path/to/maxmind-database.mmdb")
DatabaseReader reader = new DatabaseReader.Builder(database).build();
InetAddress ipAddress = InetAddress.getByName("128.101.101.101");
CityResponse response = reader.city(ipAddress);
Country country = response.getCountry();

so far i wrote this but of course it’s not working: anyway i couldn’t find much material about how to tackle this kind of problem.

CREATE OR REPLACE FUNCTION GEO()
  returns varchar not null
  language java
  imports = ('@AWS_CSV_STAGE/lib/geoip2-2.8.0.jar','@AWS_CSV_STAGE/geodata/GeoLite2-City.mmdb')
  handler = 'DatabaseReader.Builder';

SELECT GEO();

basically what i want to achieve is to call the UDF on a column of ip address table and get the country code in another column for each ip address.

Advertisement

Answer

Thanks for this question – I wrote a whole post going step-by-step to get this working:

You had the right idea in the code you posted, a full working UDF would be:

create or replace function geoip2_country(ip String)
returns string
language java
handler = 'X.x'
imports = ('@fh_jars/geoip2-4.0.0.jar'
         , '@fh_jars/maxmind-db-3.0.0.jar'
         , '@fh_jars/jackson-annotations-2.14.1.jar'
         , '@fh_jars/jackson-core-2.14.1.jar'
         , '@fh_jars/jackson-databind-2.14.1.jar')
as $$
import java.io.File;
import java.net.InetAddress;

import com.snowflake.snowpark_java.types.SnowflakeFile;
import com.maxmind.geoip2.model.*;
import com.maxmind.geoip2.DatabaseReader;
import com.maxmind.geoip2.exception.AddressNotFoundException;

class X {
    DatabaseReader _reader;
    
    public String x(String ip) throws Exception {
        if (null == _reader) {
            // lazy initialization
            _reader = new DatabaseReader.Builder(SnowflakeFile.newInstance("@fh_jars/GeoLite2-Country.mmdb").getInputStream()).build();
        }
        try {
            return _reader.country(InetAddress.getByName(ip)).getCountry().getIsoCode();
        } catch (AddressNotFoundException e) {
            return null;
        }
    }
}
$$;
User contributions licensed under: CC BY-SA
4 People found this is helpful
Advertisement