Django

Code

Show
Ignore:
Timestamp:
07/04/08 15:16:22 (6 months ago)
Author:
jbronn
Message:

gis: Merged revisions 7772-7808,7811-7814,7816-7823,7826-7829,7831-7833,7835 via svnmerge from trunk. Modified GeoWhereNode accordingly for changes in r7835.

Files:

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  
    3939MYSQL_GIS_TERMS  = MYSQL_GIS_FUNCTIONS.keys() 
    4040MYSQL_GIS_TERMS += MISC_TERMS 
    41 MYSQL_GIS_TERMS = tuple(MYSQL_GIS_TERMS) # Making immutable 
     41MYSQL_GIS_TERMS = dict((term, None) for term in MYSQL_GIS_TERMS) # Making dictionary  
    4242 
    43 def get_geo_where_clause(lookup_type, table_prefix, field, value): 
     43def get_geo_where_clause(table_alias, name, lookup_type, geo_annot): 
    4444    "Returns the SQL WHERE clause for use in MySQL spatial SQL construction." 
    4545    # 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)) 
    4747 
    4848    # See if a MySQL Geometry function matches the lookup type next 
     
    5555    # geometries in its spatial indices. 
    5656    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 '')) 
    5858 
    5959    raise TypeError("Got invalid lookup_type: %s" % repr(lookup_type)) 
  • django/branches/gis/django/contrib/gis/db/backend/oracle/query.py

    r7641 r7836  
    111111 
    112112#### The `get_geo_where_clause` function for Oracle #### 
    113 def get_geo_where_clause(lookup_type, table_prefix, field, value): 
     113def get_geo_where_clause(table_alias, name, lookup_type, geo_annot): 
    114114    "Returns the SQL WHERE clause for use in Oracle spatial SQL construction." 
    115115    # 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)) 
    117117 
    118118    # See if a Oracle Geometry function matches the lookup type next 
     
    127127 
    128128            # 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): 
    130130                raise TypeError('Tuple required for `%s` lookup type.' % lookup_type) 
    131             if len(value) != 2:  
     131            if len(geo_annot.value) != 2:  
    132132                raise ValueError('2-element tuple required for %s lookup type.' % lookup_type) 
    133133             
    134134            # 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]))) 
    137137 
    138138            if lookup_type == 'relate': 
    139139                # The SDORelate class handles construction for these queries,  
    140140                # 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) 
    142142            else: 
    143143                # Otherwise, just call the `as_sql` method on the SDOOperation instance. 
     
    150150    elif lookup_type == 'isnull': 
    151151        # 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 '')) 
    153153 
    154154    raise TypeError("Got invalid lookup_type: %s" % repr(lookup_type)) 
  • django/branches/gis/django/contrib/gis/db/backend/postgis/query.py

    r7641 r7836  
    219219POSTGIS_TERMS += POSTGIS_GEOMETRY_FUNCTIONS.keys() # Adding on the Geometry Functions 
    220220POSTGIS_TERMS += MISC_TERMS # Adding any other miscellaneous terms (e.g., 'isnull') 
    221 POSTGIS_TERMS = tuple(POSTGIS_TERMS) # Making immutable 
     221POSTGIS_TERMS = dict((term, None) for term in POSTGIS_TERMS) # Making a dictionary for fast lookups 
    222222 
    223223# For checking tuple parameters -- not very pretty but gets job done. 
     
    229229 
    230230#### The `get_geo_where_clause` function for PostGIS. #### 
    231 def get_geo_where_clause(lookup_type, table_prefix, field, value): 
     231def get_geo_where_clause(table_alias, name, lookup_type, geo_annot): 
    232232    "Returns the SQL WHERE clause for use in PostGIS SQL construction." 
    233233    # 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)) 
    235235    if lookup_type in POSTGIS_OPERATORS: 
    236236        # See if a PostGIS operator matches the lookup type. 
     
    249249 
    250250            # 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)):  
    252252                raise TypeError('Tuple required for `%s` lookup type.' % lookup_type) 
     253            
    253254            # Number of valid tuple parameters depends on the lookup type. 
    254             nparams = len(value) 
     255            nparams = len(geo_annot.value) 
    255256            if not num_params(lookup_type, nparams): 
    256257                raise ValueError('Incorrect number of parameters given for `%s` lookup type.' % lookup_type) 
    257258             
    258259            # 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]))) 
    261262 
    262263            # For lookup type `relate`, the op instance is not yet created (has 
    263264            # to be instantiated here to check the pattern parameter). 
    264265            if lookup_type == 'relate':  
    265                 op = op(value[1]) 
     266                op = op(geo_annot.value[1]) 
    266267            elif lookup_type in DISTANCE_FUNCTIONS and lookup_type != 'dwithin': 
    267                 if field.geodetic: 
     268                if geo_annot.geodetic: 
    268269                    # Geodetic distances are only availble from Points to PointFields. 
    269                     if field._geom != 'POINT': 
     270                    if geo_annot.geom_type != 'POINT': 
    270271                        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: 
    272273                        raise TypeError('PostGIS geometry distance parameter is required to be of type Point.') 
    273274                    # 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] 
    275276                    else: op = op[1] 
    276277                else: 
     
    282283    elif lookup_type == 'isnull': 
    283284        # 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 '')) 
    285286 
    286287    raise TypeError("Got invalid lookup_type: %s" % repr(lookup_type)) 
  • django/branches/gis/django/contrib/gis/db/models/fields/__init__.py

    r7641 r7836  
    112112                raise ValueError('Could not create geometry from lookup value: %s' % str(value)) 
    113113        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)) 
    115115 
    116116        # Assigning the SRID value. 
  • django/branches/gis/django/contrib/gis/db/models/sql/query.py

    r7699 r7836  
    104104        return result 
    105105 
    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): 
    107108        """ 
    108109        Computes the default columns for selecting every field in the base 
     
    116117        """ 
    117118        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] 
    119125        root_pk = self.model._meta.pk.column 
    120126        seen = {None: table_alias} 
    121         qn = self.quote_name_unless_alias 
    122         qn2 = self.connection.ops.quote_name 
    123127        aliases = set() 
    124128        for field, model in self.model._meta.get_fields_with_model(): 
     
    129133                        root_pk, model._meta.pk.column)) 
    130134                seen[model] = alias 
    131  
     135            if as_pairs: 
     136                result.append((alias, field.column)) 
     137                continue 
    132138            # This part of the function is customized for GeoQuery. We 
    133139            # see if there was any custom selection specified in the 
    134140            # dictionary, and set up the selection format appropriately. 
    135141            field_sel = self.get_field_select(field, alias) 
    136  
    137142            if with_aliases and field.column in col_aliases: 
    138143                c_alias = 'Col%d' % len(col_aliases) 
     
    146151                if with_aliases: 
    147152                    col_aliases.add(field.column) 
     153        if as_pairs: 
     154            return result, None 
    148155        return result, aliases 
    149156 
  • django/branches/gis/django/contrib/gis/db/models/sql/where.py

    r7641 r7836  
     1import datetime 
     2from django.db.models.fields import Field 
    13from django.db.models.sql.where import WhereNode 
    24from django.contrib.gis.db.backend import get_geo_where_clause, SpatialBackend 
    35 
     6class 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 
    418class GeoWhereNode(WhereNode): 
    519    """ 
    6     The GeoWhereNode calls the `get_geo_where_clause` from the appropriate 
    7     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
    822    """ 
     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 
    966    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): 
    1270            if lookup_type in SpatialBackend.gis_terms: 
    1371                # Getting the geographic where clause; substitution parameters 
    1472                # will be populated in the GeoFieldSQL object returned by the 
    1573                # 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 
    1976            else: 
    2077                raise TypeError('Invalid lookup type: %r' % lookup_type)