Package buildbot :: Package db :: Package schema :: Module v4
[frames] | no frames]

Source Code for Module buildbot.db.schema.v4

  1  # This file is part of Buildbot.  Buildbot is free software: you can 
  2  # redistribute it and/or modify it under the terms of the GNU General Public 
  3  # License as published by the Free Software Foundation, version 2. 
  4  # 
  5  # This program is distributed in the hope that it will be useful, but WITHOUT 
  6  # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS 
  7  # FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more 
  8  # details. 
  9  # 
 10  # You should have received a copy of the GNU General Public License along with 
 11  # this program; if not, write to the Free Software Foundation, Inc., 51 
 12  # Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. 
 13  # 
 14  # Copyright Buildbot Team Members 
 15   
 16  from buildbot.db.schema import base 
 17   
18 -class Upgrader(base.Upgrader):
19 - def upgrade(self):
20 self.migrate_buildrequests() 21 self.migrate_builds() 22 self.migrate_buildsets() 23 self.migrate_changes() 24 self.migrate_patches() 25 self.migrate_sourcestamps() 26 self.migrate_schedulers() 27 self.set_version()
28
29 - def makeAutoincColumn(self, name):
30 if self.dbapiName == 'MySQLdb': 31 return "`%s` INTEGER PRIMARY KEY AUTO_INCREMENT" % name 32 elif self.dbapiName in ('sqlite3', 'pysqlite2.dbapi2'): 33 return "`%s` INTEGER PRIMARY KEY AUTOINCREMENT" % name 34 raise ValueError("Unsupported dbapi: %s" % self.dbapiName)
35
36 - def migrate_table(self, table_name, schema):
37 names = { 38 'old_name': "%s_old" % table_name, 39 'table_name': table_name, 40 } 41 cursor = self.conn.cursor() 42 # If this fails, there's no cleaning up to do 43 cursor.execute(""" 44 ALTER TABLE %(table_name)s 45 RENAME TO %(old_name)s 46 """ % names) 47 48 try: 49 cursor.execute(schema) 50 except: 51 # Restore the original table 52 cursor.execute(""" 53 ALTER TABLE %(old_name)s 54 RENAME TO %(table_name)s 55 """ % names) 56 raise 57 58 try: 59 cursor.execute(""" 60 INSERT INTO %(table_name)s 61 SELECT * FROM %(old_name)s 62 """ % names) 63 cursor.execute(""" 64 DROP TABLE %(old_name)s 65 """ % names) 66 except: 67 # Clean up the new table, and restore the original 68 cursor.execute(""" 69 DROP TABLE %(table_name)s 70 """ % names) 71 cursor.execute(""" 72 ALTER TABLE %(old_name)s 73 RENAME TO %(table_name)s 74 """ % names) 75 raise
76
77 - def set_version(self):
78 c = self.conn.cursor() 79 c.execute("""UPDATE version set version = 4 where version = 3""")
80
81 - def migrate_schedulers(self):
82 schedulerid_col = self.makeAutoincColumn('schedulerid') 83 schema = """ 84 CREATE TABLE schedulers ( 85 %(schedulerid_col)s, -- joins to other tables 86 `name` VARCHAR(100) NOT NULL, -- the scheduler's name according to master.cfg 87 `class_name` VARCHAR(100) NOT NULL, -- the scheduler's class 88 `state` VARCHAR(1024) NOT NULL -- JSON-encoded state dictionary 89 ); 90 """ % {'schedulerid_col': schedulerid_col} 91 self.migrate_table('schedulers', schema) 92 93 # Fix up indices 94 cursor = self.conn.cursor() 95 cursor.execute(""" 96 CREATE UNIQUE INDEX `name_and_class` ON 97 schedulers (`name`, `class_name`) 98 """)
99
100 - def migrate_builds(self):
101 buildid_col = self.makeAutoincColumn('id') 102 schema = """ 103 CREATE TABLE builds ( 104 %(buildid_col)s, 105 `number` INTEGER NOT NULL, -- BuilderStatus.getBuild(number) 106 -- 'number' is scoped to both the local buildmaster and the buildername 107 `brid` INTEGER NOT NULL, -- matches buildrequests.id 108 `start_time` INTEGER NOT NULL, 109 `finish_time` INTEGER 110 ); 111 """ % {'buildid_col': buildid_col} 112 self.migrate_table('builds', schema)
113
114 - def migrate_changes(self):
115 changeid_col = self.makeAutoincColumn('changeid') 116 schema = """ 117 CREATE TABLE changes ( 118 %(changeid_col)s, -- also serves as 'change number' 119 `author` VARCHAR(1024) NOT NULL, 120 `comments` VARCHAR(1024) NOT NULL, -- too short? 121 `is_dir` SMALLINT NOT NULL, -- old, for CVS 122 `branch` VARCHAR(1024) NULL, 123 `revision` VARCHAR(256), -- CVS uses NULL. too short for darcs? 124 `revlink` VARCHAR(256) NULL, 125 `when_timestamp` INTEGER NOT NULL, -- copied from incoming Change 126 `category` VARCHAR(256) NULL, 127 128 -- repository specifies, along with revision and branch, the 129 -- source tree in which this change was detected. 130 `repository` TEXT NOT NULL default '', 131 132 -- project names the project this source code represents. It is used 133 -- later to filter changes 134 `project` TEXT NOT NULL default '' 135 ); 136 """ % {'changeid_col': changeid_col} 137 self.migrate_table('changes', schema) 138 139 # Drop changes_nextid columnt 140 cursor = self.conn.cursor() 141 cursor.execute("DROP TABLE changes_nextid")
142
143 - def migrate_buildrequests(self):
144 buildrequestid_col = self.makeAutoincColumn('id') 145 schema = """ 146 CREATE TABLE buildrequests ( 147 %(buildrequestid_col)s, 148 149 -- every BuildRequest has a BuildSet 150 -- the sourcestampid and reason live in the BuildSet 151 `buildsetid` INTEGER NOT NULL, 152 153 `buildername` VARCHAR(256) NOT NULL, 154 155 `priority` INTEGER NOT NULL default 0, 156 157 -- claimed_at is the time at which a master most recently asserted that 158 -- it is responsible for running the build: this will be updated 159 -- periodically to maintain the claim 160 `claimed_at` INTEGER default 0, 161 162 -- claimed_by indicates which buildmaster has claimed this request. The 163 -- 'name' contains hostname/basedir, and will be the same for subsequent 164 -- runs of any given buildmaster. The 'incarnation' contains bootime/pid, 165 -- and will be different for subsequent runs. This allows each buildmaster 166 -- to distinguish their current claims, their old claims, and the claims 167 -- of other buildmasters, to treat them each appropriately. 168 `claimed_by_name` VARCHAR(256) default NULL, 169 `claimed_by_incarnation` VARCHAR(256) default NULL, 170 171 `complete` INTEGER default 0, -- complete=0 means 'pending' 172 173 -- results is only valid when complete==1 174 `results` SMALLINT, -- 0=SUCCESS,1=WARNINGS,etc, from status/builder.py 175 176 `submitted_at` INTEGER NOT NULL, 177 178 `complete_at` INTEGER 179 ); 180 """ % {'buildrequestid_col': buildrequestid_col} 181 self.migrate_table('buildrequests', schema)
182
183 - def migrate_buildsets(self):
184 buildsetsid_col = self.makeAutoincColumn('id') 185 schema = """ 186 CREATE TABLE buildsets ( 187 %(buildsetsid_col)s, 188 `external_idstring` VARCHAR(256), 189 `reason` VARCHAR(256), 190 `sourcestampid` INTEGER NOT NULL, 191 `submitted_at` INTEGER NOT NULL, 192 `complete` SMALLINT NOT NULL default 0, 193 `complete_at` INTEGER, 194 `results` SMALLINT -- 0=SUCCESS,2=FAILURE, from status/builder.py 195 -- results is NULL until complete==1 196 ); 197 """ % {'buildsetsid_col': buildsetsid_col} 198 self.migrate_table("buildsets", schema)
199
200 - def migrate_patches(self):
201 patchesid_col = self.makeAutoincColumn('id') 202 schema = """ 203 CREATE TABLE patches ( 204 %(patchesid_col)s, 205 `patchlevel` INTEGER NOT NULL, 206 `patch_base64` TEXT NOT NULL, -- encoded bytestring 207 `subdir` TEXT -- usually NULL 208 ); 209 """ % {'patchesid_col': patchesid_col} 210 self.migrate_table("patches", schema)
211
212 - def migrate_sourcestamps(self):
213 sourcestampsid_col = self.makeAutoincColumn('id') 214 schema = """ 215 CREATE TABLE sourcestamps ( 216 %(sourcestampsid_col)s, 217 `branch` VARCHAR(256) default NULL, 218 `revision` VARCHAR(256) default NULL, 219 `patchid` INTEGER default NULL, 220 `repository` TEXT not null default '', 221 `project` TEXT not null default '' 222 ); 223 """ % {'sourcestampsid_col': sourcestampsid_col} 224 self.migrate_table("sourcestamps", schema)
225