Changeset 7836 for django/branches/gis/django/contrib/gis/db
- Timestamp:
- 07/04/08 15:16:22 (6 months ago)
- Files:
-
- django/branches/gis (modified) (1 prop)
- django/branches/gis/django/contrib/gis/db/backend/mysql/query.py (modified) (2 diffs)
- django/branches/gis/django/contrib/gis/db/backend/oracle/query.py (modified) (3 diffs)
- django/branches/gis/django/contrib/gis/db/backend/postgis/query.py (modified) (4 diffs)
- django/branches/gis/django/contrib/gis/db/models/fields/__init__.py (modified) (1 diff)
- django/branches/gis/django/contrib/gis/db/models/sql/query.py (modified) (4 diffs)
- django/branches/gis/django/contrib/gis/db/models/sql/where.py (modified) (1 diff)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
django/branches/gis
- Property svnmerge-integrated changed from /django/trunk:1-7767 to /django/trunk:1-7835
django/branches/gis/django/contrib/gis/db/backend/mysql/query.py
r7699 r7836 39 39 MYSQL_GIS_TERMS = MYSQL_GIS_FUNCTIONS.keys() 40 40 MYSQL_GIS_TERMS += MISC_TERMS 41 MYSQL_GIS_TERMS = tuple(MYSQL_GIS_TERMS) # Making immutable41 MYSQL_GIS_TERMS = dict((term, None) for term in MYSQL_GIS_TERMS) # Making dictionary 42 42 43 def get_geo_where_clause( lookup_type, table_prefix, field, value):43 def get_geo_where_clause(table_alias, name, lookup_type, geo_annot): 44 44 "Returns the SQL WHERE clause for use in MySQL spatial SQL construction." 45 45 # Getting the quoted field as `geo_col`. 46 geo_col = '%s.%s' % (qn(table_ prefix), qn(field.column))46 geo_col = '%s.%s' % (qn(table_alias), qn(name)) 47 47 48 48 # See if a MySQL Geometry function matches the lookup type next … … 55 55 # geometries in its spatial indices. 56 56 if lookup_type == 'isnull': 57 return "%s IS %sNULL" % (geo_col, (not value and 'NOT ' or ''))57 return "%s IS %sNULL" % (geo_col, (not geo_annot.value and 'NOT ' or '')) 58 58 59 59 raise TypeError("Got invalid lookup_type: %s" % repr(lookup_type)) django/branches/gis/django/contrib/gis/db/backend/oracle/query.py
r7641 r7836 111 111 112 112 #### The `get_geo_where_clause` function for Oracle #### 113 def get_geo_where_clause( lookup_type, table_prefix, field, value):113 def get_geo_where_clause(table_alias, name, lookup_type, geo_annot): 114 114 "Returns the SQL WHERE clause for use in Oracle spatial SQL construction." 115 115 # Getting the quoted table name as `geo_col`. 116 geo_col = '%s.%s' % (qn(table_ prefix), qn(field.column))116 geo_col = '%s.%s' % (qn(table_alias), qn(name)) 117 117 118 118 # See if a Oracle Geometry function matches the lookup type next … … 127 127 128 128 # Ensuring that a tuple _value_ was passed in from the user 129 if not isinstance( value, tuple):129 if not isinstance(geo_annot.value, tuple): 130 130 raise TypeError('Tuple required for `%s` lookup type.' % lookup_type) 131 if len( value) != 2:131 if len(geo_annot.value) != 2: 132 132 raise ValueError('2-element tuple required for %s lookup type.' % lookup_type) 133 133 134 134 # Ensuring the argument type matches what we expect. 135 if not isinstance( value[1], arg_type):136 raise TypeError('Argument type should be %s, got %s instead.' % (arg_type, type( value[1])))135 if not isinstance(geo_annot.value[1], arg_type): 136 raise TypeError('Argument type should be %s, got %s instead.' % (arg_type, type(geo_annot.value[1]))) 137 137 138 138 if lookup_type == 'relate': 139 139 # The SDORelate class handles construction for these queries, 140 140 # and verifies the mask argument. 141 return sdo_op( value[1]).as_sql(geo_col)141 return sdo_op(geo_annot.value[1]).as_sql(geo_col) 142 142 else: 143 143 # Otherwise, just call the `as_sql` method on the SDOOperation instance. … … 150 150 elif lookup_type == 'isnull': 151 151 # Handling 'isnull' lookup type 152 return "%s IS %sNULL" % (geo_col, (not value and 'NOT ' or ''))152 return "%s IS %sNULL" % (geo_col, (not geo_annot.value and 'NOT ' or '')) 153 153 154 154 raise TypeError("Got invalid lookup_type: %s" % repr(lookup_type)) django/branches/gis/django/contrib/gis/db/backend/postgis/query.py
r7641 r7836 219 219 POSTGIS_TERMS += POSTGIS_GEOMETRY_FUNCTIONS.keys() # Adding on the Geometry Functions 220 220 POSTGIS_TERMS += MISC_TERMS # Adding any other miscellaneous terms (e.g., 'isnull') 221 POSTGIS_TERMS = tuple(POSTGIS_TERMS) # Making immutable221 POSTGIS_TERMS = dict((term, None) for term in POSTGIS_TERMS) # Making a dictionary for fast lookups 222 222 223 223 # For checking tuple parameters -- not very pretty but gets job done. … … 229 229 230 230 #### The `get_geo_where_clause` function for PostGIS. #### 231 def get_geo_where_clause( lookup_type, table_prefix, field, value):231 def get_geo_where_clause(table_alias, name, lookup_type, geo_annot): 232 232 "Returns the SQL WHERE clause for use in PostGIS SQL construction." 233 233 # Getting the quoted field as `geo_col`. 234 geo_col = '%s.%s' % (qn(table_ prefix), qn(field.column))234 geo_col = '%s.%s' % (qn(table_alias), qn(name)) 235 235 if lookup_type in POSTGIS_OPERATORS: 236 236 # See if a PostGIS operator matches the lookup type. … … 249 249 250 250 # Ensuring that a tuple _value_ was passed in from the user 251 if not isinstance( value, (tuple, list)):251 if not isinstance(geo_annot.value, (tuple, list)): 252 252 raise TypeError('Tuple required for `%s` lookup type.' % lookup_type) 253 253 254 # Number of valid tuple parameters depends on the lookup type. 254 nparams = len( value)255 nparams = len(geo_annot.value) 255 256 if not num_params(lookup_type, nparams): 256 257 raise ValueError('Incorrect number of parameters given for `%s` lookup type.' % lookup_type) 257 258 258 259 # Ensuring the argument type matches what we expect. 259 if not isinstance( value[1], arg_type):260 raise TypeError('Argument type should be %s, got %s instead.' % (arg_type, type( value[1])))260 if not isinstance(geo_annot.value[1], arg_type): 261 raise TypeError('Argument type should be %s, got %s instead.' % (arg_type, type(geo_annot.value[1]))) 261 262 262 263 # For lookup type `relate`, the op instance is not yet created (has 263 264 # to be instantiated here to check the pattern parameter). 264 265 if lookup_type == 'relate': 265 op = op( value[1])266 op = op(geo_annot.value[1]) 266 267 elif lookup_type in DISTANCE_FUNCTIONS and lookup_type != 'dwithin': 267 if field.geodetic:268 if geo_annot.geodetic: 268 269 # Geodetic distances are only availble from Points to PointFields. 269 if field._geom!= 'POINT':270 if geo_annot.geom_type != 'POINT': 270 271 raise TypeError('PostGIS spherical operations are only valid on PointFields.') 271 if value[0].geom_typeid != 0:272 if geo_annot.value[0].geom_typeid != 0: 272 273 raise TypeError('PostGIS geometry distance parameter is required to be of type Point.') 273 274 # Setting up the geodetic operation appropriately. 274 if nparams == 3 and value[2] == 'spheroid': op = op[2]275 if nparams == 3 and geo_annot.value[2] == 'spheroid': op = op[2] 275 276 else: op = op[1] 276 277 else: … … 282 283 elif lookup_type == 'isnull': 283 284 # Handling 'isnull' lookup type 284 return "%s IS %sNULL" % (geo_col, (not value and 'NOT ' or ''))285 return "%s IS %sNULL" % (geo_col, (not geo_annot.value and 'NOT ' or '')) 285 286 286 287 raise TypeError("Got invalid lookup_type: %s" % repr(lookup_type)) django/branches/gis/django/contrib/gis/db/models/fields/__init__.py
r7641 r7836 112 112 raise ValueError('Could not create geometry from lookup value: %s' % str(value)) 113 113 else: 114 raise TypeError('Cannot use parameter of `%s` type as lookup parameter.' % type(value))114 raise TypeError('Cannot use parameter of `%s` type as a geometry lookup parameter.' % type(value)) 115 115 116 116 # Assigning the SRID value. django/branches/gis/django/contrib/gis/db/models/sql/query.py
r7699 r7836 104 104 return result 105 105 106 def get_default_columns(self, with_aliases=False, col_aliases=None): 106 def get_default_columns(self, with_aliases=False, col_aliases=None, 107 start_alias=None, opts=None, as_pairs=False): 107 108 """ 108 109 Computes the default columns for selecting every field in the base … … 116 117 """ 117 118 result = [] 118 table_alias = self.tables[0] 119 if opts is None: 120 opts = self.model._meta 121 if start_alias: 122 table_alias = start_alias 123 else: 124 table_alias = self.tables[0] 119 125 root_pk = self.model._meta.pk.column 120 126 seen = {None: table_alias} 121 qn = self.quote_name_unless_alias122 qn2 = self.connection.ops.quote_name123 127 aliases = set() 124 128 for field, model in self.model._meta.get_fields_with_model(): … … 129 133 root_pk, model._meta.pk.column)) 130 134 seen[model] = alias 131 135 if as_pairs: 136 result.append((alias, field.column)) 137 continue 132 138 # This part of the function is customized for GeoQuery. We 133 139 # see if there was any custom selection specified in the 134 140 # dictionary, and set up the selection format appropriately. 135 141 field_sel = self.get_field_select(field, alias) 136 137 142 if with_aliases and field.column in col_aliases: 138 143 c_alias = 'Col%d' % len(col_aliases) … … 146 151 if with_aliases: 147 152 col_aliases.add(field.column) 153 if as_pairs: 154 return result, None 148 155 return result, aliases 149 156 django/branches/gis/django/contrib/gis/db/models/sql/where.py
r7641 r7836 1 import datetime 2 from django.db.models.fields import Field 1 3 from django.db.models.sql.where import WhereNode 2 4 from django.contrib.gis.db.backend import get_geo_where_clause, SpatialBackend 3 5 6 class GeoAnnotation(object): 7 """ 8 The annotation used for GeometryFields; basically a placeholder 9 for metadata needed by the `get_geo_where_clause` of the spatial 10 backend. 11 """ 12 def __init__(self, field, value, where): 13 self.geodetic = field.geodetic 14 self.geom_type = field._geom 15 self.value = value 16 self.where = tuple(where) 17 4 18 class GeoWhereNode(WhereNode): 5 19 """ 6 The GeoWhereNode calls the `get_geo_where_clause` from the appropriate7 spatial backend in order to construct correct spatial SQL.20 Used to represent the SQL where-clause for spatial databases -- 21 these are tied to the GeoQuery class that created it. 8 22 """ 23 def add(self, data, connector): 24 """ 25 This is overridden from the regular WhereNode to handle the 26 peculiarties of GeometryFields, because they need a special 27 annotation object that contains the spatial metadata from the 28 field so that the correct spatial SQL is generated. 29 """ 30 if not isinstance(data, (list, tuple)): 31 super(WhereNode, self).add(data, connector) 32 return 33 34 alias, col, field, lookup_type, value = data 35 # Do we have a geographic field? 36 geo_field = hasattr(field, '_geom') 37 if field: 38 if geo_field: 39 # `GeometryField.get_db_prep_lookup` returns a where clause 40 # substitution array in addition to the parameters. 41 where, params = field.get_db_prep_lookup(lookup_type, value) 42 else: 43 params = field.get_db_prep_lookup(lookup_type, value) 44 db_type = field.db_type() 45 else: 46 # This is possible when we add a comparison to NULL sometimes (we 47 # don't really need to waste time looking up the associated field 48 # object). 49 params = Field().get_db_prep_lookup(lookup_type, value) 50 db_type = None 51 52 if geo_field: 53 # The annotation will be a `GeoAnnotation` object that 54 # will contain the necessary geometry field metadata for 55 # the `get_geo_where_clause` to construct the appropriate 56 # spatial SQL when `make_atom` is called. 57 annotation = GeoAnnotation(field, value, where) 58 elif isinstance(value, datetime.datetime): 59 annotation = datetime.datetime 60 else: 61 annotation = bool(value) 62 63 super(WhereNode, self).add((alias, col, db_type, lookup_type, 64 annotation, params), connector) 65 9 66 def make_atom(self, child, qn): 10 table_alias, name, field, lookup_type, value = child 11 if hasattr(field, '_geom'): 67 table_alias, name, db_type, lookup_type, value_annot, params = child 68 69 if isinstance(value_annot, GeoAnnotation): 12 70 if lookup_type in SpatialBackend.gis_terms: 13 71 # Getting the geographic where clause; substitution parameters 14 72 # will be populated in the GeoFieldSQL object returned by the 15 73 # GeometryField. 16 gwc = get_geo_where_clause(lookup_type, table_alias, field, value) 17 where, params = field.get_db_prep_lookup(lookup_type, value) 18 return gwc % tuple(where), params 74 gwc = get_geo_where_clause(table_alias, name, lookup_type, value_annot) 75 return gwc % value_annot.where, params 19 76 else: 20 77 raise TypeError('Invalid lookup type: %r' % lookup_type)
