mirror of
https://github.com/django/django.git
synced 2025-09-03 02:45:09 +03:00
Compare commits
4 Commits
666a37dc5a
...
a834e61820
Author | SHA1 | Date | |
---|---|---|---|
|
a834e61820 | ||
|
6c37a2fbb2 | ||
|
21603c5b50 | ||
|
2709ee9cf1 |
|
@ -269,20 +269,12 @@ class DatabaseWrapper(BaseDatabaseWrapper):
|
|||
|
||||
conn_params.pop("assume_role", None)
|
||||
conn_params.pop("isolation_level", None)
|
||||
conn_params.pop("server_side_binding", None)
|
||||
|
||||
pool_options = conn_params.pop("pool", None)
|
||||
if pool_options and not is_psycopg3:
|
||||
raise ImproperlyConfigured("Database pooling requires psycopg >= 3")
|
||||
|
||||
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"]:
|
||||
|
@ -297,9 +289,8 @@ class DatabaseWrapper(BaseDatabaseWrapper):
|
|||
)
|
||||
# Disable prepared statements by default to keep connection poolers
|
||||
# working. Can be reenabled via OPTIONS in the settings dict.
|
||||
conn_params["prepare_threshold"] = conn_params.pop(
|
||||
"prepare_threshold", None
|
||||
)
|
||||
if "prepare_threshold" not in conn_params:
|
||||
conn_params["prepare_threshold"] = None
|
||||
return conn_params
|
||||
|
||||
@async_unsafe
|
||||
|
@ -406,28 +397,20 @@ class DatabaseWrapper(BaseDatabaseWrapper):
|
|||
|
||||
@async_unsafe
|
||||
def create_cursor(self, name=None):
|
||||
ssb = self.settings_dict["OPTIONS"].get("server_side_binding")
|
||||
cursor_factory = self.settings_dict["OPTIONS"].get("cursor_factory")
|
||||
|
||||
if name:
|
||||
if is_psycopg3 and (
|
||||
self.settings_dict["OPTIONS"].get("server_side_binding") is not True
|
||||
):
|
||||
# psycopg >= 3 forces the usage of server-side bindings for
|
||||
# named cursors so a specialized class that implements
|
||||
# server-side cursors while performing client-side bindings
|
||||
# must be used if `server_side_binding` is disabled (default).
|
||||
cursor = ServerSideCursor(
|
||||
self.connection,
|
||||
name=name,
|
||||
scrollable=False,
|
||||
withhold=self.connection.autocommit,
|
||||
)
|
||||
else:
|
||||
# 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
|
||||
)
|
||||
# In autocommit mode, the cursor will be used outside of a
|
||||
# transaction, hence use a holdable cursor.
|
||||
cursor = _server_cursor_factory(ssb, cursor_factory)(
|
||||
self.connection,
|
||||
name=name,
|
||||
scrollable=False,
|
||||
withhold=self.connection.autocommit,
|
||||
)
|
||||
else:
|
||||
cursor = self.connection.cursor()
|
||||
cursor = _cursor_factory(ssb, cursor_factory)(self.connection)
|
||||
|
||||
if is_psycopg3:
|
||||
# Register the cursor timezone only if the connection disagrees, to
|
||||
|
@ -572,15 +555,32 @@ if is_psycopg3:
|
|||
return args
|
||||
|
||||
class ServerBindingCursor(CursorMixin, Database.Cursor):
|
||||
pass
|
||||
"""
|
||||
Cursor that performs server-side parameter binding.
|
||||
|
||||
This is the default in psycopg3.
|
||||
"""
|
||||
|
||||
class Cursor(CursorMixin, Database.ClientCursor):
|
||||
pass
|
||||
|
||||
class ServerSideCursor(
|
||||
CursorMixin, Database.client_cursor.ClientCursorMixin, Database.ServerCursor
|
||||
):
|
||||
"""
|
||||
Cursor that performs client-side parameter binding.
|
||||
|
||||
This is the default in Django.
|
||||
"""
|
||||
|
||||
class ServerCursor(CursorMixin, Database.ServerCursor):
|
||||
"""
|
||||
Cursor that performs server-side parameter binding and uses
|
||||
server side cursors.
|
||||
|
||||
This is the default for named cursors in psycopg3.
|
||||
"""
|
||||
|
||||
class ServerSideCursor(Database.client_cursor.ClientCursorMixin, ServerCursor):
|
||||
"""
|
||||
Cursor that performs client-side parameter binding and uses
|
||||
server side cursors.
|
||||
|
||||
psycopg >= 3 forces the usage of server-side bindings when using named
|
||||
cursors but the ORM doesn't yet support the systematic generation of
|
||||
prepareable SQL (#20516).
|
||||
|
@ -592,8 +592,18 @@ if is_psycopg3:
|
|||
Mixing ClientCursorMixin in wouldn't be necessary if Cursor allowed to
|
||||
specify how parameters should be bound instead, which ServerCursor
|
||||
would inherit, but that's not the case.
|
||||
|
||||
This is the default for named cursors in Django.
|
||||
"""
|
||||
|
||||
def _cursor_factory(server_side_binding, cursor_factory):
|
||||
if cursor_factory:
|
||||
return cursor_factory
|
||||
return ServerBindingCursor if server_side_binding else Cursor
|
||||
|
||||
def _server_cursor_factory(server_side_binding, cursor_factory):
|
||||
return ServerCursor if server_side_binding else ServerSideCursor
|
||||
|
||||
class CursorDebugWrapper(BaseCursorDebugWrapper):
|
||||
def copy(self, statement):
|
||||
with self.debug_sql(statement):
|
||||
|
@ -602,6 +612,11 @@ if is_psycopg3:
|
|||
else:
|
||||
Cursor = psycopg2.extensions.cursor
|
||||
|
||||
def _cursor_factory(server_side_binding, cursor_factory):
|
||||
return cursor_factory or Cursor
|
||||
|
||||
_server_cursor_factory = _cursor_factory
|
||||
|
||||
class CursorDebugWrapper(BaseCursorDebugWrapper):
|
||||
def copy_expert(self, sql, file, *args):
|
||||
with self.debug_sql(sql):
|
||||
|
|
|
@ -1220,7 +1220,6 @@ values. It will return the first column or value that isn't ``NULL``.
|
|||
We'll start by defining the template to be used for SQL generation and
|
||||
an ``__init__()`` method to set some attributes::
|
||||
|
||||
import copy
|
||||
from django.db.models import Expression
|
||||
|
||||
|
||||
|
|
|
@ -583,9 +583,6 @@ Miscellaneous
|
|||
* The undocumented ``django.core.mail.forbid_multi_line_headers()`` and
|
||||
``django.core.mail.message.sanitize_address()`` functions are deprecated.
|
||||
|
||||
* The ``django.utils.crypto.constant_time_compare()`` function is deprecated
|
||||
because it is merely an alias of :func:`hmac.compare_digest`.
|
||||
|
||||
Features removed in 6.0
|
||||
=======================
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user