summaryrefslogtreecommitdiff
path: root/django/db/backends/postgresql/base.py
diff options
context:
space:
mode:
authordjango-bot <ops@djangoproject.com>2022-02-03 20:24:19 +0100
committerMariusz Felisiak <felisiak.mariusz@gmail.com>2022-02-07 20:37:05 +0100
commit9c19aff7c7561e3a82978a272ecdaad40dda5c00 (patch)
treef0506b668a013d0063e5fba3dbf4863b466713ba /django/db/backends/postgresql/base.py
parentf68fa8b45dfac545cfc4111d4e52804c86db68d3 (diff)
downloaddjango-9c19aff7c7561e3a82978a272ecdaad40dda5c00.tar.gz
Refs #33476 -- Reformatted code with Black.
Diffstat (limited to 'django/db/backends/postgresql/base.py')
-rw-r--r--django/db/backends/postgresql/base.py213
1 files changed, 114 insertions, 99 deletions
diff --git a/django/db/backends/postgresql/base.py b/django/db/backends/postgresql/base.py
index e49d453f94..92f393227e 100644
--- a/django/db/backends/postgresql/base.py
+++ b/django/db/backends/postgresql/base.py
@@ -11,11 +11,10 @@ from contextlib import contextmanager
from django.conf import settings
from django.core.exceptions import ImproperlyConfigured
-from django.db import DatabaseError as WrappedDatabaseError, connections
+from django.db import DatabaseError as WrappedDatabaseError
+from django.db import connections
from django.db.backends.base.base import BaseDatabaseWrapper
-from django.db.backends.utils import (
- CursorDebugWrapper as BaseCursorDebugWrapper,
-)
+from django.db.backends.utils import CursorDebugWrapper as BaseCursorDebugWrapper
from django.utils.asyncio import async_unsafe
from django.utils.functional import cached_property
from django.utils.safestring import SafeString
@@ -30,14 +29,17 @@ except ImportError as e:
def psycopg2_version():
- version = psycopg2.__version__.split(' ', 1)[0]
+ version = psycopg2.__version__.split(" ", 1)[0]
return get_version_tuple(version)
PSYCOPG2_VERSION = psycopg2_version()
if PSYCOPG2_VERSION < (2, 8, 4):
- raise ImproperlyConfigured("psycopg2 version 2.8.4 or newer is required; you have %s" % psycopg2.__version__)
+ raise ImproperlyConfigured(
+ "psycopg2 version 2.8.4 or newer is required; you have %s"
+ % psycopg2.__version__
+ )
# Some of these import psycopg2, so import them after checking if it's installed.
@@ -56,68 +58,68 @@ psycopg2.extras.register_uuid()
INETARRAY_OID = 1041
INETARRAY = psycopg2.extensions.new_array_type(
(INETARRAY_OID,),
- 'INETARRAY',
+ "INETARRAY",
psycopg2.extensions.UNICODE,
)
psycopg2.extensions.register_type(INETARRAY)
class DatabaseWrapper(BaseDatabaseWrapper):
- vendor = 'postgresql'
- display_name = 'PostgreSQL'
+ vendor = "postgresql"
+ display_name = "PostgreSQL"
# This dictionary maps Field objects to their associated PostgreSQL column
# types, as strings. Column-type strings can contain format strings; they'll
# be interpolated against the values of Field.__dict__ before being output.
# If a column type is set to None, it won't be included in the output.
data_types = {
- 'AutoField': 'serial',
- 'BigAutoField': 'bigserial',
- 'BinaryField': 'bytea',
- 'BooleanField': 'boolean',
- 'CharField': 'varchar(%(max_length)s)',
- 'DateField': 'date',
- 'DateTimeField': 'timestamp with time zone',
- 'DecimalField': 'numeric(%(max_digits)s, %(decimal_places)s)',
- 'DurationField': 'interval',
- 'FileField': 'varchar(%(max_length)s)',
- 'FilePathField': 'varchar(%(max_length)s)',
- 'FloatField': 'double precision',
- 'IntegerField': 'integer',
- 'BigIntegerField': 'bigint',
- 'IPAddressField': 'inet',
- 'GenericIPAddressField': 'inet',
- 'JSONField': 'jsonb',
- 'OneToOneField': 'integer',
- 'PositiveBigIntegerField': 'bigint',
- 'PositiveIntegerField': 'integer',
- 'PositiveSmallIntegerField': 'smallint',
- 'SlugField': 'varchar(%(max_length)s)',
- 'SmallAutoField': 'smallserial',
- 'SmallIntegerField': 'smallint',
- 'TextField': 'text',
- 'TimeField': 'time',
- 'UUIDField': 'uuid',
+ "AutoField": "serial",
+ "BigAutoField": "bigserial",
+ "BinaryField": "bytea",
+ "BooleanField": "boolean",
+ "CharField": "varchar(%(max_length)s)",
+ "DateField": "date",
+ "DateTimeField": "timestamp with time zone",
+ "DecimalField": "numeric(%(max_digits)s, %(decimal_places)s)",
+ "DurationField": "interval",
+ "FileField": "varchar(%(max_length)s)",
+ "FilePathField": "varchar(%(max_length)s)",
+ "FloatField": "double precision",
+ "IntegerField": "integer",
+ "BigIntegerField": "bigint",
+ "IPAddressField": "inet",
+ "GenericIPAddressField": "inet",
+ "JSONField": "jsonb",
+ "OneToOneField": "integer",
+ "PositiveBigIntegerField": "bigint",
+ "PositiveIntegerField": "integer",
+ "PositiveSmallIntegerField": "smallint",
+ "SlugField": "varchar(%(max_length)s)",
+ "SmallAutoField": "smallserial",
+ "SmallIntegerField": "smallint",
+ "TextField": "text",
+ "TimeField": "time",
+ "UUIDField": "uuid",
}
data_type_check_constraints = {
- 'PositiveBigIntegerField': '"%(column)s" >= 0',
- 'PositiveIntegerField': '"%(column)s" >= 0',
- 'PositiveSmallIntegerField': '"%(column)s" >= 0',
+ "PositiveBigIntegerField": '"%(column)s" >= 0',
+ "PositiveIntegerField": '"%(column)s" >= 0',
+ "PositiveSmallIntegerField": '"%(column)s" >= 0',
}
operators = {
- 'exact': '= %s',
- 'iexact': '= UPPER(%s)',
- 'contains': 'LIKE %s',
- 'icontains': 'LIKE UPPER(%s)',
- 'regex': '~ %s',
- 'iregex': '~* %s',
- 'gt': '> %s',
- 'gte': '>= %s',
- 'lt': '< %s',
- 'lte': '<= %s',
- 'startswith': 'LIKE %s',
- 'endswith': 'LIKE %s',
- 'istartswith': 'LIKE UPPER(%s)',
- 'iendswith': 'LIKE UPPER(%s)',
+ "exact": "= %s",
+ "iexact": "= UPPER(%s)",
+ "contains": "LIKE %s",
+ "icontains": "LIKE UPPER(%s)",
+ "regex": "~ %s",
+ "iregex": "~* %s",
+ "gt": "> %s",
+ "gte": ">= %s",
+ "lt": "< %s",
+ "lte": "<= %s",
+ "startswith": "LIKE %s",
+ "endswith": "LIKE %s",
+ "istartswith": "LIKE UPPER(%s)",
+ "iendswith": "LIKE UPPER(%s)",
}
# The patterns below are used to generate SQL pattern lookup clauses when
@@ -128,14 +130,16 @@ class DatabaseWrapper(BaseDatabaseWrapper):
#
# Note: we use str.format() here for readability as '%' is used as a wildcard for
# the LIKE operator.
- pattern_esc = r"REPLACE(REPLACE(REPLACE({}, E'\\', E'\\\\'), E'%%', E'\\%%'), E'_', E'\\_')"
+ pattern_esc = (
+ r"REPLACE(REPLACE(REPLACE({}, E'\\', E'\\\\'), E'%%', E'\\%%'), E'_', E'\\_')"
+ )
pattern_ops = {
- 'contains': "LIKE '%%' || {} || '%%'",
- 'icontains': "LIKE '%%' || UPPER({}) || '%%'",
- 'startswith': "LIKE {} || '%%'",
- 'istartswith': "LIKE UPPER({}) || '%%'",
- 'endswith': "LIKE '%%' || {}",
- 'iendswith': "LIKE '%%' || UPPER({})",
+ "contains": "LIKE '%%' || {} || '%%'",
+ "icontains": "LIKE '%%' || UPPER({}) || '%%'",
+ "startswith": "LIKE {} || '%%'",
+ "istartswith": "LIKE UPPER({}) || '%%'",
+ "endswith": "LIKE '%%' || {}",
+ "iendswith": "LIKE '%%' || UPPER({})",
}
Database = Database
@@ -152,46 +156,46 @@ class DatabaseWrapper(BaseDatabaseWrapper):
def get_connection_params(self):
settings_dict = self.settings_dict
# None may be used to connect to the default 'postgres' db
- if (
- settings_dict['NAME'] == '' and
- not settings_dict.get('OPTIONS', {}).get('service')
+ if settings_dict["NAME"] == "" and not settings_dict.get("OPTIONS", {}).get(
+ "service"
):
raise ImproperlyConfigured(
"settings.DATABASES is improperly configured. "
"Please supply the NAME or OPTIONS['service'] value."
)
- if len(settings_dict['NAME'] or '') > self.ops.max_name_length():
+ if len(settings_dict["NAME"] or "") > self.ops.max_name_length():
raise ImproperlyConfigured(
"The database name '%s' (%d characters) is longer than "
"PostgreSQL's limit of %d characters. Supply a shorter NAME "
- "in settings.DATABASES." % (
- settings_dict['NAME'],
- len(settings_dict['NAME']),
+ "in settings.DATABASES."
+ % (
+ settings_dict["NAME"],
+ len(settings_dict["NAME"]),
self.ops.max_name_length(),
)
)
conn_params = {}
- if settings_dict['NAME']:
+ if settings_dict["NAME"]:
conn_params = {
- 'database': settings_dict['NAME'],
- **settings_dict['OPTIONS'],
+ "database": settings_dict["NAME"],
+ **settings_dict["OPTIONS"],
}
- elif settings_dict['NAME'] is None:
+ elif settings_dict["NAME"] is None:
# Connect to the default 'postgres' db.
- settings_dict.get('OPTIONS', {}).pop('service', None)
- conn_params = {'database': 'postgres', **settings_dict['OPTIONS']}
+ settings_dict.get("OPTIONS", {}).pop("service", None)
+ conn_params = {"database": "postgres", **settings_dict["OPTIONS"]}
else:
- conn_params = {**settings_dict['OPTIONS']}
-
- conn_params.pop('isolation_level', None)
- if settings_dict['USER']:
- conn_params['user'] = settings_dict['USER']
- if settings_dict['PASSWORD']:
- conn_params['password'] = settings_dict['PASSWORD']
- if settings_dict['HOST']:
- conn_params['host'] = settings_dict['HOST']
- if settings_dict['PORT']:
- conn_params['port'] = settings_dict['PORT']
+ conn_params = {**settings_dict["OPTIONS"]}
+
+ conn_params.pop("isolation_level", None)
+ if settings_dict["USER"]:
+ conn_params["user"] = settings_dict["USER"]
+ if settings_dict["PASSWORD"]:
+ conn_params["password"] = settings_dict["PASSWORD"]
+ if settings_dict["HOST"]:
+ conn_params["host"] = settings_dict["HOST"]
+ if settings_dict["PORT"]:
+ conn_params["port"] = settings_dict["PORT"]
return conn_params
@async_unsafe
@@ -203,9 +207,9 @@ class DatabaseWrapper(BaseDatabaseWrapper):
# default when no value is explicitly specified in options.
# - before calling _set_autocommit() because if autocommit is on, that
# will set connection.isolation_level to ISOLATION_LEVEL_AUTOCOMMIT.
- options = self.settings_dict['OPTIONS']
+ options = self.settings_dict["OPTIONS"]
try:
- self.isolation_level = options['isolation_level']
+ self.isolation_level = options["isolation_level"]
except KeyError:
self.isolation_level = connection.isolation_level
else:
@@ -215,13 +219,15 @@ class DatabaseWrapper(BaseDatabaseWrapper):
# 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)
+ psycopg2.extras.register_default_jsonb(
+ conn_or_curs=connection, loads=lambda x: x
+ )
return connection
def ensure_timezone(self):
if self.connection is None:
return False
- conn_timezone_name = self.connection.get_parameter_status('TimeZone')
+ conn_timezone_name = self.connection.get_parameter_status("TimeZone")
timezone_name = self.timezone_name
if timezone_name and conn_timezone_name != timezone_name:
with self.connection.cursor() as cursor:
@@ -230,7 +236,7 @@ class DatabaseWrapper(BaseDatabaseWrapper):
return False
def init_connection_state(self):
- self.connection.set_client_encoding('UTF8')
+ self.connection.set_client_encoding("UTF8")
timezone_changed = self.ensure_timezone()
if timezone_changed:
@@ -243,7 +249,9 @@ class DatabaseWrapper(BaseDatabaseWrapper):
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)
+ cursor = self.connection.cursor(
+ name, scrollable=False, withhold=self.connection.autocommit
+ )
else:
cursor = self.connection.cursor()
cursor.tzinfo_factory = self.tzinfo_factory if settings.USE_TZ else None
@@ -268,10 +276,11 @@ class DatabaseWrapper(BaseDatabaseWrapper):
if current_task:
task_ident = str(id(current_task))
else:
- task_ident = 'sync'
+ task_ident = "sync"
# Use that and the thread ident to get a unique name
return self._cursor(
- name='_django_curs_%d_%s_%d' % (
+ name="_django_curs_%d_%s_%d"
+ % (
# Avoid reusing name in other threads / tasks
threading.current_thread().ident,
task_ident,
@@ -289,14 +298,14 @@ class DatabaseWrapper(BaseDatabaseWrapper):
afterward.
"""
with self.cursor() as cursor:
- cursor.execute('SET CONSTRAINTS ALL IMMEDIATE')
- cursor.execute('SET CONSTRAINTS ALL DEFERRED')
+ cursor.execute("SET CONSTRAINTS ALL IMMEDIATE")
+ cursor.execute("SET CONSTRAINTS ALL DEFERRED")
def is_usable(self):
try:
# Use a psycopg cursor directly, bypassing Django's utilities.
with self.connection.cursor() as cursor:
- cursor.execute('SELECT 1')
+ cursor.execute("SELECT 1")
except Database.Error:
return False
else:
@@ -317,12 +326,18 @@ class DatabaseWrapper(BaseDatabaseWrapper):
"database when it's not needed (for example, when running tests). "
"Django was unable to create a connection to the 'postgres' database "
"and will use the first PostgreSQL database instead.",
- RuntimeWarning
+ RuntimeWarning,
)
for connection in connections.all():
- if connection.vendor == 'postgresql' and connection.settings_dict['NAME'] != 'postgres':
+ if (
+ connection.vendor == "postgresql"
+ and connection.settings_dict["NAME"] != "postgres"
+ ):
conn = self.__class__(
- {**self.settings_dict, 'NAME': connection.settings_dict['NAME']},
+ {
+ **self.settings_dict,
+ "NAME": connection.settings_dict["NAME"],
+ },
alias=self.alias,
)
try:
@@ -349,5 +364,5 @@ class CursorDebugWrapper(BaseCursorDebugWrapper):
return self.cursor.copy_expert(sql, file, *args)
def copy_to(self, file, table, *args, **kwargs):
- with self.debug_sql(sql='COPY %s TO STDOUT' % table):
+ with self.debug_sql(sql="COPY %s TO STDOUT" % table):
return self.cursor.copy_to(file, table, *args, **kwargs)