summaryrefslogtreecommitdiff
path: root/tests/backends/postgresql
diff options
context:
space:
mode:
Diffstat (limited to 'tests/backends/postgresql')
-rw-r--r--tests/backends/postgresql/test_creation.py57
-rw-r--r--tests/backends/postgresql/test_introspection.py14
-rw-r--r--tests/backends/postgresql/test_operations.py2
-rw-r--r--tests/backends/postgresql/test_server_side_cursors.py38
-rw-r--r--tests/backends/postgresql/tests.py115
5 files changed, 138 insertions, 88 deletions
diff --git a/tests/backends/postgresql/test_creation.py b/tests/backends/postgresql/test_creation.py
index eb68c6e471..319029334d 100644
--- a/tests/backends/postgresql/test_creation.py
+++ b/tests/backends/postgresql/test_creation.py
@@ -18,12 +18,11 @@ else:
from django.db.backends.postgresql.creation import DatabaseCreation
-@unittest.skipUnless(connection.vendor == 'postgresql', 'PostgreSQL tests')
+@unittest.skipUnless(connection.vendor == "postgresql", "PostgreSQL tests")
class DatabaseCreationTests(SimpleTestCase):
-
@contextmanager
def changed_test_settings(self, **kwargs):
- settings = connection.settings_dict['TEST']
+ settings = connection.settings_dict["TEST"]
saved_values = {}
for name in kwargs:
if name in settings:
@@ -47,66 +46,80 @@ class DatabaseCreationTests(SimpleTestCase):
self.assertEqual(suffix, expected)
def test_sql_table_creation_suffix_with_none_settings(self):
- settings = {'CHARSET': None, 'TEMPLATE': None}
+ settings = {"CHARSET": None, "TEMPLATE": None}
self.check_sql_table_creation_suffix(settings, "")
def test_sql_table_creation_suffix_with_encoding(self):
- settings = {'CHARSET': 'UTF8'}
+ settings = {"CHARSET": "UTF8"}
self.check_sql_table_creation_suffix(settings, "WITH ENCODING 'UTF8'")
def test_sql_table_creation_suffix_with_template(self):
- settings = {'TEMPLATE': 'template0'}
+ settings = {"TEMPLATE": "template0"}
self.check_sql_table_creation_suffix(settings, 'WITH TEMPLATE "template0"')
def test_sql_table_creation_suffix_with_encoding_and_template(self):
- settings = {'CHARSET': 'UTF8', 'TEMPLATE': 'template0'}
- self.check_sql_table_creation_suffix(settings, '''WITH ENCODING 'UTF8' TEMPLATE "template0"''')
+ settings = {"CHARSET": "UTF8", "TEMPLATE": "template0"}
+ self.check_sql_table_creation_suffix(
+ settings, '''WITH ENCODING 'UTF8' TEMPLATE "template0"'''
+ )
def test_sql_table_creation_raises_with_collation(self):
- settings = {'COLLATION': 'test'}
+ settings = {"COLLATION": "test"}
msg = (
- 'PostgreSQL does not support collation setting at database '
- 'creation time.'
+ "PostgreSQL does not support collation setting at database "
+ "creation time."
)
with self.assertRaisesMessage(ImproperlyConfigured, msg):
self.check_sql_table_creation_suffix(settings, None)
def _execute_raise_database_already_exists(self, cursor, parameters, keepdb=False):
- error = DatabaseError('database %s already exists' % parameters['dbname'])
+ error = DatabaseError("database %s already exists" % parameters["dbname"])
error.pgcode = errorcodes.DUPLICATE_DATABASE
raise DatabaseError() from error
def _execute_raise_permission_denied(self, cursor, parameters, keepdb=False):
- error = DatabaseError('permission denied to create database')
+ error = DatabaseError("permission denied to create database")
error.pgcode = errorcodes.INSUFFICIENT_PRIVILEGE
raise DatabaseError() from error
def patch_test_db_creation(self, execute_create_test_db):
- return mock.patch.object(BaseDatabaseCreation, '_execute_create_test_db', execute_create_test_db)
+ return mock.patch.object(
+ BaseDatabaseCreation, "_execute_create_test_db", execute_create_test_db
+ )
- @mock.patch('sys.stdout', new_callable=StringIO)
- @mock.patch('sys.stderr', new_callable=StringIO)
+ @mock.patch("sys.stdout", new_callable=StringIO)
+ @mock.patch("sys.stderr", new_callable=StringIO)
def test_create_test_db(self, *mocked_objects):
creation = DatabaseCreation(connection)
# Simulate test database creation raising "database already exists"
with self.patch_test_db_creation(self._execute_raise_database_already_exists):
- with mock.patch('builtins.input', return_value='no'):
+ with mock.patch("builtins.input", return_value="no"):
with self.assertRaises(SystemExit):
# SystemExit is raised if the user answers "no" to the
# prompt asking if it's okay to delete the test database.
- creation._create_test_db(verbosity=0, autoclobber=False, keepdb=False)
+ creation._create_test_db(
+ verbosity=0, autoclobber=False, keepdb=False
+ )
# "Database already exists" error is ignored when keepdb is on
creation._create_test_db(verbosity=0, autoclobber=False, keepdb=True)
# Simulate test database creation raising unexpected error
with self.patch_test_db_creation(self._execute_raise_permission_denied):
- with mock.patch.object(DatabaseCreation, '_database_exists', return_value=False):
+ with mock.patch.object(
+ DatabaseCreation, "_database_exists", return_value=False
+ ):
with self.assertRaises(SystemExit):
- creation._create_test_db(verbosity=0, autoclobber=False, keepdb=False)
+ creation._create_test_db(
+ verbosity=0, autoclobber=False, keepdb=False
+ )
with self.assertRaises(SystemExit):
- creation._create_test_db(verbosity=0, autoclobber=False, keepdb=True)
+ creation._create_test_db(
+ verbosity=0, autoclobber=False, keepdb=True
+ )
# Simulate test database creation raising "insufficient privileges".
# An error shouldn't appear when keepdb is on and the database already
# exists.
with self.patch_test_db_creation(self._execute_raise_permission_denied):
- with mock.patch.object(DatabaseCreation, '_database_exists', return_value=True):
+ with mock.patch.object(
+ DatabaseCreation, "_database_exists", return_value=True
+ ):
creation._create_test_db(verbosity=0, autoclobber=False, keepdb=True)
diff --git a/tests/backends/postgresql/test_introspection.py b/tests/backends/postgresql/test_introspection.py
index 4dcadbd733..dc95d6ad23 100644
--- a/tests/backends/postgresql/test_introspection.py
+++ b/tests/backends/postgresql/test_introspection.py
@@ -6,18 +6,24 @@ from django.test import TestCase
from ..models import Person
-@unittest.skipUnless(connection.vendor == 'postgresql', "Test only for PostgreSQL")
+@unittest.skipUnless(connection.vendor == "postgresql", "Test only for PostgreSQL")
class DatabaseSequenceTests(TestCase):
def test_get_sequences(self):
with connection.cursor() as cursor:
seqs = connection.introspection.get_sequences(cursor, Person._meta.db_table)
self.assertEqual(
seqs,
- [{'table': Person._meta.db_table, 'column': 'id', 'name': 'backends_person_id_seq'}]
+ [
+ {
+ "table": Person._meta.db_table,
+ "column": "id",
+ "name": "backends_person_id_seq",
+ }
+ ],
)
- cursor.execute('ALTER SEQUENCE backends_person_id_seq RENAME TO pers_seq')
+ cursor.execute("ALTER SEQUENCE backends_person_id_seq RENAME TO pers_seq")
seqs = connection.introspection.get_sequences(cursor, Person._meta.db_table)
self.assertEqual(
seqs,
- [{'table': Person._meta.db_table, 'column': 'id', 'name': 'pers_seq'}]
+ [{"table": Person._meta.db_table, "column": "id", "name": "pers_seq"}],
)
diff --git a/tests/backends/postgresql/test_operations.py b/tests/backends/postgresql/test_operations.py
index 821bb29cee..c2f2417923 100644
--- a/tests/backends/postgresql/test_operations.py
+++ b/tests/backends/postgresql/test_operations.py
@@ -7,7 +7,7 @@ from django.test import SimpleTestCase
from ..models import Person, Tag
-@unittest.skipUnless(connection.vendor == 'postgresql', 'PostgreSQL tests.')
+@unittest.skipUnless(connection.vendor == "postgresql", "PostgreSQL tests.")
class PostgreSQLOperationsTests(SimpleTestCase):
def test_sql_flush(self):
self.assertEqual(
diff --git a/tests/backends/postgresql/test_server_side_cursors.py b/tests/backends/postgresql/test_server_side_cursors.py
index 0cc3423a9b..705e798c23 100644
--- a/tests/backends/postgresql/test_server_side_cursors.py
+++ b/tests/backends/postgresql/test_server_side_cursors.py
@@ -9,19 +9,23 @@ from django.test import TestCase
from ..models import Person
-@unittest.skipUnless(connection.vendor == 'postgresql', 'PostgreSQL tests')
+@unittest.skipUnless(connection.vendor == "postgresql", "PostgreSQL tests")
class ServerSideCursorsPostgres(TestCase):
- cursor_fields = 'name, statement, is_holdable, is_binary, is_scrollable, creation_time'
- PostgresCursor = namedtuple('PostgresCursor', cursor_fields)
+ cursor_fields = (
+ "name, statement, is_holdable, is_binary, is_scrollable, creation_time"
+ )
+ PostgresCursor = namedtuple("PostgresCursor", cursor_fields)
@classmethod
def setUpTestData(cls):
- Person.objects.create(first_name='a', last_name='a')
- Person.objects.create(first_name='b', last_name='b')
+ Person.objects.create(first_name="a", last_name="a")
+ Person.objects.create(first_name="b", last_name="b")
def inspect_cursors(self):
with connection.cursor() as cursor:
- cursor.execute('SELECT {fields} FROM pg_cursors;'.format(fields=self.cursor_fields))
+ cursor.execute(
+ "SELECT {fields} FROM pg_cursors;".format(fields=self.cursor_fields)
+ )
cursors = cursor.fetchall()
return [self.PostgresCursor._make(cursor) for cursor in cursors]
@@ -30,7 +34,9 @@ class ServerSideCursorsPostgres(TestCase):
for setting in kwargs:
original_value = connection.settings_dict.get(setting)
if setting in connection.settings_dict:
- self.addCleanup(operator.setitem, connection.settings_dict, setting, original_value)
+ self.addCleanup(
+ operator.setitem, connection.settings_dict, setting, original_value
+ )
else:
self.addCleanup(operator.delitem, connection.settings_dict, setting)
@@ -42,7 +48,7 @@ class ServerSideCursorsPostgres(TestCase):
cursors = self.inspect_cursors()
self.assertEqual(len(cursors), num_expected)
for cursor in cursors:
- self.assertIn('_django_curs_', cursor.name)
+ self.assertIn("_django_curs_", cursor.name)
self.assertFalse(cursor.is_scrollable)
self.assertFalse(cursor.is_holdable)
self.assertFalse(cursor.is_binary)
@@ -54,17 +60,23 @@ class ServerSideCursorsPostgres(TestCase):
self.assertUsesCursor(Person.objects.iterator())
def test_values(self):
- self.assertUsesCursor(Person.objects.values('first_name').iterator())
+ self.assertUsesCursor(Person.objects.values("first_name").iterator())
def test_values_list(self):
- self.assertUsesCursor(Person.objects.values_list('first_name').iterator())
+ self.assertUsesCursor(Person.objects.values_list("first_name").iterator())
def test_values_list_flat(self):
- self.assertUsesCursor(Person.objects.values_list('first_name', flat=True).iterator())
+ self.assertUsesCursor(
+ Person.objects.values_list("first_name", flat=True).iterator()
+ )
def test_values_list_fields_not_equal_to_names(self):
- expr = models.Count('id')
- self.assertUsesCursor(Person.objects.annotate(id__count=expr).values_list(expr, 'id__count').iterator())
+ expr = models.Count("id")
+ self.assertUsesCursor(
+ Person.objects.annotate(id__count=expr)
+ .values_list(expr, "id__count")
+ .iterator()
+ )
def test_server_side_cursor_many_cursors(self):
persons = Person.objects.iterator()
diff --git a/tests/backends/postgresql/tests.py b/tests/backends/postgresql/tests.py
index 1905147f6f..af08f6f286 100644
--- a/tests/backends/postgresql/tests.py
+++ b/tests/backends/postgresql/tests.py
@@ -9,9 +9,9 @@ from django.db.backends.base.base import BaseDatabaseWrapper
from django.test import TestCase, override_settings
-@unittest.skipUnless(connection.vendor == 'postgresql', 'PostgreSQL tests')
+@unittest.skipUnless(connection.vendor == "postgresql", "PostgreSQL tests")
class Tests(TestCase):
- databases = {'default', 'other'}
+ databases = {"default", "other"}
def test_nodb_cursor(self):
"""
@@ -21,14 +21,14 @@ class Tests(TestCase):
orig_connect = BaseDatabaseWrapper.connect
def mocked_connect(self):
- if self.settings_dict['NAME'] is None:
+ if self.settings_dict["NAME"] is None:
raise DatabaseError()
return orig_connect(self)
with connection._nodb_cursor() as cursor:
self.assertIs(cursor.closed, False)
self.assertIsNotNone(cursor.db.connection)
- self.assertIsNone(cursor.db.settings_dict['NAME'])
+ self.assertIsNone(cursor.db.settings_dict["NAME"])
self.assertIs(cursor.closed, True)
self.assertIsNone(cursor.db.connection)
@@ -41,24 +41,29 @@ class Tests(TestCase):
"database and will use the first PostgreSQL database instead."
)
with self.assertWarnsMessage(RuntimeWarning, msg):
- with mock.patch('django.db.backends.base.base.BaseDatabaseWrapper.connect',
- side_effect=mocked_connect, autospec=True):
+ with mock.patch(
+ "django.db.backends.base.base.BaseDatabaseWrapper.connect",
+ side_effect=mocked_connect,
+ autospec=True,
+ ):
with mock.patch.object(
connection,
- 'settings_dict',
- {**connection.settings_dict, 'NAME': 'postgres'},
+ "settings_dict",
+ {**connection.settings_dict, "NAME": "postgres"},
):
with connection._nodb_cursor() as cursor:
self.assertIs(cursor.closed, False)
self.assertIsNotNone(cursor.db.connection)
self.assertIs(cursor.closed, True)
self.assertIsNone(cursor.db.connection)
- self.assertIsNotNone(cursor.db.settings_dict['NAME'])
- self.assertEqual(cursor.db.settings_dict['NAME'], connections['other'].settings_dict['NAME'])
+ self.assertIsNotNone(cursor.db.settings_dict["NAME"])
+ self.assertEqual(
+ cursor.db.settings_dict["NAME"], connections["other"].settings_dict["NAME"]
+ )
# Cursor is yielded only for the first PostgreSQL database.
with self.assertWarnsMessage(RuntimeWarning, msg):
with mock.patch(
- 'django.db.backends.base.base.BaseDatabaseWrapper.connect',
+ "django.db.backends.base.base.BaseDatabaseWrapper.connect",
side_effect=mocked_connect,
autospec=True,
):
@@ -71,13 +76,14 @@ class Tests(TestCase):
_nodb_cursor() re-raises authentication failure to the 'postgres' db
when other connection to the PostgreSQL database isn't available.
"""
+
def mocked_connect(self):
raise DatabaseError()
def mocked_all(self):
test_connection = copy.copy(connections[DEFAULT_DB_ALIAS])
test_connection.settings_dict = copy.deepcopy(connection.settings_dict)
- test_connection.settings_dict['NAME'] = 'postgres'
+ test_connection.settings_dict["NAME"] = "postgres"
return [test_connection]
msg = (
@@ -89,12 +95,12 @@ class Tests(TestCase):
)
with self.assertWarnsMessage(RuntimeWarning, msg):
mocker_connections_all = mock.patch(
- 'django.utils.connection.BaseConnectionHandler.all',
+ "django.utils.connection.BaseConnectionHandler.all",
side_effect=mocked_all,
autospec=True,
)
mocker_connect = mock.patch(
- 'django.db.backends.base.base.BaseDatabaseWrapper.connect',
+ "django.db.backends.base.base.BaseDatabaseWrapper.connect",
side_effect=mocked_connect,
autospec=True,
)
@@ -104,27 +110,29 @@ class Tests(TestCase):
pass
def test_nodb_cursor_reraise_exceptions(self):
- with self.assertRaisesMessage(DatabaseError, 'exception'):
+ with self.assertRaisesMessage(DatabaseError, "exception"):
with connection._nodb_cursor():
- raise DatabaseError('exception')
+ raise DatabaseError("exception")
def test_database_name_too_long(self):
from django.db.backends.postgresql.base import DatabaseWrapper
+
settings = connection.settings_dict.copy()
max_name_length = connection.ops.max_name_length()
- settings['NAME'] = 'a' + (max_name_length * 'a')
+ settings["NAME"] = "a" + (max_name_length * "a")
msg = (
"The database name '%s' (%d characters) is longer than "
"PostgreSQL's limit of %s characters. Supply a shorter NAME in "
"settings.DATABASES."
- ) % (settings['NAME'], max_name_length + 1, max_name_length)
+ ) % (settings["NAME"], max_name_length + 1, max_name_length)
with self.assertRaisesMessage(ImproperlyConfigured, msg):
DatabaseWrapper(settings).get_connection_params()
def test_database_name_empty(self):
from django.db.backends.postgresql.base import DatabaseWrapper
+
settings = connection.settings_dict.copy()
- settings['NAME'] = ''
+ settings["NAME"] = ""
msg = (
"settings.DATABASES is improperly configured. Please supply the "
"NAME or OPTIONS['service'] value."
@@ -134,22 +142,24 @@ class Tests(TestCase):
def test_service_name(self):
from django.db.backends.postgresql.base import DatabaseWrapper
+
settings = connection.settings_dict.copy()
- settings['OPTIONS'] = {'service': 'my_service'}
- settings['NAME'] = ''
+ settings["OPTIONS"] = {"service": "my_service"}
+ settings["NAME"] = ""
params = DatabaseWrapper(settings).get_connection_params()
- self.assertEqual(params['service'], 'my_service')
- self.assertNotIn('database', params)
+ self.assertEqual(params["service"], "my_service")
+ self.assertNotIn("database", params)
def test_service_name_default_db(self):
# None is used to connect to the default 'postgres' db.
from django.db.backends.postgresql.base import DatabaseWrapper
+
settings = connection.settings_dict.copy()
- settings['NAME'] = None
- settings['OPTIONS'] = {'service': 'django_test'}
+ settings["NAME"] = None
+ settings["OPTIONS"] = {"service": "django_test"}
params = DatabaseWrapper(settings).get_connection_params()
- self.assertEqual(params['database'], 'postgres')
- self.assertNotIn('service', params)
+ self.assertEqual(params["database"], "postgres")
+ self.assertNotIn("service", params)
def test_connect_and_rollback(self):
"""
@@ -165,7 +175,7 @@ class Tests(TestCase):
cursor.execute("RESET TIMEZONE")
cursor.execute("SHOW TIMEZONE")
db_default_tz = cursor.fetchone()[0]
- new_tz = 'Europe/Paris' if db_default_tz == 'UTC' else 'UTC'
+ new_tz = "Europe/Paris" if db_default_tz == "UTC" else "UTC"
new_connection.close()
# Invalidate timezone name cache, because the setting_changed
@@ -193,7 +203,7 @@ class Tests(TestCase):
after setting the time zone when AUTOCOMMIT is False (#21452).
"""
new_connection = connection.copy()
- new_connection.settings_dict['AUTOCOMMIT'] = False
+ new_connection.settings_dict["AUTOCOMMIT"] = False
try:
# Open a database connection.
@@ -207,9 +217,7 @@ class Tests(TestCase):
The transaction level can be configured with
DATABASES ['OPTIONS']['isolation_level'].
"""
- from psycopg2.extensions import (
- ISOLATION_LEVEL_SERIALIZABLE as serializable,
- )
+ from psycopg2.extensions import ISOLATION_LEVEL_SERIALIZABLE as serializable
# Since this is a django.test.TestCase, a transaction is in progress
# and the isolation level isn't reported as 0. This test assumes that
@@ -218,7 +226,7 @@ class Tests(TestCase):
self.assertIsNone(connection.connection.isolation_level)
new_connection = connection.copy()
- new_connection.settings_dict['OPTIONS']['isolation_level'] = serializable
+ new_connection.settings_dict["OPTIONS"]["isolation_level"] = serializable
try:
# Start a transaction so the isolation level isn't reported as 0.
new_connection.set_autocommit(False)
@@ -230,7 +238,7 @@ class Tests(TestCase):
def test_connect_no_is_usable_checks(self):
new_connection = connection.copy()
try:
- with mock.patch.object(new_connection, 'is_usable') as is_usable:
+ with mock.patch.object(new_connection, "is_usable") as is_usable:
new_connection.connect()
is_usable.assert_not_called()
finally:
@@ -238,49 +246,60 @@ class Tests(TestCase):
def _select(self, val):
with connection.cursor() as cursor:
- cursor.execute('SELECT %s', (val,))
+ cursor.execute("SELECT %s", (val,))
return cursor.fetchone()[0]
def test_select_ascii_array(self):
- a = ['awef']
+ a = ["awef"]
b = self._select(a)
self.assertEqual(a[0], b[0])
def test_select_unicode_array(self):
- a = ['ᄲawef']
+ a = ["ᄲawef"]
b = self._select(a)
self.assertEqual(a[0], b[0])
def test_lookup_cast(self):
from django.db.backends.postgresql.operations import DatabaseOperations
+
do = DatabaseOperations(connection=None)
lookups = (
- 'iexact', 'contains', 'icontains', 'startswith', 'istartswith',
- 'endswith', 'iendswith', 'regex', 'iregex',
+ "iexact",
+ "contains",
+ "icontains",
+ "startswith",
+ "istartswith",
+ "endswith",
+ "iendswith",
+ "regex",
+ "iregex",
)
for lookup in lookups:
with self.subTest(lookup=lookup):
- self.assertIn('::text', do.lookup_cast(lookup))
+ self.assertIn("::text", do.lookup_cast(lookup))
for lookup in lookups:
- for field_type in ('CICharField', 'CIEmailField', 'CITextField'):
+ for field_type in ("CICharField", "CIEmailField", "CITextField"):
with self.subTest(lookup=lookup, field_type=field_type):
- self.assertIn('::citext', do.lookup_cast(lookup, internal_type=field_type))
+ self.assertIn(
+ "::citext", do.lookup_cast(lookup, internal_type=field_type)
+ )
def test_correct_extraction_psycopg2_version(self):
from django.db.backends.postgresql.base import psycopg2_version
- with mock.patch('psycopg2.__version__', '4.2.1 (dt dec pq3 ext lo64)'):
+
+ with mock.patch("psycopg2.__version__", "4.2.1 (dt dec pq3 ext lo64)"):
self.assertEqual(psycopg2_version(), (4, 2, 1))
- with mock.patch('psycopg2.__version__', '4.2b0.dev1 (dt dec pq3 ext lo64)'):
+ with mock.patch("psycopg2.__version__", "4.2b0.dev1 (dt dec pq3 ext lo64)"):
self.assertEqual(psycopg2_version(), (4, 2))
@override_settings(DEBUG=True)
def test_copy_cursors(self):
out = StringIO()
- copy_expert_sql = 'COPY django_session TO STDOUT (FORMAT CSV, HEADER)'
+ copy_expert_sql = "COPY django_session TO STDOUT (FORMAT CSV, HEADER)"
with connection.cursor() as cursor:
cursor.copy_expert(copy_expert_sql, out)
- cursor.copy_to(out, 'django_session')
+ cursor.copy_to(out, "django_session")
self.assertEqual(
- [q['sql'] for q in connection.queries],
- [copy_expert_sql, 'COPY django_session TO STDOUT'],
+ [q["sql"] for q in connection.queries],
+ [copy_expert_sql, "COPY django_session TO STDOUT"],
)