diff --git a/lib/generators/geocoder/maxmind/templates/migration/geolite_city.rb b/lib/generators/geocoder/maxmind/templates/migration/geolite_city.rb
index d5e45f976a3d5f7b3aef2a2593d8091855fadfa3..fd2125bbc185f8a8c5be6382ecd5517973889669 100644
--- a/lib/generators/geocoder/maxmind/templates/migration/geolite_city.rb
+++ b/lib/generators/geocoder/maxmind/templates/migration/geolite_city.rb
@@ -1,24 +1,24 @@
class GeocoderMaxmindGeoliteCity < ActiveRecord::Migration
def self.up
create_table :maxmind_geolite_city_blocks, id: false do |t|
- t.column :startIpNum, 'integer unsigned', null: false
- t.column :endIpNum, 'integer unsigned', null: false
- t.column :locId, 'integer unsigned', null: false
+ t.column :start_ip_num, :bigint, null: false
+ t.column :end_ip_num, :bigint, null: false
+ t.column :loc_id, :bigint, null: false
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|
- t.column :locId, 'integer unsigned', null: false
+ t.column :loc_id, :bigint, null: false
t.string :country, null: false
t.string :region, null: false
t.string :city
- t.string :postalCode, null: false
+ t.string :postal_code, null: false
t.float :latitude
t.float :longitude
- t.integer :metroCode
- t.integer :areaCode
+ t.integer :metro_code
+ t.integer :area_code
end
- add_index :maxmind_geolite_city_location, :locId, unique: true
+ add_index :maxmind_geolite_city_location, :loc_id, unique: true
end
def self.down
diff --git a/lib/generators/geocoder/maxmind/templates/migration/geolite_country.rb b/lib/generators/geocoder/maxmind/templates/migration/geolite_country.rb
index d47d46b857b31bdf29c6995eac968e330267a071..5b3e1bf36d9526e93a86bc20a80bd16baf156dba 100644
--- a/lib/generators/geocoder/maxmind/templates/migration/geolite_country.rb
+++ b/lib/generators/geocoder/maxmind/templates/migration/geolite_country.rb
@@ -1,14 +1,14 @@
class GeocoderMaxmindGeoliteCountry < ActiveRecord::Migration
def self.up
create_table :maxmind_geolite_country, id: false do |t|
- t.column :startIp, :string
- t.column :endIp, :string
- t.column :startIpNum, 'integer unsigned', null: false
- t.column :endIpNum, 'integer unsigned', null: false
+ t.column :start_ip, :string
+ t.column :end_ip, :string
+ t.column :start_ip_num, :bigint, null: false
+ t.column :end_ip_num, :bigint, null: false
t.column :country_code, :string, null: false
t.column :country, :string, null: false
end
- add_index :maxmind_geolite_country, :startIpNum, unique: true
+ add_index :maxmind_geolite_country, :start_ip_num, unique: true
end
def self.down
diff --git a/lib/geocoder/lookups/maxmind_local.rb b/lib/geocoder/lookups/maxmind_local.rb
index 8a389e3dc58d18c38b57212f3c226bf0abab6765..8fcea68a48604f7f87794ab57f416b3fd997d099 100644
--- a/lib/geocoder/lookups/maxmind_local.rb
+++ b/lib/geocoder/lookups/maxmind_local.rb
@@ -28,26 +28,30 @@ module Geocoder::Lookup
private
def results(query)
- if !configuration[:file].nil?
+ if configuration[:file]
geoip_class = RUBY_PLATFORM == "java" ? JGeoIP : GeoIP
result = geoip_class.new(configuration[:file]).city(query.to_s)
result.nil? ? [] : [result.to_hash]
elsif configuration[:package] == :city
addr = IPAddr.new(query.text).to_i
q = "SELECT l.country, l.region, l.city
- FROM maxmind_geolite_city_location l JOIN maxmind_geolite_city_blocks b USING (locId)
- WHERE b.startIpNum <= #{addr} AND #{addr} <= b.endIpNum"
- if r = ActiveRecord::Base.connection.execute(q).first
- [Hash[*[:country_name, :region_name, :city_name].zip(r).flatten]]
- end
+ FROM maxmind_geolite_city_location l JOIN maxmind_geolite_city_blocks b USING (loc_id)
+ WHERE b.start_ip_num <= #{addr} AND #{addr} <= b.end_ip_num"
+ format_result(q, [:country_name, :region_name, :city_name])
elsif configuration[:package] == :country
addr = IPAddr.new(query.text).to_i
- q = "SELECT country, country_code
- FROM maxmind_geolite_country
- WHERE startIpNum <= #{addr} AND #{addr} <= endIpNum"
- if r = ActiveRecord::Base.connection.execute(q).first
- [Hash[*[:country_name, :country_code].zip(r).flatten]]
- end
+ q = "SELECT country, country_code FROM maxmind_geolite_country
+ WHERE start_ip_num <= #{addr} AND #{addr} <= end_ip_num"
+ format_result(q, [:country_name, :country_code])
+ 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
diff --git a/lib/maxmind_database.rb b/lib/maxmind_database.rb
index f223b6b445ae59d1315ef40e2f12921719c15f1c..1949e8a6e279210353334a2d49ca730ee90bc1b1 100644
--- a/lib/maxmind_database.rb
+++ b/lib/maxmind_database.rb
@@ -37,31 +37,31 @@ module Geocoder
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)
start_time = Time.now
print "Loading data for table #{table}"
rows = []
- if table =~ /city/
- headers = nil
- else
- headers = %w[startIp endIp startIpNum endIpNum country_code country]
- end
+ columns = table_columns(table)
CSV.foreach(filepath, encoding: "ISO-8859-1") do |line|
- if line.first[0...9] == "Copyright"
- next
- elsif headers.nil?
- headers = line
- next
- else
- rows << line.to_a
- if rows.size == 10000
- insert_rows(table, headers, rows)
- rows = []
- print "."
- end
+ # Some files have header rows.
+ # skip if starts with "Copyright" or "locId" or "startIpNum"
+ next if line.first.match(/[A-z]/)
+ rows << line.to_a
+ if rows.size == 10000
+ insert_rows(table, columns, rows)
+ rows = []
+ print "."
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)"
end