summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/mailman/database/alembic/versions/42756496720_header_matches.py20
-rw-r--r--src/mailman/database/tests/test_migrations.py44
2 files changed, 57 insertions, 7 deletions
diff --git a/src/mailman/database/alembic/versions/42756496720_header_matches.py b/src/mailman/database/alembic/versions/42756496720_header_matches.py
index f79b02b86..83a1275a2 100644
--- a/src/mailman/database/alembic/versions/42756496720_header_matches.py
+++ b/src/mailman/database/alembic/versions/42756496720_header_matches.py
@@ -10,9 +10,11 @@ Create Date: 2015-09-11 10:11:38.310315
revision = '42756496720'
down_revision = '2bb9b382198'
-from alembic import op
import sqlalchemy as sa
+from alembic import op
+from mailman.database.helpers import is_sqlite, exists_in_db
+
def upgrade():
# Create the new table
@@ -46,12 +48,12 @@ def upgrade():
# Now that data is migrated, drop the old column (except on SQLite which
# does not support this)
- if op.get_bind().dialect.name != 'sqlite':
+ if not is_sqlite(connection):
op.drop_column('mailinglist', 'header_matches')
def downgrade():
- if op.get_bind().dialect.name != 'sqlite':
+ if not exists_in_db(op.get_bind(), 'mailinglist', 'header_matches'):
# SQLite will not have deleted the former column, since it does not
# support column deletion.
op.add_column('mailinglist', sa.Column(
@@ -72,11 +74,15 @@ def downgrade():
sa.sql.column('pattern', sa.Unicode),
)
for mlist_id, header, pattern in connection.execute(
- header_match_table.select()):
+ header_match_table.select()).fetchall():
mlist = connection.execute(mlist_table.select().where(
mlist_table.c.id == mlist_id)).fetchone()
- if not mlist["header_matches"]:
- mlist["header_matches"] = []
- mlist["header_matches"].append((header, pattern))
+ header_matches = mlist['header_matches']
+ if not header_matches:
+ header_matches = []
+ header_matches.append((header, pattern))
+ connection.execute(mlist_table.update().where(
+ mlist_table.c.id == mlist_id).values(
+ header_matches=header_matches))
op.drop_table('headermatch')
diff --git a/src/mailman/database/tests/test_migrations.py b/src/mailman/database/tests/test_migrations.py
index 98d8deb79..d54c525ea 100644
--- a/src/mailman/database/tests/test_migrations.py
+++ b/src/mailman/database/tests/test_migrations.py
@@ -28,6 +28,7 @@ import sqlalchemy as sa
from mailman.config import config
from mailman.database.alembic import alembic_cfg
+from mailman.database.helpers import exists_in_db
from mailman.database.model import Model
from mailman.testing.layers import ConfigLayer
@@ -41,8 +42,17 @@ class TestMigrations(unittest.TestCase):
def tearDown(self):
# Drop and restore a virgin database.
+ config.db.store.rollback()
md = sa.MetaData(bind=config.db.engine)
md.reflect()
+ # We have circular dependencies between user and address, thus we can't
+ # use drop_all() without getting a warning. Setting use_alter to True
+ # on the foreign keys helps SQLAlchemy mark those loops as known.
+ for tablename in ("user", "address"):
+ if tablename not in md.tables:
+ continue
+ for fk in md.tables[tablename].foreign_key_constraints:
+ fk.use_alter = True
md.drop_all()
Model.metadata.create_all(config.db.engine)
@@ -55,3 +65,37 @@ class TestMigrations(unittest.TestCase):
revisions.reverse()
for revision in revisions:
alembic.command.upgrade(alembic_cfg, revision)
+
+ def test_42756496720_header_matches(self):
+ test_header_matches = [
+ ('test-header-1', 'test-pattern-1'),
+ ('test-header-2', 'test-pattern-2'),
+ ('test-header-3', 'test-pattern-3'),
+ ]
+ mlist_table = sa.sql.table('mailinglist',
+ sa.sql.column('id', sa.Integer),
+ sa.sql.column('header_matches', sa.PickleType)
+ )
+ header_match_table = sa.sql.table('headermatch',
+ sa.sql.column('mailing_list_id', sa.Integer),
+ sa.sql.column('header', sa.Unicode),
+ sa.sql.column('pattern', sa.Unicode),
+ )
+ # Downgrading
+ config.db.store.execute(mlist_table.insert().values(id=1))
+ config.db.store.execute(header_match_table.insert().values(
+ [{'mailing_list_id': 1, 'header': hm[0], 'pattern': hm[1]}
+ for hm in test_header_matches]))
+ config.db.store.commit()
+ alembic.command.downgrade(alembic_cfg, '2bb9b382198')
+ results = config.db.store.execute(
+ mlist_table.select()).fetchall()
+ self.assertEqual(results[0].header_matches, test_header_matches)
+ self.assertFalse(exists_in_db(config.db.engine, 'headermatch'))
+ config.db.store.commit()
+ # Upgrading
+ alembic.command.upgrade(alembic_cfg, '42756496720')
+ results = config.db.store.execute(
+ header_match_table.select()).fetchall()
+ self.assertEqual(results,
+ [(1, hm[0], hm[1]) for hm in test_header_matches])