diff --git a/django/db/backends/base/operations.py b/django/db/backends/base/operations.py index 7bf0210bc6..3517300b50 100644 --- a/django/db/backends/base/operations.py +++ b/django/db/backends/base/operations.py @@ -204,6 +204,22 @@ class BaseDatabaseOperations: ' SKIP LOCKED' if skip_locked else '', ) + def _get_limit_offset_params(self, low_mark, high_mark): + offset = low_mark or 0 + if high_mark is not None: + return (high_mark - offset), offset + elif offset: + return self.connection.ops.no_limit_value(), offset + return None, offset + + def limit_offset_sql(self, low_mark, high_mark): + """Return LIMIT/OFFSET SQL clause.""" + limit, offset = self._get_limit_offset_params(low_mark, high_mark) + return '%s%s' % ( + (' LIMIT %d' % limit) if limit else '', + (' OFFSET %d' % offset) if offset else '', + ) + def last_executed_query(self, cursor, sql, params): """ Return a string of the query last executed by the given cursor, with diff --git a/django/db/backends/oracle/operations.py b/django/db/backends/oracle/operations.py index 4377bd59ec..51df23aedb 100644 --- a/django/db/backends/oracle/operations.py +++ b/django/db/backends/oracle/operations.py @@ -233,6 +233,9 @@ END; else: return "%s" + def limit_offset_sql(self, low_mark, high_mark): + return '' + def last_executed_query(self, cursor, sql, params): # https://cx-oracle.readthedocs.io/en/latest/cursor.html#Cursor.statement # The DB API definition does not define this attribute. diff --git a/django/db/models/sql/compiler.py b/django/db/models/sql/compiler.py index 6e1c2a9aaa..6d063c4a05 100644 --- a/django/db/models/sql/compiler.py +++ b/django/db/models/sql/compiler.py @@ -532,14 +532,9 @@ class SQLCompiler: result.append('ORDER BY %s' % ', '.join(ordering)) if with_limits: - if self.query.high_mark is not None: - result.append('LIMIT %d' % (self.query.high_mark - self.query.low_mark)) - if self.query.low_mark: - if self.query.high_mark is None: - val = self.connection.ops.no_limit_value() - if val: - result.append('LIMIT %d' % val) - result.append('OFFSET %d' % self.query.low_mark) + limit_offset_sql = self.connection.ops.limit_offset_sql(self.query.low_mark, self.query.high_mark) + if limit_offset_sql: + result.append(limit_offset_sql) if for_update_part and not self.connection.features.for_update_after_from: result.append(for_update_part)