diff options
| author | François Freitag <mail@franek.fr> | 2016-06-03 15:31:21 -0700 |
|---|---|---|
| committer | Tim Graham <timograham@gmail.com> | 2017-01-11 09:25:37 -0500 |
| commit | f3b7c059367a4e82bbfc7e4f0d42b10975e79f0c (patch) | |
| tree | d64dedfcd04cfbe8d7599aa6411597cccba6eb17 /django/db/backends/postgresql | |
| parent | 53bffe8d03f01bd3214a5404998cb965fb28cd0b (diff) | |
Refs #16614 -- Made QuerySet.iterator() use server-side cursors on PostgreSQL.
Thanks to Josh Smeaton for the idea of implementing server-side cursors
in PostgreSQL from the iterator method, and Anssi Kääriäinen and Kevin
Turner for their previous work. Also Simon Charette and Tim Graham for
review.
Diffstat (limited to 'django/db/backends/postgresql')
| -rw-r--r-- | django/db/backends/postgresql/base.py | 25 |
1 files changed, 23 insertions, 2 deletions
diff --git a/django/db/backends/postgresql/base.py b/django/db/backends/postgresql/base.py index b4008532ee..91dee6a722 100644 --- a/django/db/backends/postgresql/base.py +++ b/django/db/backends/postgresql/base.py @@ -4,6 +4,7 @@ PostgreSQL database backend for Django. Requires psycopg 2: http://initd.org/projects/psycopg2 """ +import threading import warnings from django.conf import settings @@ -145,6 +146,10 @@ class DatabaseWrapper(BaseDatabaseWrapper): introspection_class = DatabaseIntrospection ops_class = DatabaseOperations + def __init__(self, *args, **kwargs): + super(DatabaseWrapper, self).__init__(*args, **kwargs) + self._named_cursor_idx = 0 + def get_connection_params(self): settings_dict = self.settings_dict # None may be used to connect to the default 'postgres' db @@ -206,11 +211,27 @@ class DatabaseWrapper(BaseDatabaseWrapper): if not self.get_autocommit(): self.connection.commit() - def create_cursor(self): - cursor = self.connection.cursor() + def create_cursor(self, name=None): + if name: + # In autocommit mode, the cursor will be used outside of a + # transaction, hence use a holdable cursor. + cursor = self.connection.cursor(name, scrollable=False, withhold=self.connection.autocommit) + else: + cursor = self.connection.cursor() cursor.tzinfo_factory = utc_tzinfo_factory if settings.USE_TZ else None return cursor + def chunked_cursor(self): + self._named_cursor_idx += 1 + db_cursor = self._cursor( + name='_django_curs_%d_%d' % ( + # Avoid reusing name in other threads + threading.current_thread().ident, + self._named_cursor_idx, + ) + ) + return self._prepare_cursor(db_cursor) + def _set_autocommit(self, autocommit): with self.wrap_database_errors: self.connection.autocommit = autocommit |
