|
29
|
1 |
from django.db.backends.mysql.base import DatabaseOperations |
|
|
2 |
|
|
|
3 |
from django.contrib.gis.db.backends.adapter import WKTAdapter |
|
|
4 |
from django.contrib.gis.db.backends.base import BaseSpatialOperations |
|
|
5 |
|
|
|
6 |
class MySQLOperations(DatabaseOperations, BaseSpatialOperations): |
|
|
7 |
|
|
|
8 |
compiler_module = 'django.contrib.gis.db.models.sql.compiler' |
|
|
9 |
mysql = True |
|
|
10 |
name = 'mysql' |
|
|
11 |
select = 'AsText(%s)' |
|
|
12 |
from_wkb = 'GeomFromWKB' |
|
|
13 |
from_text = 'GeomFromText' |
|
|
14 |
|
|
|
15 |
Adapter = WKTAdapter |
|
|
16 |
Adaptor = Adapter # Backwards-compatibility alias. |
|
|
17 |
|
|
|
18 |
geometry_functions = { |
|
|
19 |
'bbcontains' : 'MBRContains', # For consistency w/PostGIS API |
|
|
20 |
'bboverlaps' : 'MBROverlaps', # .. .. |
|
|
21 |
'contained' : 'MBRWithin', # .. .. |
|
|
22 |
'contains' : 'MBRContains', |
|
|
23 |
'disjoint' : 'MBRDisjoint', |
|
|
24 |
'equals' : 'MBREqual', |
|
|
25 |
'exact' : 'MBREqual', |
|
|
26 |
'intersects' : 'MBRIntersects', |
|
|
27 |
'overlaps' : 'MBROverlaps', |
|
|
28 |
'same_as' : 'MBREqual', |
|
|
29 |
'touches' : 'MBRTouches', |
|
|
30 |
'within' : 'MBRWithin', |
|
|
31 |
} |
|
|
32 |
|
|
|
33 |
gis_terms = dict([(term, None) for term in geometry_functions.keys() + ['isnull']]) |
|
|
34 |
|
|
|
35 |
def geo_db_type(self, f): |
|
|
36 |
return f.geom_type |
|
|
37 |
|
|
|
38 |
def get_geom_placeholder(self, value, srid): |
|
|
39 |
""" |
|
|
40 |
The placeholder here has to include MySQL's WKT constructor. Because |
|
|
41 |
MySQL does not support spatial transformations, there is no need to |
|
|
42 |
modify the placeholder based on the contents of the given value. |
|
|
43 |
""" |
|
|
44 |
if hasattr(value, 'expression'): |
|
|
45 |
placeholder = '%s.%s' % tuple(map(self.quote_name, value.cols[value.expression])) |
|
|
46 |
else: |
|
|
47 |
placeholder = '%s(%%s)' % self.from_text |
|
|
48 |
return placeholder |
|
|
49 |
|
|
|
50 |
def spatial_lookup_sql(self, lvalue, lookup_type, value, field, qn): |
|
|
51 |
alias, col, db_type = lvalue |
|
|
52 |
|
|
|
53 |
geo_col = '%s.%s' % (qn(alias), qn(col)) |
|
|
54 |
|
|
|
55 |
lookup_info = self.geometry_functions.get(lookup_type, False) |
|
|
56 |
if lookup_info: |
|
|
57 |
return "%s(%s, %s)" % (lookup_info, geo_col, |
|
|
58 |
self.get_geom_placeholder(value, field.srid)) |
|
|
59 |
|
|
|
60 |
# TODO: Is this really necessary? MySQL can't handle NULL geometries |
|
|
61 |
# in its spatial indexes anyways. |
|
|
62 |
if lookup_type == 'isnull': |
|
|
63 |
return "%s IS %sNULL" % (geo_col, (not value and 'NOT ' or '')) |
|
|
64 |
|
|
|
65 |
raise TypeError("Got invalid lookup_type: %s" % repr(lookup_type)) |