summaryrefslogtreecommitdiff
path: root/src/mailman/database/alembic/versions/42756496720_header_matches.py
blob: d1308a134445c674c26f332a9f04bc7f7e8d7091 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
"""header_matches

Revision ID: 42756496720
Revises: 2bb9b382198
Create Date: 2015-09-11 10:11:38.310315

"""

import sqlalchemy as sa

from alembic import op
from mailman.database.helpers import exists_in_db, is_sqlite
from mailman.database.types import SAUnicode

# Revision identifiers, used by Alembic.
revision = '42756496720'
down_revision = '2bb9b382198'


def upgrade():
    # Create the new table
    header_match_table = op.create_table(
        'headermatch',
        sa.Column('id', sa.Integer(), nullable=False),
        sa.Column('mailing_list_id', sa.Integer(), nullable=True),
        sa.Column('header', SAUnicode(), nullable=False),
        sa.Column('pattern', SAUnicode(), nullable=False),
        sa.Column('chain', SAUnicode(), nullable=True),
        sa.ForeignKeyConstraint(['mailing_list_id'], ['mailinglist.id'], ),
        sa.PrimaryKeyConstraint('id')
        )
    # Now migrate the data.  It can't be offline because we need to read the
    # pickles.
    connection = op.get_bind()
    # Don't import the table definition from the models, it may break this
    # migration when the model is updated in the future (see the Alembic doc).
    mlist_table = sa.sql.table(
        'mailinglist',
        sa.sql.column('id', sa.Integer),
        sa.sql.column('header_matches', sa.PickleType)
        )
    for mlist_id, old_matches in connection.execute(mlist_table.select()):
        for old_match in old_matches:
            connection.execute(header_match_table.insert().values(
                mailing_list_id=mlist_id,
                header=old_match[0],
                pattern=old_match[1],
                chain=None
                ))
    # Now that data is migrated, drop the old column (except on SQLite which
    # does not support this)
    if not is_sqlite(connection):
        op.drop_column('mailinglist', 'header_matches')


def downgrade():
    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('header_matches', sa.PickleType, nullable=True))
    # Now migrate the data.  It can't be offline because we need to read the
    # pickles.
    connection = op.get_bind()
    # Don't import the table definition from the models, it may break this
    # migration when the model is updated in the future (see the Alembic doc).
    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', SAUnicode),
        sa.sql.column('pattern', SAUnicode),
        )
    for mlist_id, header, pattern in connection.execute(
            header_match_table.select()).fetchall():
        mlist = connection.execute(mlist_table.select().where(
            mlist_table.c.id == mlist_id)).fetchone()
        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')