1 # GNU MediaGoblin -- federated, autonomous media hosting
2 # Copyright (C) 2012, 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 (
20 Table
, Column
, MetaData
,
21 Integer
, Float
, Unicode
, UnicodeText
, DateTime
, Boolean
,
22 ForeignKey
, UniqueConstraint
, PickleType
)
23 from sqlalchemy
.ext
.declarative
import declarative_base
24 from sqlalchemy
.sql
import select
, insert
25 from migrate
import changeset
27 from mediagoblin
.db
.sql
.base
import GMGTableBase
30 # This one will get filled with local migrations
34 #######################################################
35 # Migration set 1: Define initial models, no migrations
36 #######################################################
38 Base1
= declarative_base(cls
=GMGTableBase
)
40 class Creature1(Base1
):
41 __tablename__
= "creature"
43 id = Column(Integer
, primary_key
=True)
44 name
= Column(Unicode
, unique
=True, nullable
=False, index
=True)
45 num_legs
= Column(Integer
, nullable
=False)
46 is_demon
= Column(Boolean
)
49 __tablename__
= "level"
51 id = Column(Integer
, primary_key
=True)
52 name
= Column(Unicode
, unique
=True, nullable
=False, index
=True)
53 description
= Column(UnicodeText
)
54 exits
= Column(PickleType
)
56 SET1_MODELS
= [Creature1
, Level1
]
60 #######################################################
61 # Migration set 2: A few migrations and new model
62 #######################################################
64 Base2
= declarative_base(cls
=GMGTableBase
)
66 class Creature2(Base2
):
67 __tablename__
= "creature"
69 id = Column(Integer
, primary_key
=True)
70 name
= Column(Unicode
, unique
=True, nullable
=False, index
=True)
71 num_legs
= Column(Integer
, nullable
=False)
73 class CreaturePower2(Base2
):
74 __tablename__
= "creature_power"
76 id = Column(Integer
, primary_key
=True)
78 Integer
, ForeignKey('creature.id'), nullable
=False)
79 name
= Column(Unicode
)
80 description
= Column(Unicode
)
81 hitpower
= Column(Integer
, nullable
=False)
84 __tablename__
= "level"
86 id = Column(Integer
, primary_key
=True)
87 name
= Column(Unicode
)
88 description
= Column(UnicodeText
)
90 class LevelExit2(Base2
):
91 __tablename__
= "level_exit"
93 id = Column(Integer
, primary_key
=True)
94 name
= Column(Unicode
)
96 Integer
, ForeignKey('level.id'), nullable
=False)
98 Integer
, ForeignKey('level.id'), nullable
=False)
100 SET2_MODELS
= [Creature2
, CreaturePower2
, Level2
, LevelExit2
]
103 @RegisterMigration(1, FULL_MIGRATIONS
)
104 def creature_remove_is_demon(db_conn
):
105 metadata
= MetaData(bind
=db_conn
.engine
)
106 creature_table
= Table(
107 'creature', metadata
,
108 autoload
=True, autoload_with
=db_conn
.engine
)
109 creature_table
.drop_column('is_demon')
112 @RegisterMigration(2, FULL_MIGRATIONS
)
113 def creature_powers_new_table(db_conn
):
114 metadata
= MetaData(bind
=db_conn
.engine
)
115 creature_powers
= Table(
116 'creature_power', metadata
,
117 Column('id', Integer
, primary_key
=True),
119 Integer
, ForeignKey('creature.id'), nullable
=False),
120 Column('name', Unicode
),
121 Column('description', Unicode
),
122 Column('hitpower', Integer
, nullable
=False))
123 metadata
.create_all(db_conn
.engine
)
126 @RegisterMigration(3, FULL_MIGRATIONS
)
127 def level_exits_new_table(db_conn
):
128 # First, create the table
129 # -----------------------
130 metadata
= MetaData(bind
=db_conn
.engine
)
132 'level_exit', metadata
,
133 Column('id', Integer
, primary_key
=True),
134 Column('name', Unicode
),
136 Integer
, ForeignKey('level.id'), nullable
=False),
138 Integer
, ForeignKey('level.id'), nullable
=False))
139 metadata
.create_all(db_conn
.engine
)
141 # And now, convert all the old exit pickles to new level exits
142 # ------------------------------------------------------------
144 # Minimal representation of level table.
145 # Not auto-introspecting here because of pickle table. I'm not
146 # sure sqlalchemy can auto-introspect pickle columns.
149 Column('id', Integer
, primary_key
=True),
150 Column('exits', PickleType
))
152 # query over and insert
153 result
= db_conn
.execute(
154 select([levels
], levels
.c
.exits
!=None))
157 this_exit
= level
['exits']
159 # Insert the level exit
161 level_exits
.insert().values(
162 name
=this_exit
['name'],
163 from_level
=this_exit
['from_level'],
164 to_level
=this_exit
['to_level']))
166 # Finally, drop the old level exits pickle table
167 # ----------------------------------------------
168 levels
.drop_column('exits')
171 # A hack! At this point we freeze-fame and get just a partial list of
174 SET2_MIGRATIONS
= copy
.copy(FULL_MIGRATIONS
)
176 #######################################################
177 # Migration set 3: Final migrations
178 #######################################################
180 Base3
= declarative_base(cls
=GMGTableBase
)
182 class Creature3(Base3
):
183 __tablename__
= "creature"
185 id = Column(Integer
, primary_key
=True)
186 name
= Column(Unicode
, unique
=True, nullable
=False, index
=True)
187 num_limbs
= Column(Integer
, nullable
=False)
189 class CreaturePower3(Base3
):
190 __tablename__
= "creature_power"
192 id = Column(Integer
, primary_key
=True)
194 Integer
, ForeignKey('creature.id'), nullable
=False, index
=True)
195 name
= Column(Unicode
)
196 description
= Column(Unicode
)
197 hitpower
= Column(Float
, nullable
=False)
200 __tablename__
= "level"
202 id = Column(Integer
, primary_key
=True)
203 name
= Column(Unicode
)
204 description
= Column(UnicodeText
)
206 class LevelExit3(Base3
):
207 __tablename__
= "level_exit"
209 id = Column(Integer
, primary_key
=True)
210 name
= Column(Unicode
)
212 Integer
, ForeignKey('level.id'), nullable
=False, index
=True)
214 Integer
, ForeignKey('level.id'), nullable
=False, index
=True)
217 SET3_MODELS
= [Creature3
, CreaturePower3
, Level3
, LevelExit3
]
220 @RegisterMigration(4, FULL_MIGRATIONS
)
221 def creature_num_legs_to_num_limbs(db_conn
):
224 @RegisterMigration(5, FULL_MIGRATIONS
)
225 def level_exit_index_from_and_to_level(db_conn
):
228 @RegisterMigration(6, FULL_MIGRATIONS
)
229 def creature_power_index_creature(db_conn
):
232 @RegisterMigration(7, FULL_MIGRATIONS
)
233 def creature_power_hitpower_to_float(db_conn
):