Ticket #7126: gis_select_related.diff

File gis_select_related.diff, 4.5 KB (added by jbronn, 16 years ago)

Fix for selection of geometry columns when using select_related on MySQL/Oracle.

  • django/contrib/gis/db/models/query.py

     
     1from itertools import izip
    12from django.core.exceptions import ImproperlyConfigured
    23from django.db import connection
    34from django.db.models.query import sql, QuerySet, Q
     
    5354        obj.ewkt = self.ewkt
    5455        return obj
    5556
     57    def get_columns(self, with_aliases=False):
     58        """
     59        Return the list of columns to use in the select statement. If no
     60        columns have been specified, returns all columns relating to fields in
     61        the model.
     62
     63        If 'with_aliases' is true, any column names that are duplicated
     64        (without the table names) are given unique aliases. This is needed in
     65        some cases to avoid ambiguitity with nested queries.
     66
     67        This routine is overridden from Query to handle customized selection of
     68        geometry columns.
     69        """
     70        qn = self.quote_name_unless_alias
     71        result = ['(%s) AS %s' % (col, alias) for alias, col in self.extra_select.iteritems()]
     72        aliases = set(self.extra_select.keys())
     73        if with_aliases:
     74            col_aliases = aliases.copy()
     75        else:
     76            col_aliases = set()
     77        if self.select:
     78            for col, field in izip(self.select, self.select_fields):
     79                if isinstance(col, (list, tuple)):
     80                    # This part customized for GeoQuery.
     81                    sel_fmt = self.get_select_format(field)
     82                    r = '%s.%s' % (qn(col[0]), qn(col[1]))
     83                    r = sel_fmt % r
     84                    if with_aliases and col[1] in col_aliases:
     85                        c_alias = 'Col%d' % len(col_aliases)
     86                        result.append('%s AS %s' % (r, c_alias))
     87                        aliases.add(c_alias)
     88                        col_aliases.add(c_alias)
     89                    else:
     90                        result.append(r)
     91                        aliases.add(r)
     92                        col_aliases.add(col[1])
     93                else:
     94                    result.append(col.as_sql(quote_func=qn))
     95                    if hasattr(col, 'alias'):
     96                        aliases.add(col.alias)
     97                        col_aliases.add(col.alias)
     98        elif self.default_cols:
     99            cols, new_aliases = self.get_default_columns(with_aliases,
     100                    col_aliases)
     101            result.extend(cols)
     102            aliases.update(new_aliases)
     103
     104        for i in xrange(len(self.related_select_cols)):
     105            table, col = self.related_select_cols[i]
     106            field = self.related_select_fields[i]
     107
     108            # This part customized for GeoQuery.
     109            sel_fmt = self.get_select_format(field)
     110            r = '%s.%s' % (qn(table), qn(col))
     111            r = sel_fmt % r
     112
     113            if with_aliases and col in col_aliases:
     114                c_alias = 'Col%d' % len(col_aliases)
     115                result.append('%s AS %s' % (r, c_alias))
     116                aliases.add(c_alias)
     117                col_aliases.add(c_alias)
     118            else:
     119                result.append(r)
     120                aliases.add(r)
     121                col_aliases.add(col)
     122
     123        self._select_aliases = aliases
     124        return result
     125
    56126    def get_default_columns(self, with_aliases=False, col_aliases=None):
    57127        """
    58128        Computes the default columns for selecting every field in the base
     
    79149                        root_pk, model._meta.pk.column))
    80150                seen[model] = alias
    81151
    82             # This part of the function is customized for GeoQuerySet. We
     152            # This part of the function is customized for GeoQuery. We
    83153            # see if there was any custom selection specified in the
    84154            # dictionary, and set up the selection format appropriately.
    85155            sel_fmt = self.get_select_format(field)
     
    229299        extent_sql = '%s(%s)' % (EXTENT, geo_col)
    230300
    231301        self.query.select = [GeomSQL(extent_sql)]
     302        self.query.select_fields = [None]
    232303        try:
    233304            esql, params = self.query.as_sql()
    234305        except sql.datastructures.EmptyResultSet:
     
    365436
    366437        # Only want the union SQL to be selected.
    367438        self.query.select = [GeomSQL(union_sql)]
     439        self.query.select_fields = [GeometryField]
    368440        try:
    369441            usql, params = self.query.as_sql()
    370442        except sql.datastructures.EmptyResultSet:
Back to Top