Browse Source

Fixed #23061: Avoided setting a limit on a query for get with select_for_update on Oracle

Thanks Michael Miller for reporting the issue.
Shai Berger 10 years ago
parent
commit
746f2a4bed

+ 3 - 0
django/db/backends/__init__.py

@@ -666,6 +666,9 @@ class BaseDatabaseFeatures(object):
 
     uppercases_column_names = False
 
+    # Does the backend support "select for update" queries with limit (and offset)?
+    supports_select_for_update_with_limit = True
+
     def __init__(self, connection):
         self.connection = connection
 

+ 2 - 0
django/db/backends/oracle/base.py

@@ -121,6 +121,8 @@ class DatabaseFeatures(BaseDatabaseFeatures):
     closed_cursor_error_class = InterfaceError
     bare_select_suffix = " FROM DUAL"
     uppercases_column_names = True
+    # select for update with limit can be achieved on Oracle, but not with the current backend.
+    supports_select_for_update_with_limit = False
 
 
 class DatabaseOperations(BaseDatabaseOperations):

+ 3 - 1
django/db/models/query.py

@@ -357,7 +357,9 @@ class QuerySet(object):
         clone = self.filter(*args, **kwargs)
         if self.query.can_filter():
             clone = clone.order_by()
-        clone = clone[:MAX_GET_RESULTS + 1]
+        if (not clone.query.select_for_update or
+            connections[self.db].features.supports_select_for_update_with_limit):
+            clone = clone[:MAX_GET_RESULTS + 1]
         num = len(clone)
         if num == 1:
             return clone._result_cache[0]

+ 6 - 0
tests/select_for_update/tests.py

@@ -265,3 +265,9 @@ class SelectForUpdateTests(TransactionTestCase):
             self.assertEqual(router.db_for_write(Person), query.db)
         finally:
             router.routers = old_routers
+
+    @skipUnlessDBFeature('has_select_for_update')
+    def test_select_for_update_with_get(self):
+        with transaction.atomic():
+            person = Person.objects.select_for_update().get(name='Reinhardt')
+        self.assertEqual(person.name, 'Reinhardt')