Bug #81129 Geohash decoding returns the same result for different geohash
Submitted: 18 Apr 2016 14:41 Modified: 19 Apr 2016 8:39
Reporter: Goncharov Vitalii Email Updates:
Status: Not a Bug Impact on me:
None 
Category:MySQL Server: GIS Severity:S3 (Non-critical)
Version:5.7.11 Community Server OS:Ubuntu
Assigned to: CPU Architecture:Any

[18 Apr 2016 14:41] Goncharov Vitalii
Description:
In "MySQL Community Server 5.7.11 has been released" description was wrote - 

     * Geohash decoding (for example, for ST_LongFromGeoHash(),
       ST_LatFromGeoHash(), and ST_PointFromGeoHash()) could
       yield incorrect results due to the rounding algorithm
       being too aggressive. (Bug #22165582)

but the error can be still reproduced

How to repeat:
SELECT st_longfromgeohash('tn1xn1'),st_longfromgeohash('tn1xn4')
[18 Apr 2016 15:17] MySQL Verification Team
Thank you for the bug report.

C:\dbs>c:\dbs\5.7\bin\mysql -uroot -p --port=3570 --prompt="mysql 5.7 > "
Enter password: ******
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.13 Source distribution PULL: 2016-APR-07

Copyright (c) 2000, 2016, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql 5.7 > SELECT st_longfromgeohash('tn1xn1'),st_longfromgeohash('tn1xn4');
+------------------------------+------------------------------+
| st_longfromgeohash('tn1xn1') | st_longfromgeohash('tn1xn4') |
+------------------------------+------------------------------+
|                        47.38 |                        47.38 |
+------------------------------+------------------------------+
1 row in set (0.00 sec)
---------------------------------------------------------------------------
c:\dbs\mysql-5.7.9>bin\mysql -uroot -p --port=3309
Enter password: ******
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 2
Server version: 5.7.9 MySQL Community Server (GPL)

Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> SELECT st_longfromgeohash('tn1xn1'),st_longfromgeohash('tn1xn4');
+------------------------------+------------------------------+
| st_longfromgeohash('tn1xn1') | st_longfromgeohash('tn1xn4') |
+------------------------------+------------------------------+
|                         47.4 |                         47.4 |
+------------------------------+------------------------------+
1 row in set (0.00 sec)
[19 Apr 2016 8:39] Erik Frøseth
Posted by developer:
 
Hi Goncharov,

The result you are getting is as expected and correct, so I'm closing this as "not a bug".
If you convert those two geohashes to their binary representation, you will get the following binary values:

tn1xn1: 110011010000001111011010000001
tn1xn4: 110011010000001111011010000100

As the "standard" describes (https://en.wikipedia.org/wiki/Geohash), you shall only use the even bits (counting the leftmost bit as 0) when decoding a geohash value to it's longitude value. So, removing the odd bits gives us the following binary values for the longitude value:

tn1xn1: 1 0 1 0 0 0 0 1 1 0 1 1 0 0 0
tn1xn4: 1 0 1 0 0 0 0 1 1 0 1 1 0 0 0

Since they both are equal, the two geohashes should indeed produce the exact same longitude value.

I investigated this a bit further, and it turns out that geohash.org returns the wrong results. For instance, the geohash value 'tn1xn1' gives us the following bounding box:

Lower longitude: 47.373046875
Upper longitude: 47.384033203125
Lower latitude:  34.9859619140625
Upper latitude:  34.991455078125

Geohash.org returns [34.99 47.4] for this geohash value, and the longitude value is outside the bounding box. The same goes for the geohash value 'tn1xn4':

Lower longitude: 47.373046875
Upper longitude: 47.384033203125
Lower latitude:  34.991455078125
Upper latitude:  34.9969482421875

Geohash.org returns [34.99 47.4] for this geohash as well, and in this case both the longitude value and the latitude value is outside the bounding box. Luckily, MySQL is smart enough to return [34.994 47.38] here :-)