Skip to content
Snippets Groups Projects
Commit 00282062 authored by Alex Reisner's avatar Alex Reisner
Browse files

Support DBs other than MySQL (:maxmind_local).

parent 151d0f64
No related branches found
No related tags found
No related merge requests found
class GeocoderMaxmindGeoliteCity < ActiveRecord::Migration class GeocoderMaxmindGeoliteCity < ActiveRecord::Migration
def self.up def self.up
create_table :maxmind_geolite_city_blocks, id: false do |t| create_table :maxmind_geolite_city_blocks, id: false do |t|
t.column :startIpNum, 'integer unsigned', null: false t.column :start_ip_num, :bigint, null: false
t.column :endIpNum, 'integer unsigned', null: false t.column :end_ip_num, :bigint, null: false
t.column :locId, 'integer unsigned', null: false t.column :loc_id, :bigint, null: false
end end
add_index :maxmind_geolite_city_blocks, :startIpNum, unique: true add_index :maxmind_geolite_city_blocks, :start_ip_num, unique: true
create_table :maxmind_geolite_city_location, id: false do |t| create_table :maxmind_geolite_city_location, id: false do |t|
t.column :locId, 'integer unsigned', null: false t.column :loc_id, :bigint, null: false
t.string :country, null: false t.string :country, null: false
t.string :region, null: false t.string :region, null: false
t.string :city t.string :city
t.string :postalCode, null: false t.string :postal_code, null: false
t.float :latitude t.float :latitude
t.float :longitude t.float :longitude
t.integer :metroCode t.integer :metro_code
t.integer :areaCode t.integer :area_code
end end
add_index :maxmind_geolite_city_location, :locId, unique: true add_index :maxmind_geolite_city_location, :loc_id, unique: true
end end
def self.down def self.down
......
class GeocoderMaxmindGeoliteCountry < ActiveRecord::Migration class GeocoderMaxmindGeoliteCountry < ActiveRecord::Migration
def self.up def self.up
create_table :maxmind_geolite_country, id: false do |t| create_table :maxmind_geolite_country, id: false do |t|
t.column :startIp, :string t.column :start_ip, :string
t.column :endIp, :string t.column :end_ip, :string
t.column :startIpNum, 'integer unsigned', null: false t.column :start_ip_num, :bigint, null: false
t.column :endIpNum, 'integer unsigned', null: false t.column :end_ip_num, :bigint, null: false
t.column :country_code, :string, null: false t.column :country_code, :string, null: false
t.column :country, :string, null: false t.column :country, :string, null: false
end end
add_index :maxmind_geolite_country, :startIpNum, unique: true add_index :maxmind_geolite_country, :start_ip_num, unique: true
end end
def self.down def self.down
......
...@@ -28,26 +28,30 @@ module Geocoder::Lookup ...@@ -28,26 +28,30 @@ module Geocoder::Lookup
private private
def results(query) def results(query)
if !configuration[:file].nil? if configuration[:file]
geoip_class = RUBY_PLATFORM == "java" ? JGeoIP : GeoIP geoip_class = RUBY_PLATFORM == "java" ? JGeoIP : GeoIP
result = geoip_class.new(configuration[:file]).city(query.to_s) result = geoip_class.new(configuration[:file]).city(query.to_s)
result.nil? ? [] : [result.to_hash] result.nil? ? [] : [result.to_hash]
elsif configuration[:package] == :city elsif configuration[:package] == :city
addr = IPAddr.new(query.text).to_i addr = IPAddr.new(query.text).to_i
q = "SELECT l.country, l.region, l.city q = "SELECT l.country, l.region, l.city
FROM maxmind_geolite_city_location l JOIN maxmind_geolite_city_blocks b USING (locId) FROM maxmind_geolite_city_location l JOIN maxmind_geolite_city_blocks b USING (loc_id)
WHERE b.startIpNum <= #{addr} AND #{addr} <= b.endIpNum" WHERE b.start_ip_num <= #{addr} AND #{addr} <= b.end_ip_num"
if r = ActiveRecord::Base.connection.execute(q).first format_result(q, [:country_name, :region_name, :city_name])
[Hash[*[:country_name, :region_name, :city_name].zip(r).flatten]]
end
elsif configuration[:package] == :country elsif configuration[:package] == :country
addr = IPAddr.new(query.text).to_i addr = IPAddr.new(query.text).to_i
q = "SELECT country, country_code q = "SELECT country, country_code FROM maxmind_geolite_country
FROM maxmind_geolite_country WHERE start_ip_num <= #{addr} AND #{addr} <= end_ip_num"
WHERE startIpNum <= #{addr} AND #{addr} <= endIpNum" format_result(q, [:country_name, :country_code])
if r = ActiveRecord::Base.connection.execute(q).first end
[Hash[*[:country_name, :country_code].zip(r).flatten]] end
end
def format_result(query, attr_names)
if r = ActiveRecord::Base.connection.execute(query).first
r = r.values if r.is_a?(Hash) # some db adapters return Hash, some Array
[Hash[*attr_names.zip(r).flatten]]
else
[]
end end
end end
end end
......
...@@ -37,31 +37,31 @@ module Geocoder ...@@ -37,31 +37,31 @@ module Geocoder
private # ------------------------------------------------------------- private # -------------------------------------------------------------
def table_columns(table_name)
{
maxmind_geolite_city_blocks: %w[start_ip_num end_ip_num loc_id],
maxmind_geolite_city_location: %w[loc_id country region city postal_code latitude longitude metro_code area_code],
maxmind_geolite_country: %w[start_ip end_ip start_ip_num end_ip_num country_code country]
}[table_name.to_sym]
end
def insert_into_table(table, filepath) def insert_into_table(table, filepath)
start_time = Time.now start_time = Time.now
print "Loading data for table #{table}" print "Loading data for table #{table}"
rows = [] rows = []
if table =~ /city/ columns = table_columns(table)
headers = nil
else
headers = %w[startIp endIp startIpNum endIpNum country_code country]
end
CSV.foreach(filepath, encoding: "ISO-8859-1") do |line| CSV.foreach(filepath, encoding: "ISO-8859-1") do |line|
if line.first[0...9] == "Copyright" # Some files have header rows.
next # skip if starts with "Copyright" or "locId" or "startIpNum"
elsif headers.nil? next if line.first.match(/[A-z]/)
headers = line rows << line.to_a
next if rows.size == 10000
else insert_rows(table, columns, rows)
rows << line.to_a rows = []
if rows.size == 10000 print "."
insert_rows(table, headers, rows)
rows = []
print "."
end
end end
end end
insert_rows(table, headers, rows) if rows.size > 0 insert_rows(table, columns, rows) if rows.size > 0
puts "done (#{Time.now - start_time} seconds)" puts "done (#{Time.now - start_time} seconds)"
end end
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment