|
0
|
1 |
""" |
|
|
2 |
This module contains the spatial lookup types, and the `get_geo_where_clause` |
|
|
3 |
routine for MySQL. |
|
|
4 |
|
|
|
5 |
Please note that MySQL only supports bounding box queries, also |
|
|
6 |
known as MBRs (Minimum Bounding Rectangles). Moreover, spatial |
|
|
7 |
indices may only be used on MyISAM tables -- if you need |
|
|
8 |
transactions, take a look at PostGIS. |
|
|
9 |
""" |
|
|
10 |
from django.db import connection |
|
|
11 |
qn = connection.ops.quote_name |
|
|
12 |
|
|
|
13 |
# To ease implementation, WKT is passed to/from MySQL. |
|
|
14 |
GEOM_FROM_TEXT = 'GeomFromText' |
|
|
15 |
GEOM_FROM_WKB = 'GeomFromWKB' |
|
|
16 |
GEOM_SELECT = 'AsText(%s)' |
|
|
17 |
|
|
|
18 |
# WARNING: MySQL is NOT compliant w/the OpenGIS specification and |
|
|
19 |
# _every_ one of these lookup types is on the _bounding box_ only. |
|
|
20 |
MYSQL_GIS_FUNCTIONS = { |
|
|
21 |
'bbcontains' : 'MBRContains', # For consistency w/PostGIS API |
|
|
22 |
'bboverlaps' : 'MBROverlaps', # .. .. |
|
|
23 |
'contained' : 'MBRWithin', # .. .. |
|
|
24 |
'contains' : 'MBRContains', |
|
|
25 |
'disjoint' : 'MBRDisjoint', |
|
|
26 |
'equals' : 'MBREqual', |
|
|
27 |
'exact' : 'MBREqual', |
|
|
28 |
'intersects' : 'MBRIntersects', |
|
|
29 |
'overlaps' : 'MBROverlaps', |
|
|
30 |
'same_as' : 'MBREqual', |
|
|
31 |
'touches' : 'MBRTouches', |
|
|
32 |
'within' : 'MBRWithin', |
|
|
33 |
} |
|
|
34 |
|
|
|
35 |
# This lookup type does not require a mapping. |
|
|
36 |
MISC_TERMS = ['isnull'] |
|
|
37 |
|
|
|
38 |
# Assacceptable lookup types for Oracle spatial. |
|
|
39 |
MYSQL_GIS_TERMS = MYSQL_GIS_FUNCTIONS.keys() |
|
|
40 |
MYSQL_GIS_TERMS += MISC_TERMS |
|
|
41 |
MYSQL_GIS_TERMS = dict((term, None) for term in MYSQL_GIS_TERMS) # Making dictionary |
|
|
42 |
|
|
|
43 |
def get_geo_where_clause(table_alias, name, lookup_type, geo_annot): |
|
|
44 |
"Returns the SQL WHERE clause for use in MySQL spatial SQL construction." |
|
|
45 |
# Getting the quoted field as `geo_col`. |
|
|
46 |
geo_col = '%s.%s' % (qn(table_alias), qn(name)) |
|
|
47 |
|
|
|
48 |
# See if a MySQL Geometry function matches the lookup type next |
|
|
49 |
lookup_info = MYSQL_GIS_FUNCTIONS.get(lookup_type, False) |
|
|
50 |
if lookup_info: |
|
|
51 |
return "%s(%s, %%s)" % (lookup_info, geo_col) |
|
|
52 |
|
|
|
53 |
# Handling 'isnull' lookup type |
|
|
54 |
# TODO: Is this needed because MySQL cannot handle NULL |
|
|
55 |
# geometries in its spatial indices. |
|
|
56 |
if lookup_type == 'isnull': |
|
|
57 |
return "%s IS %sNULL" % (geo_col, (not geo_annot.value and 'NOT ' or '')) |
|
|
58 |
|
|
|
59 |
raise TypeError("Got invalid lookup_type: %s" % repr(lookup_type)) |