diff options
author | django-bot <ops@djangoproject.com> | 2022-02-03 20:24:19 +0100 |
---|---|---|
committer | Mariusz Felisiak <felisiak.mariusz@gmail.com> | 2022-02-07 20:37:05 +0100 |
commit | 9c19aff7c7561e3a82978a272ecdaad40dda5c00 (patch) | |
tree | f0506b668a013d0063e5fba3dbf4863b466713ba /django/db/backends/postgresql/base.py | |
parent | f68fa8b45dfac545cfc4111d4e52804c86db68d3 (diff) | |
download | django-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.py | 213 |
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) |