diff options
| author | Anders Kaseorg <andersk@mit.edu> | 2023-04-06 12:44:37 -0700 |
|---|---|---|
| committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2023-04-07 09:21:54 +0200 |
| commit | 0bc2bbf041df40a6ecb6262b2e5f3bb659dd8da8 (patch) | |
| tree | b1dfb41f38d3eec0f9f91d4fb704fc0b19562c3d | |
| parent | 511dc3db539122577aaba71f5a24d65d5adab092 (diff) | |
[4.2.x] Fixed #34466 -- Reallowed setting cursor_factory in DATABASES["options"] on PostgreSQL.
Regression in 09ffc5c1212d4ced58b708cbbf3dfbfb77b782ca.
Backport of 73cbb372baa45d1fdafd571e2f430a980831f722 from main
| -rw-r--r-- | django/db/backends/postgresql/base.py | 17 | ||||
| -rw-r--r-- | docs/releases/4.2.1.txt | 4 | ||||
| -rw-r--r-- | tests/backends/postgresql/tests.py | 18 |
3 files changed, 30 insertions, 9 deletions
diff --git a/django/db/backends/postgresql/base.py b/django/db/backends/postgresql/base.py index 3db3d6abd2..5ed856448f 100644 --- a/django/db/backends/postgresql/base.py +++ b/django/db/backends/postgresql/base.py @@ -223,7 +223,13 @@ class DatabaseWrapper(BaseDatabaseWrapper): conn_params.pop("assume_role", None) conn_params.pop("isolation_level", None) - conn_params.pop("server_side_binding", None) + server_side_binding = conn_params.pop("server_side_binding", None) + conn_params.setdefault( + "cursor_factory", + ServerBindingCursor + if is_psycopg3 and server_side_binding is True + else Cursor, + ) if settings_dict["USER"]: conn_params["user"] = settings_dict["USER"] if settings_dict["PASSWORD"]: @@ -269,20 +275,13 @@ class DatabaseWrapper(BaseDatabaseWrapper): connection = self.Database.connect(**conn_params) if set_isolation_level: connection.isolation_level = self.isolation_level - if is_psycopg3: - connection.cursor_factory = ( - ServerBindingCursor - if options.get("server_side_binding") is True - else Cursor - ) - else: + if not is_psycopg3: # Register dummy loads() to avoid a round trip from psycopg2's # decode to json.dumps() to json.loads(), when using a custom # decoder in JSONField. psycopg2.extras.register_default_jsonb( conn_or_curs=connection, loads=lambda x: x ) - connection.cursor_factory = Cursor return connection def ensure_timezone(self): diff --git a/docs/releases/4.2.1.txt b/docs/releases/4.2.1.txt index f8a4edf787..dd172a1a89 100644 --- a/docs/releases/4.2.1.txt +++ b/docs/releases/4.2.1.txt @@ -18,3 +18,7 @@ Bugfixes * Fixed a regression in Django 4.2 that caused aggregation over query that uses explicit grouping to group against the wrong columns (:ticket:`34464`). + +* Reallowed, following a regression in Django 4.2, setting the + ``"cursor_factory"`` option in :setting:`OPTIONS` on PostgreSQL + (:ticket:`34466`). diff --git a/tests/backends/postgresql/tests.py b/tests/backends/postgresql/tests.py index ab66e7ab0e..5589daa0c2 100644 --- a/tests/backends/postgresql/tests.py +++ b/tests/backends/postgresql/tests.py @@ -296,6 +296,24 @@ class Tests(TestCase): finally: new_connection.close() + def test_connect_custom_cursor_factory(self): + """ + A custom cursor factory can be configured with DATABASES["options"] + ["cursor_factory"]. + """ + from django.db.backends.postgresql.base import Cursor + + class MyCursor(Cursor): + pass + + new_connection = connection.copy() + new_connection.settings_dict["OPTIONS"]["cursor_factory"] = MyCursor + try: + new_connection.connect() + self.assertEqual(new_connection.connection.cursor_factory, MyCursor) + finally: + new_connection.close() + def test_connect_no_is_usable_checks(self): new_connection = connection.copy() try: |
