Opened 3 years ago
Last modified 2 years ago
#33050 closed Bug
calling count on union of queries having select_related results in error. — at Version 4
Reported by: | Sunkyue | Owned by: | nobody |
---|---|---|---|
Component: | Database layer (models, ORM) | Version: | 3.2 |
Severity: | Normal | Keywords: | orm, count, union, select_related mysql |
Cc: | Triage Stage: | Accepted | |
Has patch: | no | Needs documentation: | no |
Needs tests: | no | Patch needs improvement: | no |
Easy pickings: | no | UI/UX: | no |
Description (last modified by )
test case:
class ModelA(models.Model): value = models.IntegerField() class ModelB(models.Model): model_a = models.ForeignKey("ModelA", on_delete=models.CASCADE)
->
ModelB.objects.select_related('model_a').union(ModelB.objects.select_related('model_a')).count()
results in error.
File "c:\Users\user\Documents\workspace\realclass2-api\.venv\lib\site-packages\django\db\models\query.py", line 412, in count return self.query.get_count(using=self.db) File "c:\Users\user\Documents\workspace\realclass2-api\.venv\lib\site-packages\django\db\models\sql\query.py", line 521, in get_count number = obj.get_aggregation(using, ['__count'])['__count'] File "c:\Users\user\Documents\workspace\realclass2-api\.venv\lib\site-packages\django\db\models\sql\query.py", line 506, in get_aggregation result = compiler.execute_sql(SINGLE) File "c:\Users\user\Documents\workspace\realclass2-api\.venv\lib\site-packages\django\db\models\sql\compiler.py", line 1175, in execute_sql cursor.execute(sql, params) File "c:\Users\user\Documents\workspace\realclass2-api\.venv\lib\site-packages\django\db\backends\utils.py", line 98, in execute return super().execute(sql, params) File "c:\Users\user\Documents\workspace\realclass2-api\.venv\lib\site-packages\django\db\backends\utils.py", line 66, in execute return self._execute_with_wrappers(sql, params, many=False, executor=self._execute) File "c:\Users\user\Documents\workspace\realclass2-api\.venv\lib\site-packages\django\db\backends\utils.py", line 75, in _execute_with_wrappers return executor(sql, params, many, context) File "c:\Users\user\Documents\workspace\realclass2-api\.venv\lib\site-packages\django\db\backends\utils.py", line 84, in _execute return self.cursor.execute(sql, params) File "c:\Users\user\Documents\workspace\realclass2-api\.venv\lib\site-packages\django\db\utils.py", line 90, in __exit__ raise dj_exc_value.with_traceback(traceback) from exc_value File "c:\Users\user\Documents\workspace\realclass2-api\.venv\lib\site-packages\django\db\backends\utils.py", line 84, in _execute return self.cursor.execute(sql, params) File "c:\Users\user\Documents\workspace\realclass2-api\.venv\lib\site-packages\django\db\backends\mysql\base.py", line 73, in execute return self.cursor.execute(query, args) File "c:\Users\user\Documents\workspace\realclass2-api\.venv\lib\site-packages\MySQLdb\cursors.py", line 206, in execute res = self._query(query) File "c:\Users\user\Documents\workspace\realclass2-api\.venv\lib\site-packages\MySQLdb\cursors.py", line 319, in _query db.query(q) File "c:\Users\user\Documents\workspace\realclass2-api\.venv\lib\site-packages\MySQLdb\connections.py", line 259, in query _mysql.connection.query(self, query) django.db.utils.OperationalError: (1060, "Duplicate column name 'id'")
suggested fix:
on django.db.models.sql.query.py -> Query.get_aggregation, from
inner_query.select_for_update = False inner_query.select_related = False inner_query.set_annotation_mask(self.annotation_select)
to
inner_query.select_for_update = False inner_query.select_related = False for combined_query in inner_query.combined_queries: combined_query.select_related = False inner_query.set_annotation_mask(self.annotation_select)
can solve the problem I think.
my current monkey-patching code is,
from django.db.models.sql.query import Query old_get_aggregation = Query.get_aggregation def get_aggregation(self, using, added_aggregate_names): original_select_related_values = {} for combined_query in self.combined_queries: original_select_related_values[combined_query] = combined_query.select_related combined_query.select_related = False result = old_get_aggregation(self, using, added_aggregate_names) for combined_query in self.combined_queries: combined_query.select_related = original_select_related_values[combined_query] return result Query.get_aggregation = get_aggregation
reproduced on on 3.2.5/3.2.6
Change History (4)
comment:1 by , 3 years ago
Easy pickings: | set |
---|
comment:2 by , 3 years ago
Description: | modified (diff) |
---|
comment:3 by , 3 years ago
Description: | modified (diff) |
---|
comment:4 by , 3 years ago
Description: | modified (diff) |
---|
Note:
See TracTickets
for help on using tickets.