Ticket #7961: django_extra.diff

File django_extra.diff, 5.7 KB (added by Matthijs, 16 years ago)
  • db/models/query.py

     
    625625        # names of the model fields to select.
    626626
    627627    def iterator(self):
    628         if (not self.extra_names and
    629             len(self.field_names) != len(self.model._meta.fields)):
    630             self.query.trim_extra_select(self.extra_names)
     628        self.query.trim_extra_select(self.extra_names)
    631629        names = self.query.extra_select.keys() + self.field_names
    632630        for row in self.query.results_iter():
    633631            yield dict(zip(names, row))
  • db/models/sql/query.py

     
    7878
    7979        # These are for extensions. The contents are more or less appended
    8080        # verbatim to the appropriate clause.
    81         self.extra_select = {}  # Maps col_alias -> col_sql.
    82         self.extra_select_params = ()
     81        self.extra_select = SortedDict()  # Maps col_alias -> col_sql.
     82        self.extra_select_params = SortedDict()
    8383        self.extra_tables = ()
    8484        self.extra_where = ()
    8585        self.extra_params = ()
     
    182182        obj.related_select_cols = []
    183183        obj.max_depth = self.max_depth
    184184        obj.extra_select = self.extra_select.copy()
    185         obj.extra_select_params = self.extra_select_params
     185        obj.extra_select_params = self.extra_select_params.copy()
    186186        obj.extra_tables = self.extra_tables
    187187        obj.extra_where = self.extra_where
    188188        obj.extra_params = self.extra_params
     
    255255        # get_from_clause() for details.
    256256        from_, f_params = self.get_from_clause()
    257257
    258         where, w_params = self.where.as_sql(qn=self.quote_name_unless_alias)
    259         params = list(self.extra_select_params)
    260 
     258        where, w_params = self.where.as_sql(qn=self.quote_name_unless_alias)
     259        params = []
     260        for extra_select_param in self.extra_select_params.values():
     261            params.extend(extra_select_param)
     262
    261263        result = ['SELECT']
    262264        if self.distinct:
    263265            result.append('DISTINCT')
     
    15031505            self.distinct = False
    15041506        self.select = [select]
    15051507        self.select_fields = [None]
    1506         self.extra_select = {}
    1507         self.extra_select_params = ()
     1508        self.extra_select = SortedDict()
     1509        self.extra_select_params = SortedDict()
    15081510
    15091511    def add_select_related(self, fields):
    15101512        """
     
    15261528        Adds data to the various extra_* attributes for user-created additions
    15271529        to the query.
    15281530        """
    1529         if select:
    1530             # The extra select might be ordered (because it will be accepting
    1531             # parameters).
    1532             if (isinstance(select, SortedDict) and
    1533                     not isinstance(self.extra_select, SortedDict)):
    1534                 self.extra_select = SortedDict(self.extra_select)
    1535             self.extra_select.update(select)
    1536         if select_params:
    1537             self.extra_select_params += tuple(select_params)
     1531        if select:
     1532            select = SortedDict(select)
     1533            self.extra_select.append(select)
     1534            if select_params:
     1535                start = 0
     1536                for key in select.keys():
     1537                    number_of_params = select[key].count(" %s") # a %s in a sql statement is always preceded by a space, but could be at the very end of the string and then not be followed by a space
     1538                    self.extra_select_params.append({key:select_params[start:start+number_of_params]})
     1539                    start += number_of_params
     1540                if start != len(select_params):
     1541                    raise ValueError("The number of parameters expected by select= (%d) is not equal to the number of parameters given in select_params= (%d)" % (start, len(select_params)))
    15381542        if where:
    15391543            self.extra_where += tuple(where)
    15401544        if params:
     
    15471551    def trim_extra_select(self, names):
    15481552        """
    15491553        Removes any aliases in the extra_select dictionary that aren't in
    1550         'names'.
     1554        'names'.
     1555        Additionally remove the parameters that belonged to the removed aliases,
     1556        this ensures that the parameters stay aligned with the '%s'-replacements in the query
    15511557
    15521558        This is needed if we are selecting certain values that don't incldue
    15531559        all of the extra_select names.
    1554         """
    1555         for key in set(self.extra_select).difference(set(names)):
    1556             del self.extra_select[key]
     1560        """
     1561        for key in reversed(self.extra_select.keys()):
     1562            if key not in names:               
     1563                del self.extra_select[key]
     1564                if self.extra_select_params.has_key(key): # sometimes a select statement has no params
     1565                    del self.extra_select_params[key]
    15571566
    15581567    def set_start(self, start):
    15591568        """
     
    16741683    sender._meta._join_cache = {}
    16751684
    16761685dispatcher.connect(setup_join_cache, signal=signals.class_prepared)
    1677 
     1686
  • utils/datastructures.py

     
    121121    def update(self, dict_):
    122122        for k, v in dict_.items():
    123123            self.__setitem__(k, v)
     124   
     125    def append(self, data):
     126        for key, value in data.iteritems():
     127            super(SortedDict, self).__setitem__(key, value)
     128            self.keyOrder.append(key)
    124129
    125130    def setdefault(self, key, default):
    126131        if key not in self.keyOrder:
     
    406411            return self.func(value)
    407412        return value
    408413
     414
Back to Top