1 # GNU MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2011, 2012 MediaGoblin contributors. See AUTHORS.
4 # This program is free software: you can redistribute it and/or modify
5 # it under the terms of the GNU Affero General Public License as published by
6 # the Free Software Foundation, either version 3 of the License, or
7 # (at your option) any later version.
9 # This program is distributed in the hope that it will be useful,
10 # but WITHOUT ANY WARRANTY; without even the implied warranty of
11 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 # GNU Affero General Public License for more details.
14 # You should have received a copy of the GNU Affero General Public License
15 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 from sqlalchemy
import (MetaData
, Table
, Column
, Boolean
, SmallInteger
,
20 Integer
, Unicode
, UnicodeText
, DateTime
,
22 from sqlalchemy
.exc
import ProgrammingError
23 from sqlalchemy
.ext
.declarative
import declarative_base
24 from migrate
.changeset
.constraint
import UniqueConstraint
26 from mediagoblin
.db
.migration_tools
import RegisterMigration
, inspect_table
27 from mediagoblin
.db
.models
import MediaEntry
, Collection
, User
32 @RegisterMigration(1, MIGRATIONS
)
33 def ogg_to_webm_audio(db_conn
):
34 metadata
= MetaData(bind
=db_conn
.bind
)
36 file_keynames
= Table('core__file_keynames', metadata
, autoload
=True,
37 autoload_with
=db_conn
.bind
)
40 file_keynames
.update().where(file_keynames
.c
.name
== 'ogg').
41 values(name
='webm_audio')
46 @RegisterMigration(2, MIGRATIONS
)
47 def add_wants_notification_column(db_conn
):
48 metadata
= MetaData(bind
=db_conn
.bind
)
50 users
= Table('core__users', metadata
, autoload
=True,
51 autoload_with
=db_conn
.bind
)
53 col
= Column('wants_comment_notification', Boolean
,
54 default
=True, nullable
=True)
55 col
.create(users
, populate_defaults
=True)
59 @RegisterMigration(3, MIGRATIONS
)
60 def add_transcoding_progress(db_conn
):
61 metadata
= MetaData(bind
=db_conn
.bind
)
63 media_entry
= inspect_table(metadata
, 'core__media_entries')
65 col
= Column('transcoding_progress', SmallInteger
)
66 col
.create(media_entry
)
70 class Collection_v0(declarative_base()):
71 __tablename__
= "core__collections"
73 id = Column(Integer
, primary_key
=True)
74 title
= Column(Unicode
, nullable
=False)
75 slug
= Column(Unicode
)
76 created
= Column(DateTime
, nullable
=False, default
=datetime
.datetime
.now
,
78 description
= Column(UnicodeText
)
79 creator
= Column(Integer
, ForeignKey(User
.id), nullable
=False)
80 items
= Column(Integer
, default
=0)
82 class CollectionItem_v0(declarative_base()):
83 __tablename__
= "core__collection_items"
85 id = Column(Integer
, primary_key
=True)
87 Integer
, ForeignKey(MediaEntry
.id), nullable
=False, index
=True)
88 collection
= Column(Integer
, ForeignKey(Collection
.id), nullable
=False)
89 note
= Column(UnicodeText
, nullable
=True)
90 added
= Column(DateTime
, nullable
=False, default
=datetime
.datetime
.now
)
91 position
= Column(Integer
)
93 ## This should be activated, normally.
94 ## But this would change the way the next migration used to work.
95 ## So it's commented for now.
97 UniqueConstraint('collection', 'media_entry'),
100 collectionitem_unique_constraint_done
= False
102 @RegisterMigration(4, MIGRATIONS
)
103 def add_collection_tables(db_conn
):
104 Collection_v0
.__table__
.create(db_conn
.bind
)
105 CollectionItem_v0
.__table__
.create(db_conn
.bind
)
107 global collectionitem_unique_constraint_done
108 collectionitem_unique_constraint_done
= True
113 @RegisterMigration(5, MIGRATIONS
)
114 def add_mediaentry_collected(db_conn
):
115 metadata
= MetaData(bind
=db_conn
.bind
)
117 media_entry
= inspect_table(metadata
, 'core__media_entries')
119 col
= Column('collected', Integer
, default
=0)
120 col
.create(media_entry
)
124 class ProcessingMetaData_v0(declarative_base()):
125 __tablename__
= 'core__processing_metadata'
127 id = Column(Integer
, primary_key
=True)
128 media_entry_id
= Column(Integer
, ForeignKey(MediaEntry
.id), nullable
=False,
130 callback_url
= Column(Unicode
)
132 @RegisterMigration(6, MIGRATIONS
)
133 def create_processing_metadata_table(db
):
134 ProcessingMetaData_v0
.__table__
.create(db
.bind
)
138 # Okay, problem being:
139 # Migration #4 forgot to add the uniqueconstraint for the
140 # new tables. While creating the tables from scratch had
141 # the constraint enabled.
143 # So we have four situations that should end up at the same
147 # Well, easy. Just uses the tables in models.py
148 # 2. Fresh install using a git version just before this migration
149 # The tables are all there, the unique constraint is also there.
150 # This migration should do nothing.
151 # But as we can't detect the uniqueconstraint easily,
152 # this migration just adds the constraint again.
153 # And possibly fails very loud. But ignores the failure.
154 # 3. old install, not using git, just releases.
155 # This one will get the new tables in #4 (now with constraint!)
156 # And this migration is just skipped silently.
157 # 4. old install, always on latest git.
158 # This one has the tables, but lacks the constraint.
159 # So this migration adds the constraint.
160 @RegisterMigration(7, MIGRATIONS
)
161 def fix_CollectionItem_v0_constraint(db_conn
):
162 """Add the forgotten Constraint on CollectionItem"""
164 global collectionitem_unique_constraint_done
165 if collectionitem_unique_constraint_done
:
166 # Reset it. Maybe the whole thing gets run again
167 # For a different db?
168 collectionitem_unique_constraint_done
= False
171 metadata
= MetaData(bind
=db_conn
.bind
)
173 CollectionItem_table
= inspect_table(metadata
, 'core__collection_items')
175 constraint
= UniqueConstraint('collection', 'media_entry',
176 name
='core__collection_items_collection_media_entry_key',
177 table
=CollectionItem_table
)
181 except ProgrammingError
:
182 # User probably has an install that was run since the
183 # collection tables were added, so we don't need to run this migration.