Merge "Fix for FK constraint violation"
This commit is contained in:
commit
3d52684346
@ -1322,6 +1322,35 @@ def purge_deleted_rows(context, age_in_days, max_rows, session=None):
|
||||
continue
|
||||
if hasattr(model_class, 'deleted'):
|
||||
tables.append(model_class.__tablename__)
|
||||
|
||||
# First force purging of records that are not soft deleted but
|
||||
# are referencing soft deleted tasks/images records (e.g. task_info
|
||||
# records). Then purge all soft deleted records in glance tables in the
|
||||
# right order to avoid FK constraint violation.
|
||||
t = Table("tasks", metadata, autoload=True)
|
||||
ti = Table("task_info", metadata, autoload=True)
|
||||
joined_rec = ti.join(t, t.c.id == ti.c.task_id)
|
||||
deleted_task_info = sql.select([ti.c.task_id],
|
||||
t.c.deleted_at < deleted_age).\
|
||||
select_from(joined_rec).order_by(t.c.deleted_at).limit(max_rows)
|
||||
delete_statement = DeleteFromSelect(ti, deleted_task_info,
|
||||
ti.c.task_id)
|
||||
LOG.info(_LI('Purging deleted rows older than %(age_in_days)d day(s) '
|
||||
'from table %(tbl)s'),
|
||||
{'age_in_days': age_in_days, 'tbl': ti})
|
||||
try:
|
||||
with session.begin():
|
||||
result = session.execute(delete_statement)
|
||||
except (db_exception.DBError, db_exception.DBReferenceError) as ex:
|
||||
LOG.exception(_LE('DBError detected when force purging '
|
||||
'table=%(table)s: %(error)s'),
|
||||
{'table': ti, 'error': six.text_type(ex)})
|
||||
raise
|
||||
|
||||
rows = result.rowcount
|
||||
LOG.info(_LI('Deleted %(rows)d row(s) from table %(tbl)s'),
|
||||
{'rows': rows, 'tbl': ti})
|
||||
|
||||
# get rid of FK constraints
|
||||
for tbl in ('images', 'tasks'):
|
||||
try:
|
||||
|
@ -1946,6 +1946,7 @@ class DBPurgeTests(test_utils.BaseTestCase):
|
||||
self.adm_context = context.get_admin_context(show_deleted=True)
|
||||
self.db_api = db_tests.get_db(self.config)
|
||||
db_tests.reset_db(self.db_api)
|
||||
self.context = context.RequestContext(is_admin=True)
|
||||
self.image_fixtures, self.task_fixtures = self.build_fixtures()
|
||||
self.create_tasks(self.task_fixtures)
|
||||
self.create_images(self.image_fixtures)
|
||||
@ -2079,6 +2080,29 @@ class DBPurgeTests(test_utils.BaseTestCase):
|
||||
images_rows = session.query(images).count()
|
||||
self.assertEqual(4, images_rows)
|
||||
|
||||
def test_purge_task_info_with_refs_to_soft_deleted_tasks(self):
|
||||
session = db_api.get_session()
|
||||
engine = db_api.get_engine()
|
||||
|
||||
# check initial task and task_info row number are 3
|
||||
tasks = self.db_api.task_get_all(self.adm_context)
|
||||
self.assertEqual(3, len(tasks))
|
||||
|
||||
task_info = sqlalchemyutils.get_table(engine, 'task_info')
|
||||
task_info_rows = session.query(task_info).count()
|
||||
self.assertEqual(3, task_info_rows)
|
||||
|
||||
# purge soft deleted rows older than yesterday
|
||||
self.db_api.purge_deleted_rows(self.context, 1, 5)
|
||||
|
||||
# check 1 row of task table is purged
|
||||
tasks = self.db_api.task_get_all(self.adm_context)
|
||||
self.assertEqual(2, len(tasks))
|
||||
|
||||
# and no task_info was left behind, 1 row purged
|
||||
task_info_rows = session.query(task_info).count()
|
||||
self.assertEqual(2, task_info_rows)
|
||||
|
||||
|
||||
class TestVisibility(test_utils.BaseTestCase):
|
||||
def setUp(self):
|
||||
|
Loading…
Reference in New Issue
Block a user