PostgreSQL returns the error "input is out of range" when graticule is calculating the distance between a
given origin point and itself.
I've encountered this bug via acts_as_geocodable, doing something like this:
Place acts_as_geocodable
Place.find :all, :origin => bad_place, :within => 1.0
where bad_place has a geocode with latitude 43.767626, longitude -79.272319.
The error stems from the WHERE clause in the following SQL code produced by acts_as_geocodable. The WHERE clause is
generated by Graticule::Distance::Spherical.to_sql.
SELECT places.*,
(ACOS( SIN(RADIANS(43.767626)) * SIN(RADIANS(geocodes.latitude)) +
COS(RADIANS(43.767626)) * COS(RADIANS(geocodes.latitude)) *
COS(RADIANS(geocodes.longitude) - RADIANS(-79.272319)) ) * 6378.135)
AS distance
FROM places
JOIN geocodings ON places.id = geocodings.geocodable_id AND
geocodings.geocodable_type = 'Place'
JOIN geocodes ON geocodings.geocode_id = geocodes.id
WHERE ((ACOS( SIN(RADIANS(43.767626)) * SIN(RADIANS(geocodes.latitude)) +
COS(RADIANS(43.767626)) * COS(RADIANS(geocodes.latitude)) *
COS(RADIANS(geocodes.longitude) - RADIANS(-79.272319)) ) * 6378.135) <= 1.0)
In the WHERE clause, the value within ACOS() evaluates to 1 when calculating the distance between the origin and itself.
I believe this triggers a rounding error, which results in PostgreSQL trying to calculate ACOS of some number bigger
than 1, which is Bad.
I have a simple workaround which adds an ":exclude_origin" option to acts_as_geocodable. This avoids the recursive
distance calc altogether. But it's hacky, since it just sidesteps the underlying issue. Happy to give you this patch
if you want it.
A better fix would bound the value passed to ACOS() within the range [-1..1]. I am not smart enough about PostgreSQL
yet to write this code. (E.g. you could do a ceil or floor call, but those calls don't work with double precision numbers.
Is the type conversion easy? Can't seem to find it.)
Another fix would solve the rounding error in PostgreSQL, but that would only help graticule running on newer versions
of the database.
A similar bug is also described here:
http://www.nabble.com/PGError%3A-input-out-of-range-to12217589.html#a12217589 |