From bfc0f06e94730831bc092359446022c080588dd8 Mon Sep 17 00:00:00 2001 From: Steve Jorgensen <stevej@stevej.name> Date: Sun, 26 Jun 2016 03:51:31 -0700 Subject: [PATCH] Use SQLite Ruby math extensions if present --- Gemfile | 1 + lib/geocoder/stores/active_record.rb | 22 +++++++++++++++++----- test/test_helper.rb | 5 +++++ test/unit/near_test.rb | 24 ++++++++++++++---------- 4 files changed, 37 insertions(+), 15 deletions(-) diff --git a/Gemfile b/Gemfile index 288a90ca..ad4ed6a9 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 771d5f89..40a0108b 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 89aa2bef..dda4330b 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 3cd9ae36..1e82c94c 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 -- GitLab