diff --git a/Gemfile b/Gemfile index 288a90caf46c6207edf968939c14a44f54ca50bd..ad4ed6a9bb9ac2090d160c25f66c8d667e005cd0 100644 --- a/Gemfile +++ b/Gemfile @@ -24,6 +24,7 @@ end group :test do gem 'sqlite3', :platform => [:ruby, :mswin, :mingw] + gem 'sqlite_ext', '~> 1.4.0', :platform => [:ruby, :mswin, :mingw] gem 'webmock' platforms :ruby do diff --git a/lib/geocoder/stores/active_record.rb b/lib/geocoder/stores/active_record.rb index 771d5f89aa963a8ca38bda40289ed1f2232d7a14..40a0108bb9d2cadc06d5c6002240ebc0afe43e2a 100644 --- a/lib/geocoder/stores/active_record.rb +++ b/lib/geocoder/stores/active_record.rb @@ -138,7 +138,7 @@ module Geocoder::Store ] bounding_box_conditions = Geocoder::Sql.within_bounding_box(*args) - if using_sqlite? + if using_unextended_sqlite? conditions = bounding_box_conditions else min_radius = options.fetch(:min_radius, 0).to_f @@ -160,7 +160,7 @@ module Geocoder::Store # capabilities (trig functions?). # def distance_sql(latitude, longitude, options = {}) - method_prefix = using_sqlite? ? "approx" : "full" + method_prefix = using_unextended_sqlite? ? "approx" : "full" Geocoder::Sql.send( method_prefix + "_distance", latitude, longitude, @@ -179,7 +179,7 @@ module Geocoder::Store options[:bearing] = Geocoder.config.distances end if options[:bearing] - method_prefix = using_sqlite? ? "approx" : "full" + method_prefix = using_unextended_sqlite? ? "approx" : "full" Geocoder::Sql.send( method_prefix + "_bearing", latitude, longitude, @@ -225,8 +225,20 @@ module Geocoder::Store conditions end + def using_unextended_sqlite? + using_sqlite? && !using_sqlite_with_extensions? + end + def using_sqlite? - connection.adapter_name.match(/sqlite/i) + !!connection.adapter_name.match(/sqlite/i) + end + + def using_sqlite_with_extensions? + connection.adapter_name.match(/sqlite/i) && + defined?(::SqliteExt) && + %W(POWER SQRT PI SIN COS ASIN ATAN2).all?{ |fn_name| + connection.raw_connection.function_created?(fn_name) + } end def using_postgres? @@ -244,7 +256,7 @@ module Geocoder::Store # Value which can be passed to where() to produce no results. # def false_condition - using_sqlite? ? 0 : "false" + using_unextended_sqlite? ? 0 : "false" end ## diff --git a/test/test_helper.rb b/test/test_helper.rb index 89aa2bef97f4884b047a70375bc5441efe77833b..dda4330bb1204138f3a9e193d18df38a72fe1d6a 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -15,6 +15,11 @@ if configs.keys.include? ENV['DB'] ActiveRecord::Base.configurations = configs db_name = ENV['DB'] + if db_name == 'sqlite' && ENV['USE_SQLITE_EXT'] == '1' then + gem 'sqlite_ext' + require 'sqlite_ext' + SqliteExt.register_ruby_math + end ActiveRecord::Base.establish_connection(db_name) ActiveRecord::Base.default_timezone = :utc diff --git a/test/unit/near_test.rb b/test/unit/near_test.rb index 3cd9ae365e8401cdbaf4e5da0d76ae2d40f4b1e5..1e82c94c16264726b63cf60d02d9a3cbd52c3118 100644 --- a/test/unit/near_test.rb +++ b/test/unit/near_test.rb @@ -3,23 +3,23 @@ require 'test_helper' class NearTest < GeocoderTestCase - def test_near_scope_options_without_sqlite_includes_bounding_box_condition - omit("Not applicable to SQLite") if ENV['DB'] == 'sqlite' + def test_near_scope_options_without_raw_sqlite_includes_bounding_box_condition + omit("Not applicable to unextended SQLite") if using_raw_sqlite? result = PlaceWithCustomResultsHandling.send(:near_scope_options, 1.0, 2.0, 5) table_name = PlaceWithCustomResultsHandling.table_name assert_match(/#{table_name}.latitude BETWEEN 0.9276\d* AND 1.0723\d* AND #{table_name}.longitude BETWEEN 1.9276\d* AND 2.0723\d* AND /, result[:conditions][0]) end - def test_near_scope_options_without_sqlite_includes_radius_condition - omit("Not applicable to SQLite") if ENV['DB'] == 'sqlite' + def test_near_scope_options_without_raw_sqlite_includes_radius_condition + omit("Not applicable to unextended SQLite") if using_raw_sqlite? result = Place.send(:near_scope_options, 1.0, 2.0, 5) assert_match(/BETWEEN \? AND \?$/, result[:conditions][0]) end - def test_near_scope_options_without_sqlite_includes_radius_default_min_radius - omit("Not applicable to SQLite") if ENV['DB'] == 'sqlite' + def test_near_scope_options_without_raw_sqlite_includes_radius_default_min_radius + omit("Not applicable to unextended SQLite") if using_raw_sqlite? result = Place.send(:near_scope_options, 1.0, 2.0, 5) @@ -27,8 +27,8 @@ class NearTest < GeocoderTestCase assert_equal(5, result[:conditions][2]) end - def test_near_scope_options_without_sqlite_includes_radius_custom_min_radius - omit("Not applicable to SQLite") if ENV['DB'] == 'sqlite' + def test_near_scope_options_without_raw_sqlite_includes_radius_custom_min_radius + omit("Not applicable to unextended SQLite") if using_raw_sqlite? result = Place.send(:near_scope_options, 1.0, 2.0, 5, :min_radius => 3) @@ -36,8 +36,8 @@ class NearTest < GeocoderTestCase assert_equal(5, result[:conditions][2]) end - def test_near_scope_options_without_sqlite_includes_radius_bogus_min_radius - omit("Not applicable to SQLite") if ENV['DB'] == 'sqlite' + def test_near_scope_options_without_raw_sqlite_includes_radius_bogus_min_radius + omit("Not applicable to unextended SQLite") if using_raw_sqlite? result = Place.send(:near_scope_options, 1.0, 2.0, 5, :min_radius => 'bogus') @@ -94,4 +94,8 @@ class NearTest < GeocoderTestCase def assert_no_consecutive_comma(string) assert_no_match(/, *,/, string, "two consecutive commas") end + + def using_raw_sqlite? + ENV['DB'] == 'sqlite' and ENV['USE_SQLITE_EXT'] != '1' + end end