Kaydet (Commit) 746f2a4b authored tarafından Shai Berger's avatar Shai Berger

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

Thanks Michael Miller for reporting the issue.
üst 6d256ae2
...@@ -666,6 +666,9 @@ class BaseDatabaseFeatures(object): ...@@ -666,6 +666,9 @@ class BaseDatabaseFeatures(object):
uppercases_column_names = False 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): def __init__(self, connection):
self.connection = connection self.connection = connection
......
...@@ -121,6 +121,8 @@ class DatabaseFeatures(BaseDatabaseFeatures): ...@@ -121,6 +121,8 @@ class DatabaseFeatures(BaseDatabaseFeatures):
closed_cursor_error_class = InterfaceError closed_cursor_error_class = InterfaceError
bare_select_suffix = " FROM DUAL" bare_select_suffix = " FROM DUAL"
uppercases_column_names = True 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): class DatabaseOperations(BaseDatabaseOperations):
......
...@@ -357,6 +357,8 @@ class QuerySet(object): ...@@ -357,6 +357,8 @@ class QuerySet(object):
clone = self.filter(*args, **kwargs) clone = self.filter(*args, **kwargs)
if self.query.can_filter(): if self.query.can_filter():
clone = clone.order_by() clone = clone.order_by()
if (not clone.query.select_for_update or
connections[self.db].features.supports_select_for_update_with_limit):
clone = clone[:MAX_GET_RESULTS + 1] clone = clone[:MAX_GET_RESULTS + 1]
num = len(clone) num = len(clone)
if num == 1: if num == 1:
......
...@@ -265,3 +265,9 @@ class SelectForUpdateTests(TransactionTestCase): ...@@ -265,3 +265,9 @@ class SelectForUpdateTests(TransactionTestCase):
self.assertEqual(router.db_for_write(Person), query.db) self.assertEqual(router.db_for_write(Person), query.db)
finally: finally:
router.routers = old_routers 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')
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment