diff options
-rw-r--r-- | mediagoblin/db/base.py | 26 | ||||
-rw-r--r-- | mediagoblin/db/migrations/versions/101510e3a713_removes_graveyard_items_from_.py | 84 |
2 files changed, 110 insertions, 0 deletions
diff --git a/mediagoblin/db/base.py b/mediagoblin/db/base.py index 11afbcec..af2337df 100644 --- a/mediagoblin/db/base.py +++ b/mediagoblin/db/base.py @@ -92,6 +92,31 @@ class GMGTableBase(object): if deletion is None: deletion = self.deletion_mode + # If the item is in any collection then it should be removed, this will + # cause issues if it isn't. See #5382. + # Import here to prevent cyclic imports. + from mediagoblin.db.models import CollectionItem, GenericModelReference + + # Some of the models don't have an "id" field which means they can't be + # used with GMR, these models won't be in collections because they + # can't be. We can skip all of this. + if hasattr(self, "id"): + # First find the GenericModelReference for this object + gmr = GenericModelReference.query.filter_by( + obj_pk=self.id, + model_type=self.__tablename__ + ).first() + + # If there is no gmr then we've got lucky, a GMR is a requirement of + # being in a collection. + if gmr is not None: + items = CollectionItem.query.filter_by( + object_id=gmr.id + ) + + # Delete any CollectionItems found. + items.delete() + # Hand off to the correct deletion function. if deletion == self.HARD_DELETE: return self.hard_delete(commit=commit) @@ -132,6 +157,7 @@ class GMGTableBase(object): "model_type": tombstone.__tablename__, }) + # Now we can go ahead and actually delete the model. return self.hard_delete(commit=commit) diff --git a/mediagoblin/db/migrations/versions/101510e3a713_removes_graveyard_items_from_.py b/mediagoblin/db/migrations/versions/101510e3a713_removes_graveyard_items_from_.py new file mode 100644 index 00000000..d730e808 --- /dev/null +++ b/mediagoblin/db/migrations/versions/101510e3a713_removes_graveyard_items_from_.py @@ -0,0 +1,84 @@ +"""#5382 Removes graveyard items from collections + +Revision ID: 101510e3a713 +Revises: 52bf0ccbedc1 +Create Date: 2016-01-12 10:46:26.486610 + +""" + +# revision identifiers, used by Alembic. +revision = '101510e3a713' +down_revision = '52bf0ccbedc1' + +from alembic import op + +import sqlalchemy as sa +from sqlalchemy.sql import and_ + +# Create the tables to query +gmr_table = sa.Table( + "core__generic_model_reference", + sa.MetaData(), + sa.Column("id", sa.Integer, primary_key=True), + sa.Column("obj_pk", sa.Integer), + sa.Column("model_type", sa.Unicode) +) + +graveyard_table = sa.Table( + "core__graveyard", + sa.MetaData(), + sa.Column("id", sa.Integer, primary_key=True), + sa.Column("public_id", sa.Unicode, unique=True), + sa.Column("deleted", sa.DateTime, nullable=False), + sa.Column("object_type", sa.Unicode, nullable=False), + sa.Column("actor_id", sa.Integer) +) + +collection_items_table = sa.Table( + "core__collection_items", + sa.MetaData(), + sa.Column("id", sa.Integer, primary_key=True), + sa.Column("collection", sa.Integer, nullable=False), + sa.Column("note", sa.UnicodeText), + sa.Column("added", sa.DateTime, nullable=False), + sa.Column("position", sa.Integer), + sa.Column("object_id", sa.Integer, index=True) +) + +def upgrade(): + """ + The problem is deletions are occuring and as we expect the + GenericModelReference objects are being updated to point to the tombstone + object. The issue is that collections now contain deleted items, this + causes problems when it comes to rendering them for example. + + This migration is to remove any Graveyard objects (tombstones) from any + Collection. + """ + connection = op.get_bind() + + for tombstone in connection.execute(graveyard_table.select()): + # Get GMR for tombstone + gmr = connection.execute(gmr_table.select().where(and_( + gmr_table.c.obj_pk == tombstone.id, + gmr_table.c.model_type == "core__graveyard" + ))).first() + + # If there is no GMR, we're all good as it's required to be in a + # collection + if gmr is None: + continue + + # Delete all the CollectionItem objects for this GMR + connection.execute(collection_items_table.delete().where( + collection_items_table.c.object_id == gmr.id + )) + + +def downgrade(): + """ + Nothing to do here, the migration just deletes objects from collections. + There are no schema changes that have occured. This can be reverted without + any problems. + """ + pass |