summaryrefslogtreecommitdiffstats
path: root/webapp/django/contrib/gis/db/models/sql/where.py
diff options
context:
space:
mode:
Diffstat (limited to 'webapp/django/contrib/gis/db/models/sql/where.py')
-rw-r--r--webapp/django/contrib/gis/db/models/sql/where.py64
1 files changed, 64 insertions, 0 deletions
diff --git a/webapp/django/contrib/gis/db/models/sql/where.py b/webapp/django/contrib/gis/db/models/sql/where.py
new file mode 100644
index 0000000000..a1a28d9511
--- /dev/null
+++ b/webapp/django/contrib/gis/db/models/sql/where.py
@@ -0,0 +1,64 @@
+import datetime
+from django.db.models.fields import Field
+from django.db.models.sql.where import WhereNode
+from django.contrib.gis.db.backend import get_geo_where_clause, SpatialBackend
+
+class GeoAnnotation(object):
+ """
+ The annotation used for GeometryFields; basically a placeholder
+ for metadata needed by the `get_geo_where_clause` of the spatial
+ backend.
+ """
+ def __init__(self, field, value, where):
+ self.geodetic = field.geodetic
+ self.geom_type = field._geom
+ self.value = value
+ self.where = tuple(where)
+
+class GeoWhereNode(WhereNode):
+ """
+ Used to represent the SQL where-clause for spatial databases --
+ these are tied to the GeoQuery class that created it.
+ """
+ def add(self, data, connector):
+ """
+ This is overridden from the regular WhereNode to handle the
+ peculiarties of GeometryFields, because they need a special
+ annotation object that contains the spatial metadata from the
+ field to generate the spatial SQL.
+ """
+ if not isinstance(data, (list, tuple)):
+ return super(WhereNode, self).add(data, connector)
+ alias, col, field, lookup_type, value = data
+ if not hasattr(field, "_geom"):
+ # Not a geographic field, so call `WhereNode.add`.
+ return super(GeoWhereNode, self).add(data, connector)
+ else:
+ # `GeometryField.get_db_prep_lookup` returns a where clause
+ # substitution array in addition to the parameters.
+ where, params = field.get_db_prep_lookup(lookup_type, value)
+
+ # The annotation will be a `GeoAnnotation` object that
+ # will contain the necessary geometry field metadata for
+ # the `get_geo_where_clause` to construct the appropriate
+ # spatial SQL when `make_atom` is called.
+ annotation = GeoAnnotation(field, value, where)
+ return super(WhereNode, self).add((alias, col, field.db_type(), lookup_type,
+ annotation, params), connector)
+
+ def make_atom(self, child, qn):
+ table_alias, name, db_type, lookup_type, value_annot, params = child
+
+ if isinstance(value_annot, GeoAnnotation):
+ if lookup_type in SpatialBackend.gis_terms:
+ # Getting the geographic where clause; substitution parameters
+ # will be populated in the GeoFieldSQL object returned by the
+ # GeometryField.
+ gwc = get_geo_where_clause(table_alias, name, lookup_type, value_annot)
+ return gwc % value_annot.where, params
+ else:
+ raise TypeError('Invalid lookup type: %r' % lookup_type)
+ else:
+ # If not a GeometryField, call the `make_atom` from the
+ # base class.
+ return super(GeoWhereNode, self).make_atom(child, qn)