Fixed #23649 -- Made Oracle test-db creation drop test-user earlier when needed
Checked database destruction for ORA-29857, which happens when objects of some types are left over in an old test database (notably, such objects are created by the GIS backend). When this happens, we can resolve the issue by dropping the test-user (if we are allowed to). An alternative approach, to just switch the order of creation (so that, if the test user exists and can be dropped, it is always dropped before the tablespace) was considered; but since the user creation depends on the tablespace, this would necessitate separating the dropping of the user from its creation -- a change I am reluctant to make. Thanks Josh Smeaton and Tim Graham for reviews.
This commit is contained in:
parent
babbf18999
commit
2e1ed5f33c
|
@ -75,10 +75,22 @@ class DatabaseCreation(BaseDatabaseCreation):
|
||||||
"It appears the test database, %s, already exists. "
|
"It appears the test database, %s, already exists. "
|
||||||
"Type 'yes' to delete it, or 'no' to cancel: " % parameters['user'])
|
"Type 'yes' to delete it, or 'no' to cancel: " % parameters['user'])
|
||||||
if autoclobber or confirm == 'yes':
|
if autoclobber or confirm == 'yes':
|
||||||
|
if verbosity >= 1:
|
||||||
|
print("Destroying old test database '%s'..." % self.connection.alias)
|
||||||
try:
|
try:
|
||||||
if verbosity >= 1:
|
|
||||||
print("Destroying old test database '%s'..." % self.connection.alias)
|
|
||||||
self._execute_test_db_destruction(cursor, parameters, verbosity)
|
self._execute_test_db_destruction(cursor, parameters, verbosity)
|
||||||
|
except DatabaseError as e:
|
||||||
|
if 'ORA-29857' in str(e):
|
||||||
|
self._handle_objects_preventing_db_destruction(cursor, parameters,
|
||||||
|
verbosity, autoclobber)
|
||||||
|
else:
|
||||||
|
# Ran into a database error that isn't about leftover objects in the tablespace
|
||||||
|
sys.stderr.write("Got an error destroying the old test database: %s\n" % e)
|
||||||
|
sys.exit(2)
|
||||||
|
except Exception as e:
|
||||||
|
sys.stderr.write("Got an error destroying the old test database: %s\n" % e)
|
||||||
|
sys.exit(2)
|
||||||
|
try:
|
||||||
self._execute_test_db_creation(cursor, parameters, verbosity)
|
self._execute_test_db_creation(cursor, parameters, verbosity)
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
sys.stderr.write("Got an error recreating the test database: %s\n" % e)
|
sys.stderr.write("Got an error recreating the test database: %s\n" % e)
|
||||||
|
@ -128,6 +140,41 @@ class DatabaseCreation(BaseDatabaseCreation):
|
||||||
|
|
||||||
return self.connection.settings_dict['NAME']
|
return self.connection.settings_dict['NAME']
|
||||||
|
|
||||||
|
def _handle_objects_preventing_db_destruction(self, cursor, parameters, verbosity, autoclobber):
|
||||||
|
# There are objects in the test tablespace which prevent dropping it
|
||||||
|
# The easy fix is to drop the test user -- but are we allowed to do so?
|
||||||
|
print("There are objects in the old test database which prevent its destruction.")
|
||||||
|
print("If they belong to the test user, deleting the user will allow the test "
|
||||||
|
"database to be recreated.")
|
||||||
|
print("Otherwise, you will need to find and remove each of these objects, "
|
||||||
|
"or use a different tablespace.\n")
|
||||||
|
if self._test_user_create():
|
||||||
|
if not autoclobber:
|
||||||
|
confirm = input("Type 'yes' to delete user %s: " % parameters['user'])
|
||||||
|
if autoclobber or confirm == 'yes':
|
||||||
|
try:
|
||||||
|
if verbosity >= 1:
|
||||||
|
print("Destroying old test user...")
|
||||||
|
self._destroy_test_user(cursor, parameters, verbosity)
|
||||||
|
except Exception as e:
|
||||||
|
sys.stderr.write("Got an error destroying the test user: %s\n" % e)
|
||||||
|
sys.exit(2)
|
||||||
|
try:
|
||||||
|
if verbosity >= 1:
|
||||||
|
print("Destroying old test database '%s'..." % self.connection.alias)
|
||||||
|
self._execute_test_db_destruction(cursor, parameters, verbosity)
|
||||||
|
except Exception as e:
|
||||||
|
sys.stderr.write("Got an error destroying the test database: %s\n" % e)
|
||||||
|
sys.exit(2)
|
||||||
|
else:
|
||||||
|
print("Tests cancelled -- test database cannot be recreated.")
|
||||||
|
sys.exit(1)
|
||||||
|
else:
|
||||||
|
print("Django is configured to use pre-existing test user '%s',"
|
||||||
|
" and will not attempt to delete it.\n" % parameters['user'])
|
||||||
|
print("Tests cancelled -- test database cannot be recreated.")
|
||||||
|
sys.exit(1)
|
||||||
|
|
||||||
def _destroy_test_db(self, test_database_name, verbosity=1):
|
def _destroy_test_db(self, test_database_name, verbosity=1):
|
||||||
"""
|
"""
|
||||||
Destroy a test database, prompting the user for confirmation if the
|
Destroy a test database, prompting the user for confirmation if the
|
||||||
|
|
Loading…
Reference in New Issue