app/django/contrib/gis/db/backend/mysql/query.py
author Lennard de Rijk <ljvderijk@gmail.com>
Thu, 05 Feb 2009 22:15:38 +0000
changeset 1225 1d5c58e24fd3
parent 323 ff1a9aa48cfd
permissions -rw-r--r--
Org applications can now only be made by a user when a program allows it. To do this a new access_type has been added called apply. This ensures that users can only used the seeded version of create. Also the review_overview now has his own access type to ensure the separability of hosts for different sponsors in case of org app reviews. Note that the access checks for hosts are broken and only give access to developers at the moment. Patch by: Lennard de Rijk Reviewed by: to-be-reviewed

"""
 This module contains the spatial lookup types, and the `get_geo_where_clause`
 routine for MySQL.

 Please note that MySQL only supports bounding box queries, also
 known as MBRs (Minimum Bounding Rectangles).  Moreover, spatial
 indices may only be used on MyISAM tables -- if you need 
 transactions, take a look at PostGIS.
"""
from django.db import connection
qn = connection.ops.quote_name

# To ease implementation, WKT is passed to/from MySQL.
GEOM_FROM_TEXT = 'GeomFromText'
GEOM_FROM_WKB = 'GeomFromWKB'
GEOM_SELECT = 'AsText(%s)'

# WARNING: MySQL is NOT compliant w/the OpenGIS specification and
# _every_ one of these lookup types is on the _bounding box_ only.
MYSQL_GIS_FUNCTIONS = {
    'bbcontains' : 'MBRContains', # For consistency w/PostGIS API
    'bboverlaps' : 'MBROverlaps', # .. ..
    'contained' : 'MBRWithin',    # .. ..
    'contains' : 'MBRContains',
    'disjoint' : 'MBRDisjoint',
    'equals' : 'MBREqual',
    'exact' : 'MBREqual',
    'intersects' : 'MBRIntersects',
    'overlaps' : 'MBROverlaps',
    'same_as' : 'MBREqual',
    'touches' : 'MBRTouches',
    'within' : 'MBRWithin',
    }

# This lookup type does not require a mapping.
MISC_TERMS = ['isnull']

# Assacceptable lookup types for Oracle spatial.
MYSQL_GIS_TERMS  = MYSQL_GIS_FUNCTIONS.keys()
MYSQL_GIS_TERMS += MISC_TERMS
MYSQL_GIS_TERMS = dict((term, None) for term in MYSQL_GIS_TERMS) # Making dictionary 

def get_geo_where_clause(table_alias, name, lookup_type, geo_annot):
    "Returns the SQL WHERE clause for use in MySQL spatial SQL construction."
    # Getting the quoted field as `geo_col`.
    geo_col = '%s.%s' % (qn(table_alias), qn(name))

    # See if a MySQL Geometry function matches the lookup type next
    lookup_info = MYSQL_GIS_FUNCTIONS.get(lookup_type, False)
    if lookup_info:
        return "%s(%s, %%s)" % (lookup_info, geo_col)
    
    # Handling 'isnull' lookup type
    # TODO: Is this needed because MySQL cannot handle NULL
    # geometries in its spatial indices.
    if lookup_type == 'isnull':
        return "%s IS %sNULL" % (geo_col, (not geo_annot.value and 'NOT ' or ''))

    raise TypeError("Got invalid lookup_type: %s" % repr(lookup_type))