From 04da22633fcda983cb9ee69e63b2ebe99301b717 Mon Sep 17 00:00:00 2001 From: Malcolm Tredinnick Date: Thu, 20 Mar 2008 19:16:04 +0000 Subject: queryset-refactor: Fixed up extra(select=...) calls with parameters so that the parameters are substituted in correctly in all cases. This introduces an extra argument to extra() for this purpose; no alternative there. Also fixed values() to work if you don't specify *all* the extra select aliases in the values() call. Refs #3141. git-svn-id: http://code.djangoproject.com/svn/django/branches/queryset-refactor@7340 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/db/models/sql/query.py | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) (limited to 'django/db/models/sql/query.py') diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index b67bfae699..6a68448bf1 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -73,6 +73,7 @@ class Query(object): # These are for extensions. The contents are more or less appended # verbatim to the appropriate clause. self.extra_select = {} # Maps col_alias -> col_sql. + self.extra_select_params = () self.extra_tables = () self.extra_where = () self.extra_params = () @@ -150,6 +151,7 @@ class Query(object): obj.select_related = self.select_related obj.max_depth = self.max_depth obj.extra_select = self.extra_select.copy() + obj.extra_select_params = self.extra_select_params obj.extra_tables = self.extra_tables obj.extra_where = self.extra_where obj.extra_params = self.extra_params @@ -214,6 +216,7 @@ class Query(object): # get_from_clause() for details. from_, f_params = self.get_from_clause() where, w_params = self.where.as_sql(qn=self.quote_name_unless_alias) + params = list(self.extra_select_params) result = ['SELECT'] if self.distinct: @@ -222,7 +225,7 @@ class Query(object): result.append('FROM') result.extend(from_) - params = list(f_params) + params.extend(f_params) if where: result.append('WHERE %s' % where) @@ -351,8 +354,8 @@ class Query(object): the model. """ qn = self.quote_name_unless_alias - result = [] - aliases = [] + result = ['(%s) AS %s' % (col, alias) for alias, col in self.extra_select.items()] + aliases = self.extra_select.keys() if self.select: for col in self.select: if isinstance(col, (list, tuple)): @@ -364,12 +367,9 @@ class Query(object): if hasattr(col, 'alias'): aliases.append(col.alias) elif self.default_cols: - result = self.get_default_columns(True) - aliases = result[:] - - result.extend(['(%s) AS %s' % (col, alias) - for alias, col in self.extra_select.items()]) - aliases.extend(self.extra_select.keys()) + cols = self.get_default_columns(True) + result.extend(cols) + aliases.extend(cols) self._select_aliases = set(aliases) return result @@ -403,9 +403,9 @@ class Query(object): def get_from_clause(self): """ Returns a list of strings that are joined together to go after the - "FROM" part of the query, as well as any extra parameters that need to - be included. Sub-classes, can override this to create a from-clause via - a "select", for example (e.g. CountQuery). + "FROM" part of the query, as well as a list any extra parameters that + need to be included. Sub-classes, can override this to create a + from-clause via a "select", for example (e.g. CountQuery). This should only be called after any SQL construction methods that might change the tables we need. This means the select columns and @@ -1253,6 +1253,7 @@ class Query(object): self.distinct = False self.select = [select] self.extra_select = {} + self.extra_select_params = () def add_select_related(self, fields): """ @@ -1267,7 +1268,7 @@ class Query(object): d = d.setdefault(part, {}) self.select_related = field_dict - def add_extra(self, select, where, params, tables, order_by): + def add_extra(self, select, select_params, where, params, tables, order_by): """ Adds data to the various extra_* attributes for user-created additions to the query. @@ -1279,6 +1280,8 @@ class Query(object): not isinstance(self.extra_select, SortedDict)): self.extra_select = SortedDict(self.extra_select) self.extra_select.update(select) + if select_params: + self.extra_select_params += tuple(select_params) if where: self.extra_where += tuple(where) if params: @@ -1288,6 +1291,17 @@ class Query(object): if order_by: self.extra_order_by = order_by + def trim_extra_select(self, names): + """ + Removes any aliases in the extra_select dictionary that aren't in + 'names'. + + This is needed if we are selecting certain values that don't incldue + all of the extra_select names. + """ + for key in set(self.extra_select).difference(set(names)): + del self.extra_select[key] + def set_start(self, start): """ Sets the table from which to start joining. The start position is -- cgit v1.3