#33160: postgresql DatabaseWrapper._nodb_cursor causes confusing/wrong "Django
was
unable to create a connection to the 'postgres' database" warning in case
of errors from queries
-------------------------------------+-------------------------------------
Reporter: Daniel Hahler | Owner: nobody
Type: Bug | Status: new
Component: Database layer | Version: 3.2
(models, ORM) |
Severity: Normal | Resolution:
Keywords: | Triage Stage:
| Unreviewed
Has patch: 1 | Needs documentation: 0
Needs tests: 0 | Patch needs improvement: 0
Easy pickings: 0 | UI/UX: 0
-------------------------------------+-------------------------------------
Description changed by Daniel Hahler:
Old description:
> {{_nodb_cursor}} might cause a confusing/wrong warning, e.g. via
> {{teardown_database}}:
>
> {{{
> [35] …/Vcs/django/django/test/utils.py(313)teardown_databases()
> connection.creation.destroy_test_db(old_name, verbosity, keepdb)
> [36]
> …/Vcs/django/django/db/backends/base/creation.py(282)destroy_test_db()
> self._destroy_test_db(test_database_name, verbosity)
> [37]
> …/Vcs/django/django/db/backends/base/creation.py(298)_destroy_test_db()
> cursor.execute("DROP DATABASE %s"
> [38] /usr/lib/python3.9/contextlib.py(137)__exit__()
> self.gen.throw(typ, value, traceback)
> > [39]
> …/Vcs/django/django/db/backends/postgresql/base.py(306)_nodb_cursor()
> warnings.warn(
> (Pdb++) l
> 301 with super()._nodb_cursor() as cursor:
> 302 yield cursor
> 303 except (Database.DatabaseError, WrappedDatabaseError) as
> exc:
> 304 e = exc
> 305 __import__('pdb').set_trace()
> 306 -> warnings.warn(
> 307 "Normally Django will use a connection to the
> 'postgres' database "
> 308 "to avoid running initialization queries against
> the production "
> 309 "database when it's not needed (for example, when
> running tests). "
> 310 "Django was unable to create a connection to the
> 'postgres' database "
> 311 "and will use the first PostgreSQL database
> instead.",
> (Pdb++) e
> OperationalError('database "test_foo" is being accessed by other
> users\nDETAIL: There is 1 other session using the database.\n')
> }}}
>
> As you can see there is another issue this will (partly) swallow/hide
> then, apart from the message being just wrong: it is not the connection
> that failed, but a query in there:
>
> {{{
> [37] >
> …/django/django/db/backends/base/creation.py(298)_destroy_test_db(), 4
> frames hidden
>
> 289 def _destroy_test_db(self, test_database_name, verbosity):
> 290 """
> 291 Internal implementation - remove the test db tables.
> 292 """
> 293 # Remove the test database to clean up after
> 294 # ourselves. Connect to the previous database (not the
> test database)
> 295 # to do so, because it's not allowed to delete a database
> while being
> 296 # connected to it.
> 297 with self._nodb_cursor() as cursor:
> 298 -> cursor.execute("DROP DATABASE %s"
> 299 %
> self.connection.ops.quote_name(test_database_name))
> }}}
>
> Only {{connect()} should get wrapped/handled in {{_nodb_cursor}} probably
> (in terms of adding the warning), which could be achieved by handling
> specific exceptions only, or re-raising it in case a {{cursor}} was used
> (i.e. it could connect).
New description:
{{_nodb_cursor}} might cause a confusing/wrong warning, e.g. via
{{teardown_database}}:
{{{
[35] …/Vcs/django/django/test/utils.py(313)teardown_databases()
connection.creation.destroy_test_db(old_name, verbosity, keepdb)
[36]
…/Vcs/django/django/db/backends/base/creation.py(282)destroy_test_db()
self._destroy_test_db(test_database_name, verbosity)
[37]
…/Vcs/django/django/db/backends/base/creation.py(298)_destroy_test_db()
cursor.execute("DROP DATABASE %s"
[38] /usr/lib/python3.9/contextlib.py(137)__exit__()
self.gen.throw(typ, value, traceback)
> [39]
…/Vcs/django/django/db/backends/postgresql/base.py(306)_nodb_cursor()
warnings.warn(
(Pdb++) l
301 with super()._nodb_cursor() as cursor:
302 yield cursor
303 except (Database.DatabaseError, WrappedDatabaseError) as
exc:
304 e = exc
305 __import__('pdb').set_trace()
306 -> warnings.warn(
307 "Normally Django will use a connection to the
'postgres' database "
308 "to avoid running initialization queries against
the production "
309 "database when it's not needed (for example, when
running tests). "
310 "Django was unable to create a connection to the
'postgres' database "
311 "and will use the first PostgreSQL database
instead.",
(Pdb++) e
OperationalError('database "test_foo" is being accessed by other
users\nDETAIL: There is 1 other session using the database.\n')
}}}
As you can see there is another issue this will (partly) swallow/hide
then, apart from the message being just wrong: it is not the connection
that failed, but a query in there:
{{{
[37] >
…/django/django/db/backends/base/creation.py(298)_destroy_test_db(), 4
frames hidden
289 def _destroy_test_db(self, test_database_name, verbosity):
290 """
291 Internal implementation - remove the test db tables.
292 """
293 # Remove the test database to clean up after
294 # ourselves. Connect to the previous database (not the
test database)
295 # to do so, because it's not allowed to delete a database
while being
296 # connected to it.
297 with self._nodb_cursor() as cursor:
298 -> cursor.execute("DROP DATABASE %s"
299 %
self.connection.ops.quote_name(test_database_name))
}}}
Only {{connect()} should get wrapped/handled in {{_nodb_cursor}} probably
(in terms of adding the warning), which could be achieved by handling
specific exceptions only, or re-raising it in case a {{cursor}} was used
(i.e. it could connect).
Possible fix: https://github.com/django/django/pull/14918
--
--
Ticket URL: <https://code.djangoproject.com/ticket/33160#comment:2>
Django <https://code.djangoproject.com/>
The Web framework for perfectionists with deadlines.
--
You received this message because you are subscribed to the Google Groups
"Django updates" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To view this discussion on the web visit
https://groups.google.com/d/msgid/django-updates/065.c6c9de466c9be9d58cc7d9e75793805d%40djangoproject.com.