1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 import sqlalchemy as sa
17 import migrate
18 import migrate.versioning.schema
19 import migrate.versioning.repository
20 from twisted.python import util, log
21 from buildbot.db import base
22
23 try:
24 from migrate.versioning import exceptions
25 _hush_pyflakes = exceptions
26 except ImportError:
27 from migrate import exceptions
28
29 -class Model(base.DBConnectorComponent):
30
31
32
33
34 metadata = sa.MetaData()
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54 buildrequests = sa.Table('buildrequests', metadata,
55 sa.Column('id', sa.Integer, primary_key=True),
56 sa.Column('buildsetid', sa.Integer, sa.ForeignKey("buildsets.id"),
57 nullable=False),
58 sa.Column('buildername', sa.String(length=256), nullable=False),
59 sa.Column('priority', sa.Integer, nullable=False,
60 server_default=sa.DefaultClause("0")),
61
62
63 sa.Column('complete', sa.Integer,
64 server_default=sa.DefaultClause("0")),
65
66
67
68 sa.Column('results', sa.SmallInteger),
69
70
71 sa.Column('submitted_at', sa.Integer, nullable=False),
72
73
74 sa.Column('complete_at', sa.Integer),
75 )
76
77
78
79 buildrequest_claims = sa.Table('buildrequest_claims', metadata,
80 sa.Column('brid', sa.Integer, sa.ForeignKey('buildrequests.id'),
81 index=True, unique=True),
82 sa.Column('objectid', sa.Integer, sa.ForeignKey('objects.id'),
83 index=True, nullable=True),
84 sa.Column('claimed_at', sa.Integer, nullable=False),
85 )
86
87
88
89
90
91 builds = sa.Table('builds', metadata,
92 sa.Column('id', sa.Integer, primary_key=True),
93
94
95
96 sa.Column('number', sa.Integer, nullable=False),
97
98 sa.Column('brid', sa.Integer, sa.ForeignKey('buildrequests.id'), nullable=False),
99 sa.Column('start_time', sa.Integer, nullable=False),
100 sa.Column('finish_time', sa.Integer),
101 )
102
103
104
105
106 buildset_properties = sa.Table('buildset_properties', metadata,
107 sa.Column('buildsetid', sa.Integer, sa.ForeignKey('buildsets.id'), nullable=False),
108 sa.Column('property_name', sa.String(256), nullable=False),
109
110 sa.Column('property_value', sa.String(1024), nullable=False),
111 )
112
113
114
115 buildsets = sa.Table('buildsets', metadata,
116 sa.Column('id', sa.Integer, primary_key=True),
117
118
119
120 sa.Column('external_idstring', sa.String(256)),
121
122
123 sa.Column('reason', sa.String(256)),
124 sa.Column('submitted_at', sa.Integer, nullable=False),
125
126
127 sa.Column('complete', sa.SmallInteger, nullable=False, server_default=sa.DefaultClause("0")),
128 sa.Column('complete_at', sa.Integer),
129
130
131
132 sa.Column('results', sa.SmallInteger),
133
134
135 sa.Column('sourcestampsetid', sa.Integer, sa.ForeignKey('sourcestampsets.id')),
136 )
137
138
139
140
141 change_files = sa.Table('change_files', metadata,
142 sa.Column('changeid', sa.Integer, sa.ForeignKey('changes.changeid'), nullable=False),
143 sa.Column('filename', sa.String(1024), nullable=False),
144 )
145
146
147 change_properties = sa.Table('change_properties', metadata,
148 sa.Column('changeid', sa.Integer, sa.ForeignKey('changes.changeid'), nullable=False),
149 sa.Column('property_name', sa.String(256), nullable=False),
150
151 sa.Column('property_value', sa.String(1024), nullable=False),
152 )
153
154
155
156
157 change_users = sa.Table("change_users", metadata,
158 sa.Column("changeid", sa.Integer, sa.ForeignKey('changes.changeid'), nullable=False),
159
160 sa.Column("uid", sa.Integer, sa.ForeignKey('users.uid'), nullable=False)
161 )
162
163
164 changes = sa.Table('changes', metadata,
165
166 sa.Column('changeid', sa.Integer, primary_key=True),
167
168
169 sa.Column('author', sa.String(256), nullable=False),
170
171
172 sa.Column('comments', sa.String(1024), nullable=False),
173
174
175 sa.Column('is_dir', sa.SmallInteger, nullable=False),
176
177
178
179 sa.Column('branch', sa.String(256)),
180
181
182 sa.Column('revision', sa.String(256)),
183
184
185 sa.Column('revlink', sa.String(256)),
186
187
188
189
190 sa.Column('when_timestamp', sa.Integer, nullable=False),
191
192
193 sa.Column('category', sa.String(256)),
194
195
196
197 sa.Column('repository', sa.String(length=512), nullable=False, server_default=''),
198
199
200
201 sa.Column('project', sa.String(length=512), nullable=False, server_default=''),
202 )
203
204
205
206
207 patches = sa.Table('patches', metadata,
208 sa.Column('id', sa.Integer, primary_key=True),
209
210
211 sa.Column('patchlevel', sa.Integer, nullable=False),
212
213
214 sa.Column('patch_base64', sa.Text, nullable=False),
215
216
217 sa.Column('patch_author', sa.Text, nullable=False),
218
219
220 sa.Column('patch_comment', sa.Text, nullable=False),
221
222
223 sa.Column('subdir', sa.Text),
224 )
225
226
227 sourcestamp_changes = sa.Table('sourcestamp_changes', metadata,
228 sa.Column('sourcestampid', sa.Integer, sa.ForeignKey('sourcestamps.id'), nullable=False),
229 sa.Column('changeid', sa.Integer, sa.ForeignKey('changes.changeid'), nullable=False),
230 )
231
232
233
234 sourcestampsets = sa.Table('sourcestampsets', metadata,
235 sa.Column('id', sa.Integer, primary_key=True),
236 )
237
238
239
240
241
242 sourcestamps = sa.Table('sourcestamps', metadata,
243 sa.Column('id', sa.Integer, primary_key=True),
244
245
246
247 sa.Column('branch', sa.String(256)),
248
249
250 sa.Column('revision', sa.String(256)),
251
252
253 sa.Column('patchid', sa.Integer, sa.ForeignKey('patches.id')),
254
255
256 sa.Column('repository', sa.String(length=512), nullable=False, server_default=''),
257
258
259 sa.Column('project', sa.String(length=512), nullable=False, server_default=''),
260
261
262 sa.Column('sourcestampsetid', sa.Integer, sa.ForeignKey('sourcestampsets.id')),
263 )
264
265
266
267
268
269
270
271
272 scheduler_changes = sa.Table('scheduler_changes', metadata,
273 sa.Column('objectid', sa.Integer, sa.ForeignKey('objects.id')),
274 sa.Column('changeid', sa.Integer, sa.ForeignKey('changes.changeid')),
275
276 sa.Column('important', sa.Integer),
277 )
278
279
280
281
282
283 objects = sa.Table("objects", metadata,
284
285 sa.Column("id", sa.Integer, primary_key=True),
286
287 sa.Column('name', sa.String(128), nullable=False),
288
289 sa.Column('class_name', sa.String(128), nullable=False),
290 )
291
292
293
294 object_state = sa.Table("object_state", metadata,
295
296 sa.Column("objectid", sa.Integer, sa.ForeignKey('objects.id'),
297 nullable=False),
298
299 sa.Column("name", sa.String(length=256), nullable=False),
300
301 sa.Column("value_json", sa.Text, nullable=False),
302 )
303
304
305
306
307
308 users = sa.Table("users", metadata,
309
310 sa.Column("uid", sa.Integer, primary_key=True),
311
312
313 sa.Column("identifier", sa.String(256), nullable=False),
314
315
316 sa.Column("bb_username", sa.String(128)),
317
318
319 sa.Column("bb_password", sa.String(128)),
320 )
321
322
323
324 users_info = sa.Table("users_info", metadata,
325
326 sa.Column("uid", sa.Integer, sa.ForeignKey('users.uid'),
327 nullable=False),
328
329
330 sa.Column("attr_type", sa.String(128), nullable=False),
331
332
333 sa.Column("attr_data", sa.String(128), nullable=False),
334 )
335
336
337
338
339 sa.Index('buildrequests_buildsetid', buildrequests.c.buildsetid)
340 sa.Index('buildrequests_buildername', buildrequests.c.buildername)
341 sa.Index('buildrequests_complete', buildrequests.c.complete)
342 sa.Index('builds_number', builds.c.number)
343 sa.Index('builds_brid', builds.c.brid)
344 sa.Index('buildsets_complete', buildsets.c.complete)
345 sa.Index('buildsets_submitted_at', buildsets.c.submitted_at)
346 sa.Index('buildset_properties_buildsetid', buildset_properties.c.buildsetid)
347 sa.Index('changes_branch', changes.c.branch)
348 sa.Index('changes_revision', changes.c.revision)
349 sa.Index('changes_author', changes.c.author)
350 sa.Index('changes_category', changes.c.category)
351 sa.Index('changes_when_timestamp', changes.c.when_timestamp)
352 sa.Index('change_files_changeid', change_files.c.changeid)
353 sa.Index('change_properties_changeid', change_properties.c.changeid)
354 sa.Index('scheduler_changes_objectid', scheduler_changes.c.objectid)
355 sa.Index('scheduler_changes_changeid', scheduler_changes.c.changeid)
356 sa.Index('scheduler_changes_unique', scheduler_changes.c.objectid,
357 scheduler_changes.c.changeid, unique=True)
358 sa.Index('sourcestamp_changes_sourcestampid', sourcestamp_changes.c.sourcestampid)
359 sa.Index('sourcestamps_sourcestampsetid', sourcestamps.c.sourcestampsetid, unique=False)
360 sa.Index('users_identifier', users.c.identifier, unique=True)
361 sa.Index('users_info_uid', users_info.c.uid)
362 sa.Index('users_info_uid_attr_type', users_info.c.uid,
363 users_info.c.attr_type, unique=True)
364 sa.Index('users_info_attrs', users_info.c.attr_type,
365 users_info.c.attr_data, unique=True)
366 sa.Index('change_users_changeid', change_users.c.changeid)
367 sa.Index('users_bb_user', users.c.bb_username, unique=True)
368 sa.Index('object_identity', objects.c.name, objects.c.class_name,
369 unique=True)
370 sa.Index('name_per_object', object_state.c.objectid, object_state.c.name,
371 unique=True)
372
373
374
375
376
377 implied_indexes = [
378 ('change_users',
379 dict(unique=False, column_names=['uid'], name='uid')),
380 ('sourcestamps',
381 dict(unique=False, column_names=['patchid'], name='patchid')),
382 ('sourcestamp_changes',
383 dict(unique=False, column_names=['changeid'], name='changeid')),
384 ('buildsets',
385 dict(unique=False, column_names=['sourcestampsetid'],
386 name='buildsets_sourcestampsetid_fkey')),
387 ]
388
389
390
391
392
393
394
395
396
397
398
399 repo_path = util.sibpath(__file__, "migrate")
400
402 def thd(engine):
403
404
405 repo = migrate.versioning.repository.Repository(self.repo_path)
406 repo_version = repo.latest
407 try:
408
409 schema = migrate.versioning.schema.ControlledSchema(engine, self.repo_path)
410 db_version = schema.version
411 except exceptions.DatabaseNotControlledError:
412 return False
413
414 return db_version == repo_version
415 return self.db.pool.do_with_engine(thd)
416
418
419
420
421
422
423
424
425 def table_exists(engine, tbl):
426 try:
427 r = engine.execute("select * from %s limit 1" % tbl)
428 r.close()
429 return True
430 except:
431 return False
432
433
434
435
436 def upgrade(engine):
437 schema = migrate.versioning.schema.ControlledSchema(engine, self.repo_path)
438 changeset = schema.changeset(None)
439 for version, change in changeset:
440 log.msg('migrating schema version %s -> %d'
441 % (version, version + 1))
442 schema.runchange(version, change, 1)
443
444 def check_sqlalchemy_migrate_version():
445
446
447
448 version = getattr(migrate, '__version__', 'old')
449 if version == 'old':
450 try:
451 from migrate.versioning import schemadiff
452 if hasattr(schemadiff, 'ColDiff'):
453 version = "0.6.1"
454 else:
455 version = "0.6"
456 except:
457 version = "0.0"
458 version_tup = tuple(map(int, version.split('.')))
459 log.msg("using SQLAlchemy-Migrate version %s" % (version,))
460 if version_tup < (0,6,1):
461 raise RuntimeError("You are using SQLAlchemy-Migrate %s. "
462 "The minimum version is 0.6.1." % (version,))
463
464 def version_control(engine, version=None):
465 migrate.versioning.schema.ControlledSchema.create(engine, self.repo_path, version)
466
467
468 def thd(engine):
469
470
471 if table_exists(engine, 'migrate_version'):
472 upgrade(engine)
473
474
475
476
477 elif table_exists(engine, 'version'):
478
479 r = engine.execute("select version from version limit 1")
480 old_version = r.scalar()
481
482
483 version_control(engine, old_version)
484
485
486
487 table = sa.Table('version', self.metadata,
488 sa.Column('x', sa.Integer))
489 table.drop(bind=engine)
490
491
492 self.metadata.remove(table)
493
494
495 upgrade(engine)
496
497
498
499 else:
500 version_control(engine)
501 upgrade(engine)
502
503 check_sqlalchemy_migrate_version()
504 return self.db.pool.do_with_engine(thd)
505
506
507
508
509 try:
510 import migrate.versioning.exceptions as ex1
511 import migrate.changeset.exceptions as ex2
512 ex1.MigrateDeprecationWarning = ex2.MigrateDeprecationWarning
513 except (ImportError,AttributeError):
514 pass
515