mirror of
https://github.com/django/django.git
synced 2024-12-01 15:42:04 +01:00
Fixed #27061 -- Added a TEST['TEMPLATE'] setting for PostgreSQL.
This commit is contained in:
parent
bc1e2d8e8e
commit
a3db480393
@ -5,28 +5,42 @@ from django.db.backends.base.creation import BaseDatabaseCreation
|
||||
|
||||
class DatabaseCreation(BaseDatabaseCreation):
|
||||
|
||||
def _quote_name(self, name):
|
||||
return self.connection.ops.quote_name(name)
|
||||
|
||||
def _get_database_create_suffix(self, encoding=None, template=None):
|
||||
suffix = ""
|
||||
if encoding:
|
||||
suffix += " ENCODING '{}'".format(encoding)
|
||||
if template:
|
||||
suffix += " TEMPLATE {}".format(self._quote_name(template))
|
||||
if suffix:
|
||||
suffix = "WITH" + suffix
|
||||
return suffix
|
||||
|
||||
def sql_table_creation_suffix(self):
|
||||
test_settings = self.connection.settings_dict['TEST']
|
||||
assert test_settings['COLLATION'] is None, (
|
||||
"PostgreSQL does not support collation setting at database creation time."
|
||||
)
|
||||
if test_settings['CHARSET']:
|
||||
return "WITH ENCODING '%s'" % test_settings['CHARSET']
|
||||
return ''
|
||||
return self._get_database_create_suffix(
|
||||
encoding=test_settings['CHARSET'],
|
||||
template=test_settings.get('TEMPLATE'),
|
||||
)
|
||||
|
||||
def _clone_test_db(self, number, verbosity, keepdb=False):
|
||||
# CREATE DATABASE ... WITH TEMPLATE ... requires closing connections
|
||||
# to the template database.
|
||||
self.connection.close()
|
||||
|
||||
qn = self.connection.ops.quote_name
|
||||
source_database_name = self.connection.settings_dict['NAME']
|
||||
target_database_name = self.get_test_db_clone_settings(number)['NAME']
|
||||
suffix = self._get_database_create_suffix(template=source_database_name)
|
||||
creation_sql = "CREATE DATABASE {} {}".format(self._quote_name(target_database_name), suffix)
|
||||
|
||||
with self._nodb_connection.cursor() as cursor:
|
||||
try:
|
||||
cursor.execute("CREATE DATABASE %s WITH TEMPLATE %s" % (
|
||||
qn(target_database_name), qn(source_database_name)))
|
||||
cursor.execute(creation_sql)
|
||||
except Exception as e:
|
||||
if keepdb:
|
||||
return
|
||||
@ -35,9 +49,8 @@ class DatabaseCreation(BaseDatabaseCreation):
|
||||
print("Destroying old test database for alias %s..." % (
|
||||
self._get_database_display_str(verbosity, target_database_name),
|
||||
))
|
||||
cursor.execute("DROP DATABASE %s" % qn(target_database_name))
|
||||
cursor.execute("CREATE DATABASE %s WITH TEMPLATE %s" % (
|
||||
qn(target_database_name), qn(source_database_name)))
|
||||
cursor.execute("DROP DATABASE %s" % self._quote_name(target_database_name))
|
||||
cursor.execute(creation_sql)
|
||||
except Exception as e:
|
||||
sys.stderr.write("Got an error cloning the test database: %s\n" % e)
|
||||
sys.exit(2)
|
||||
|
@ -164,6 +164,16 @@ lookups that use the ``LIKE`` operator in their SQL, as is done with the
|
||||
|
||||
.. _PostgreSQL operator class: http://www.postgresql.org/docs/current/static/indexes-opclass.html
|
||||
|
||||
Test database templates
|
||||
-----------------------
|
||||
|
||||
.. versionadded:: 1.11
|
||||
|
||||
You can use the :setting:`TEST['TEMPLATE'] <TEST_TEMPLATE>` setting to specify
|
||||
a `template`_ (e.g. ``'template0'``) from which to create a test database.
|
||||
|
||||
.. _template: https://www.postgresql.org/docs/current/static/sql-createdatabase.html
|
||||
|
||||
Speeding up test execution with non-durable settings
|
||||
----------------------------------------------------
|
||||
|
||||
|
@ -738,6 +738,20 @@ the database state between tests if you don't have transactions). You can set
|
||||
this to ``False`` to speed up creation time if you don't have any test classes
|
||||
with :ref:`serialized_rollback=True <test-case-serialized-rollback>`.
|
||||
|
||||
.. setting:: TEST_TEMPLATE
|
||||
|
||||
``TEMPLATE``
|
||||
^^^^^^^^^^^^
|
||||
|
||||
.. versionadded:: 1.11
|
||||
|
||||
This is a PostgreSQL-specific setting.
|
||||
|
||||
The name of a `template`_ (e.g. ``'template0'``) from which to create the test
|
||||
database.
|
||||
|
||||
.. _template: https://www.postgresql.org/docs/current/static/sql-createdatabase.html
|
||||
|
||||
.. setting:: TEST_CREATE
|
||||
|
||||
``CREATE_DB``
|
||||
|
@ -159,6 +159,9 @@ Database backends
|
||||
on PostgreSQL 9.5+ and Oracle to execute queries with
|
||||
``FOR UPDATE SKIP LOCKED``.
|
||||
|
||||
* Added the :setting:`TEST['TEMPLATE'] <TEST_TEMPLATE>` setting to let
|
||||
PostgreSQL users specify a template for creating the test database.
|
||||
|
||||
Email
|
||||
~~~~~
|
||||
|
||||
|
@ -1,9 +1,12 @@
|
||||
import copy
|
||||
import unittest
|
||||
from contextlib import contextmanager
|
||||
|
||||
from django.db import DEFAULT_DB_ALIAS, connections
|
||||
from django.db import DEFAULT_DB_ALIAS, connection, connections
|
||||
from django.db.backends.base.creation import (
|
||||
TEST_DATABASE_PREFIX, BaseDatabaseCreation,
|
||||
)
|
||||
from django.db.backends.postgresql.creation import DatabaseCreation
|
||||
from django.test import SimpleTestCase
|
||||
|
||||
|
||||
@ -40,3 +43,48 @@ class TestDbSignatureTests(SimpleTestCase):
|
||||
test_connection.settings_dict['TEST'] = {'NAME': test_name}
|
||||
signature = BaseDatabaseCreation(test_connection).test_db_signature()
|
||||
self.assertEqual(signature[3], test_name)
|
||||
|
||||
|
||||
@unittest.skipUnless(connection.vendor == 'postgresql', "PostgreSQL-specific tests")
|
||||
class PostgreSQLDatabaseCreationTests(SimpleTestCase):
|
||||
|
||||
@contextmanager
|
||||
def changed_test_settings(self, **kwargs):
|
||||
settings = connection.settings_dict['TEST']
|
||||
saved_values = {}
|
||||
for name in kwargs:
|
||||
if name in settings:
|
||||
saved_values[name] = settings[name]
|
||||
|
||||
for name, value in kwargs.items():
|
||||
settings[name] = value
|
||||
try:
|
||||
yield
|
||||
finally:
|
||||
for name, value in kwargs.items():
|
||||
if name in saved_values:
|
||||
settings[name] = saved_values[name]
|
||||
else:
|
||||
del settings[name]
|
||||
|
||||
def check_sql_table_creation_suffix(self, settings, expected):
|
||||
with self.changed_test_settings(**settings):
|
||||
creation = DatabaseCreation(connection)
|
||||
suffix = creation.sql_table_creation_suffix()
|
||||
self.assertEqual(suffix, expected)
|
||||
|
||||
def test_sql_table_creation_suffix_with_none_settings(self):
|
||||
settings = dict(CHARSET=None, TEMPLATE=None)
|
||||
self.check_sql_table_creation_suffix(settings, "")
|
||||
|
||||
def test_sql_table_creation_suffix_with_encoding(self):
|
||||
settings = dict(CHARSET='UTF8')
|
||||
self.check_sql_table_creation_suffix(settings, "WITH ENCODING 'UTF8'")
|
||||
|
||||
def test_sql_table_creation_suffix_with_template(self):
|
||||
settings = dict(TEMPLATE='template0')
|
||||
self.check_sql_table_creation_suffix(settings, 'WITH TEMPLATE "template0"')
|
||||
|
||||
def test_sql_table_creation_suffix_with_encoding_and_template(self):
|
||||
settings = dict(CHARSET='UTF8', TEMPLATE='template0')
|
||||
self.check_sql_table_creation_suffix(settings, '''WITH ENCODING 'UTF8' TEMPLATE "template0"''')
|
||||
|
Loading…
Reference in New Issue
Block a user