Ticket #14483: spatial_subquery2.diff
File spatial_subquery2.diff, 8.1 KB (added by , 14 years ago) |
---|
-
django/contrib/gis/db/models/sql/where.py
46 46 data, params = lvalue.process(lookup_type, params_or_value, connection) 47 47 alias, col, db_type = data 48 48 spatial_sql = connection.ops.spatial_lookup_sql(data, lookup_type, params_or_value, lvalue.field, qn) 49 50 tables = [alias] 51 if hasattr(params, 'as_sql'): 52 if hasattr(params, 'tables'): 53 tables.extend(params.tables) 54 extra, params = params.as_sql(qn, connection) 55 spatial_sql = spatial_sql % extra 56 return spatial_sql, params, tables 49 57 return spatial_sql, params, [alias] 50 58 else: 51 59 return super(GeoWhereNode, self).make_atom(child, qn, connection) -
django/contrib/gis/db/models/fields.py
1 1 from django.db.models.fields import Field 2 2 from django.db.models.sql.expressions import SQLEvaluator 3 from django.db.models.query_utils import QueryWrapper 3 4 from django.utils.translation import ugettext_lazy as _ 4 5 from django.contrib.gis import forms 5 6 from django.contrib.gis.db.models.proxy import GeometryProxy … … 148 149 """ 149 150 if isinstance(value, SQLEvaluator): 150 151 return value 152 elif hasattr(value, 'query'): 153 return value 151 154 elif isinstance(value, (tuple, list)): 152 155 geom = value[0] 153 156 seq_value = True … … 234 237 pass 235 238 else: 236 239 params += value[1:] 240 elif hasattr(value, 'as_sql') or hasattr(value, '_as_sql'): 241 # If the value has a relabel_aliases method, it will need to 242 # be invoked before the final SQL is evaluated 243 if hasattr(value, 'relabel_aliases'): 244 return value 245 if hasattr(value, 'as_sql'): 246 sql, params = value.as_sql() 247 else: 248 sql, params = value._as_sql(connection=connection) 249 subselect_sql = connection.ops.wrap_spatial_subselect(sql) 250 return QueryWrapper((subselect_sql), params, value.query.tables) 237 251 elif isinstance(value, SQLEvaluator): 238 252 params = [] 239 253 else: -
django/contrib/gis/db/backends/spatialite/operations.py
188 188 """ 189 189 def transform_value(value, srid): 190 190 return not (value is None or value.srid == srid) 191 if hasattr(value, 'query'): 192 return '%s' 191 193 if hasattr(value, 'expression'): 192 194 if transform_value(value, f.srid): 193 195 placeholder = '%s(%%s, %s)' % (self.transform, f.srid) -
django/contrib/gis/db/backends/mysql/operations.py
41 41 MySQL does not support spatial transformations, there is no need to 42 42 modify the placeholder based on the contents of the given value. 43 43 """ 44 if hasattr(value, 'query'): 45 return '%s' 44 46 if hasattr(value, 'expression'): 45 47 placeholder = '%s.%s' % tuple(map(self.quote_name, value.cols[value.expression])) 46 48 else: -
django/contrib/gis/db/backends/oracle/operations.py
205 205 """ 206 206 if value is None: 207 207 return 'NULL' 208 208 if hasattr(value, 'query'): 209 return '%s' 209 210 def transform_value(val, srid): 210 211 return val.srid != srid 211 212 -
django/contrib/gis/db/backends/postgis/operations.py
387 387 SRID of the field. Specifically, this routine will substitute in the 388 388 ST_Transform() function call. 389 389 """ 390 if value is None or value.srid == f.srid:390 if value is None or hasattr(value, 'query') or value.srid == f.srid: 391 391 placeholder = '%s' 392 392 else: 393 393 # Adding Transform() to the SQL placeholder. -
backends/base.py
131 131 def spatial_ref_sys(self): 132 132 raise NotImplementedError 133 133 134 def wrap_spatial_subselect(self, subselect_sql): 135 return '(%s)' % subselect_sql 136 134 137 class SpatialRefSysMixin(object): 135 138 """ 136 139 The SpatialRefSysMixin is a class used by the database-dependent -
backends/postgis/func.sql
1 /* function that will immediately execute subselect that returns spatial geometry */ 2 create or replace function execute_spatial_subselect(a_query text) 3 returns geometry as 4 $$ 5 DECLARE poly geometry; 6 BEGIN 7 EXECUTE a_query INTO poly; 8 RETURN poly; 9 END 10 $$ LANGUAGE 'plpgsql' IMMUTABLE; -
backends/postgis/operations.py
589 589 def spatial_ref_sys(self): 590 590 from django.contrib.gis.db.backends.postgis.models import SpatialRefSys 591 591 return SpatialRefSys 592 593 def wrap_spatial_subselect(self, subselect_sql): 594 # use dollar quoting to prevent problems with quoted params -
tests/modeltests/spatial_subquery/models.py
+ return '(execute_spatial_subselect($$%s$$))' % subselect_sql
1 """ 2 Tests for spatial subqueries 3 """ 4 5 from django.contrib.gis.db import models 6 7 class Address(models.Model): 8 city = models.CharField(max_length=50) 9 location = models.PointField(srid=4326) 10 objects = models.GeoManager() 11 def __unicode__(self): 12 return u"%s" % (self.city) 13 14 class District(models.Model): 15 name = models.CharField(max_length=50) 16 area = models.MultiPolygonField(srid=4326) 17 def __unicode__(self): 18 return u"%s" % (self.name) 19 20 __test__ = {'API_TESTS':""" 21 22 >>> qset = Address.objects.filter(location__within = District.objects.filter(name='Boston area').values('area')) 23 >>> str(qset.query) 24 'SELECT "spatial_subquery_address"."id", "spatial_subquery_address"."city", "spatial_subquery_address"."location" FROM "spatial_subquery_address" WHERE ST_Within("spatial_subquery_address"."location", (execute_spatial_subselect($$SELECT U0."area" FROM "spatial_subquery_district" U0 WHERE U0."name" = Boston area $$)))' 25 26 >>> list(qset) 27 [] 28 29 >>> qset.query.tables # check presence of both tables for johnny cache patch 30 ['spatial_subquery_address'] 31 32 >>> qset.query.where.result_tables # also QueryWrapper tables should be present 33 ['spatial_subquery_address', 'spatial_subquery_district'] 34 35 """}