From 016f12a2c27fd6006d43cc32af734dfd0ea96f98 Mon Sep 17 00:00:00 2001 From: Malcolm Tredinnick Date: Sun, 1 Mar 2009 01:59:18 +0000 Subject: [PATCH] [1.0.X] Fixed insert/update handling when no database interaction is required. Fixed #10205 as part of this. Backport of r9926 from trunk. git-svn-id: http://code.djangoproject.com/svn/django/branches/releases/1.0.X@9927 bcc190cf-cafb-0310-a4f2-bffc1f526a37 --- django/db/models/sql/query.py | 8 +++++--- django/db/models/sql/subqueries.py | 4 ++-- tests/regressiontests/queries/models.py | 14 ++++++++++++++ 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/django/db/models/sql/query.py b/django/db/models/sql/query.py index 0a9092d77d..79bb2bafbf 100644 --- a/django/db/models/sql/query.py +++ b/django/db/models/sql/query.py @@ -1743,9 +1743,11 @@ class BaseQuery(object): iterator over the results if the result_type is MULTI. result_type is either MULTI (use fetchmany() to retrieve all rows), - SINGLE (only retrieve a single row), or None (no results expected, but - the cursor is returned, since it's used by subclasses such as - InsertQuery). + SINGLE (only retrieve a single row), or None. In this last case, the + cursor is returned if any query is executed, since it's used by + subclasses such as InsertQuery). It's possible, however, that no query + is needed, as the filters describe an empty set. In that case, None is + returned, to avoid any unnecessary database interaction. """ try: sql, params = self.as_sql() diff --git a/django/db/models/sql/subqueries.py b/django/db/models/sql/subqueries.py index 39ef439dc9..a84eeabf38 100644 --- a/django/db/models/sql/subqueries.py +++ b/django/db/models/sql/subqueries.py @@ -115,7 +115,7 @@ class UpdateQuery(Query): tables, but their rowcounts are not returned). """ cursor = super(UpdateQuery, self).execute_sql(result_type) - rows = cursor.rowcount + rows = cursor and cursor.rowcount or 0 del cursor for query in self.get_related_updates(): query.execute_sql(result_type) @@ -307,7 +307,7 @@ class InsertQuery(Query): def execute_sql(self, return_id=False): cursor = super(InsertQuery, self).execute_sql(None) - if return_id: + if return_id and cursor: return self.connection.ops.last_insert_id(cursor, self.model._meta.db_table, self.model._meta.pk.column) diff --git a/tests/regressiontests/queries/models.py b/tests/regressiontests/queries/models.py index 755b9ffc3f..e3aebd7915 100644 --- a/tests/regressiontests/queries/models.py +++ b/tests/regressiontests/queries/models.py @@ -1056,6 +1056,20 @@ cases). Bug #9985 -- qs.values_list(...).values(...) combinations should work. >>> Note.objects.values_list("note", flat=True).values("id").order_by("id") [{'id': 1}, {'id': 2}, {'id': 3}] +>>> Annotation.objects.filter(notes__in=Note.objects.filter(note="n1").values_list('note').values('id')) +[] + +Bug #10028 -- ordering by model related to nullable relations(!) should use +outer joins, so that all results are included. +>>> _ = Plaything.objects.create(name="p1") +>>> Plaything.objects.all() +[] + +Bug #10205 -- When bailing out early because of an empty "__in" filter, we need +to set things up correctly internally so that subqueries can continue properly. +>>> Tag.objects.filter(name__in=()).update(name="foo") +0 + """} # In Python 2.3 and the Python 2.6 beta releases, exceptions raised in __len__