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