Explorar o código

Fixed #29613 -- Fixed --keepdb on PostgreSQL if the database exists and the user can't create databases.

Regression in e776dd2db677d58dcb50aea20d3bb191537df25b.

Thanks Tim Graham for the review.
Mariusz Felisiak %!s(int64=6) %!d(string=hai) anos
pai
achega
1a9cbf41a1

+ 9 - 0
django/db/backends/postgresql/creation.py

@@ -3,6 +3,7 @@ import sys
 from psycopg2 import errorcodes
 
 from django.db.backends.base.creation import BaseDatabaseCreation
+from django.db.backends.utils import strip_quotes
 
 
 class DatabaseCreation(BaseDatabaseCreation):
@@ -28,8 +29,16 @@ class DatabaseCreation(BaseDatabaseCreation):
             template=test_settings.get('TEMPLATE'),
         )
 
+    def _database_exists(self, cursor, database_name):
+        cursor.execute('SELECT 1 FROM pg_catalog.pg_database WHERE datname = %s', [strip_quotes(database_name)])
+        return cursor.fetchone() is not None
+
     def _execute_create_test_db(self, cursor, parameters, keepdb=False):
         try:
+            if keepdb and self._database_exists(cursor, parameters['dbname']):
+                # If the database should be kept and it already exists, don't
+                # try to create a new one.
+                return
             super()._execute_create_test_db(cursor, parameters, keepdb)
         except Exception as e:
             if getattr(e.__cause__, 'pgcode', '') != errorcodes.DUPLICATE_DATABASE:

+ 4 - 0
docs/releases/2.1.1.txt

@@ -14,3 +14,7 @@ Bugfixes
 
 * Fixed a regression where ``QueryDict.urlencode()`` crashed if the dictionary
   contains a non-string value (:ticket:`29627`).
+
+* Fixed a regression in Django 2.0 where using ``manage.py test --keepdb``
+  fails on PostgreSQL if the database exists and the user doesn't have
+  permission to create databases (:ticket:`29613`).

+ 10 - 3
tests/backends/postgresql/test_creation.py

@@ -89,7 +89,14 @@ class DatabaseCreationTests(SimpleTestCase):
             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 self.assertRaises(SystemExit):
-                creation._create_test_db(verbosity=0, autoclobber=False, keepdb=False)
-            with self.assertRaises(SystemExit):
+            with mock.patch.object(DatabaseCreation, '_database_exists', return_value=False):
+                with self.assertRaises(SystemExit):
+                    creation._create_test_db(verbosity=0, autoclobber=False, keepdb=False)
+                with self.assertRaises(SystemExit):
+                    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):
                 creation._create_test_db(verbosity=0, autoclobber=False, keepdb=True)