r1303 + even closer to a working 0.14.7 release, waiting for tests to succeed
[racktables] / upgrade.php
1 <?php
2
3 // At the moment we assume, that for any two releases we can
4 // sequentally execute all batches, that separate them, and
5 // nothing will break. If this changes one day, the function
6 // below will have to generate smarter upgrade paths, while
7 // the upper layer will remain the same.
8 // Returning an empty array means that no upgrade is necessary.
9 function getDBUpgradePath ($v1, $v2)
10 {
11 $versionhistory = array ('0.14.4', '0.14.5', '0.14.6');
12 if (!in_array ($v1, $versionhistory) || !in_array ($v2, $versionhistory))
13 {
14 showError ("An upgrade path has been requested for versions '${v1}' and '${v2}', " .
15 "and at least one of those isn't known to me.");
16 die;
17 }
18 $skip = TRUE;
19 $path = array();
20 // Now collect all versions > $v1 and <= $v2
21 foreach ($versionhistory as $v)
22 {
23 if ($v == $v1)
24 {
25 $skip = FALSE;
26 continue;
27 }
28 if ($skip)
29 continue;
30 $path[] = $v;
31 if ($v == $v2)
32 break;
33 }
34 return $path;
35 }
36
37 // Upgrade batches are name exactly as the release where they first appear.
38 // That simple, but seems sufficient for beginning.
39 function executeUpgradeBatch ($batchid)
40 {
41 $query = array();
42 global $dbxlink;
43 switch ($batchid)
44 {
45 case '0.14.5':
46 // We can't realiably distinguish between 0.14.4 and 0.14.5, but
47 // luckily the SQL statements below can be safely executed for both.
48
49
50 // This has to be checked once more to be sure IPAddress allocation
51 // conventions are correct.
52 $query[] = "delete from IPAddress where name = '' and reserved = 'no'";
53
54 // In the 0.14.4 release we had AUTO_INCREMENT low in the dictionary and auth
55 // data tables, thus causing new user's data to take primary keys equal to
56 // the values of shipped data in future releases. Let's shift user's data
57 // up and keep DB consistent.
58 $query[] = "alter table Attribute AUTO_INCREMENT = 10000";
59 $query[] = "alter table Chapter AUTO_INCREMENT = 10000";
60 $query[] = "alter table Dictionary AUTO_INCREMENT = 10000";
61 $query[] = "alter table UserAccount AUTO_INCREMENT = 10000";
62 $query[] = "update UserAccount set user_id = user_id + 10000 where user_id between 2 and 10000";
63 $query[] = "update UserPermission set user_id = user_id + 10000 where user_id between 2 and 10000";
64 $query[] = "update Attribute set attr_id = attr_id + 10000 where attr_id between 25 and 10000";
65 $query[] = "update AttributeMap set attr_id = attr_id + 10000 where attr_id between 25 and 10000";
66 $query[] = "update Chapter set chapter_no = chapter_no + 10000 where chapter_no between 21 and 10000";
67 $query[] = "update AttributeMap set chapter_no = chapter_no + 10000 where chapter_no between 21 and 10000";
68 break; // --------------------------------------------
69 case '0.14.6':
70 // This version features new dictionary entries, the correction above should allow us
71 // inject them w/o a problem.
72 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (13,25,'FreeBSD 1.x')";
73 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (13,26,'FreeBSD 2.x')";
74 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (13,27,'FreeBSD 3.x')";
75 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (13,28,'FreeBSD 4.x')";
76 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (13,29,'FreeBSD 5.x')";
77 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (13,30,'FreeBSD 6.x')";
78 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (13,31,'RHFC8')";
79 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (13,32,'ALTLinux Master 4.0')";
80 $query[] = "INSERT INTO `PortCompat` (`type1`, `type2`) VALUES (20,20)";
81 $query[] = "INSERT INTO `PortCompat` (`type1`, `type2`) VALUES (21,21)";
82 $query[] = "INSERT INTO `PortCompat` (`type1`, `type2`) VALUES (22,22)";
83 $query[] = "INSERT INTO `PortCompat` (`type1`, `type2`) VALUES (23,23)";
84 $query[] = "INSERT INTO `PortCompat` (`type1`, `type2`) VALUES (24,24)";
85 $query[] = "INSERT INTO `PortCompat` (`type1`, `type2`) VALUES (25,25)";
86 $query[] = "INSERT INTO `PortCompat` (`type1`, `type2`) VALUES (26,26)";
87 $query[] = "INSERT INTO `PortCompat` (`type1`, `type2`) VALUES (27,27)";
88 $query[] = "INSERT INTO `PortCompat` (`type1`, `type2`) VALUES (28,28)";
89 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (2,20,'KVM')";
90 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (2,21,'1000Base-ZX')";
91 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (2,22,'10GBase-ER')";
92 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (2,23,'10GBase-LR')";
93 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (2,24,'10GBase-LRM')";
94 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (2,25,'10GBase-ZR')";
95 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (2,26,'10GBase-LX4')";
96 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (2,27,'10GBase-CX4')";
97 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (2,28,'10GBase-Kx')";
98 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (12,114,'Cisco Catalyst 2970G-24T')";
99 $query[] = "INSERT INTO `Dictionary` (`chapter_no`, `dict_key`, `dict_value`) VALUES (12,115,'Cisco Catalyst 2970G-24TS')";
100 $query[] = "INSERT INTO `UserPermission` (`user_id`, `page`, `tab`, `access`) VALUES (0,'help','%','yes')";
101 // And 0.14.6 is the first release, which features Config table. Let's create
102 // and fill it with default values.
103 $query[] = "
104 CREATE TABLE `Config` (
105 `varname` char(32) NOT NULL,
106 `varvalue` char(64) NOT NULL,
107 `vartype` enum('string','uint') NOT NULL default 'string',
108 `emptyok` enum('yes','no') NOT NULL default 'no',
109 `is_hidden` enum('yes','no') NOT NULL default 'yes',
110 `description` text,
111 PRIMARY KEY (`varname`)
112 ) ENGINE=MyISAM DEFAULT CHARSET=latin1
113 ";
114 $query[] = "INSERT INTO `Config` VALUES ('rtwidth_0','9','uint','no','yes','')";
115 $query[] = "INSERT INTO `Config` VALUES ('rtwidth_1','21','uint','no','yes','')";
116 $query[] = "INSERT INTO `Config` VALUES ('rtwidth_2','9','uint','no','yes','')";
117 $query[] = "INSERT INTO `Config` VALUES ('color_F','8fbfbf','string','no','no','HSV: 180-25-75. Free atoms, they are available for allocation to objects.')";
118 $query[] = "INSERT INTO `Config` VALUES ('color_A','bfbfbf','string','no','no','HSV: 0-0-75. Absent atoms.')";
119 $query[] = "INSERT INTO `Config` VALUES ('color_U','bf8f8f','string','no','no','HSV: 0-25-75. Unusable atoms. Some problems keep them from being free.')";
120 $query[] = "INSERT INTO `Config` VALUES ('color_T','408080','string','no','no','HSV: 180-50-50. Taken atoms, object_id should be set for such.')";
121 $query[] = "INSERT INTO `Config` VALUES ('color_Th','80ffff','string','no','no','HSV: 180-50-100. Taken atoms with highlight. They are not stored in the database and are only used for highlighting.')";
122 $query[] = "INSERT INTO `Config` VALUES ('color_Tw','804040','string','no','no','HSV: 0-50-50. Taken atoms with object problem. This is detected at runtime.')";
123 $query[] = "INSERT INTO `Config` VALUES ('color_Thw','ff8080','string','no','no','HSV: 0-50-100. An object can be both current and problematic. We run highlightObject() first and markupObjectProblems() second.')";
124 $query[] = "INSERT INTO `Config` VALUES ('default_port_type','11','uint','no','no','Default value for port type selects.')";
125 $query[] = "INSERT INTO `Config` VALUES ('MASSCOUNT','15','uint','no','no','Number of lines in object mass-adding form.')";
126 $query[] = "INSERT INTO `Config` VALUES ('MAXSELSIZE','30','uint','no','no','Maximum size of a SELECT HTML element.')";
127 $query[] = "INSERT INTO `Config` VALUES ('enterprise','MyCompanyName','string','no','no','Fit to your needs.')";
128 $query[] = "INSERT INTO `Config` VALUES ('NAMEFUL_OBJTYPES','4,7,8','string','yes','no','These are the object types, which assume a common name to be normally configured. If a name is absent for an object of one of such types, HTML output is corrected to accent this misconfiguration.')";
129 $query[] = "INSERT INTO `Config` VALUES ('ROW_SCALE','2','uint','no','no','Row-scope picture scale factor.')";
130 $query[] = "INSERT INTO `Config` VALUES ('PORTS_PER_ROW','12','uint','no','yes','Max switch port per one row on the switchvlans dynamic tab.')";
131 $query[] = "INSERT INTO `Config` VALUES ('DB_VERSION','0.14.6','string','no','yes','Database version.')";
132 break; // --------------------------------------------
133 case '0.14.7':
134 // IPAddress is hopefully fixed now finally.
135 $query[] = "delete from IPAddress where name = '' and reserved != 'yes'";
136
137 // Now rebuild the dictionary into a new table with the same data,
138 // but proper indexing. We are going to convert compound index
139 // into 1-field one to employ AUTO_INCREMENT properly. This means
140 // renumbering lots of records in Dictionary and adjusting records
141 // in related tables. After that we can safely swap the tables.
142 $query[] = 'create table Dictionary_0_14_7_new (chapter_no int(10) unsigned NOT NULL, dict_key int(10) unsigned NOT NULL auto_increment PRIMARY KEY, dict_value char(128) default NULL)';
143 // Convert the fields to unsigned on occasion.
144 $query[] = 'create table PortCompat_0_14_7_new (type1 int(10) unsigned NOT NULL, type2 int(10) unsigned NOT NULL)';
145
146 echo '<pre>';
147 // Find all chapter numbers, which will require AttributeValue adjustment.
148 $q2 = 'select distinct chapter_no from AttributeMap where chapter_no != 0';
149 $r2 = $dbxlink->query ($q2);
150 $chaplist = array();
151 while ($row = $r2->fetch (PDO::FETCH_NUM))
152 $chaplist[] = $row[0];
153 print_r ($chaplist);
154 $r2->closeCursor();
155 unset ($r2);
156
157 $stock = array();
158 // Below I list the records, which are known to be the stock
159 // dictionary records of 0.14.6 release.
160 $stock[1] = array
161 (
162 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 14, 15, 16
163 );
164 $stock[2] = array
165 (
166 3, 4, 5, 6, 7, 8, 9,
167 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20,
168 20, 21, 22, 23, 24, 25, 26, 27, 28
169 );
170 $stock[11] = array
171 (
172 1, 3, 4, 5, 6, 7, 8, 9,
173 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
174 21, 22, 24, 25, 26, 27, 28, 29,
175 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
176 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
177 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
178 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
179 70, 71, 72, 73, 74, 75, 76
180 );
181 $stock[12] = array
182 (
183 1, 11, 13, 14, 15, 16, 17, 18, 19, 20, 26, 29,
184 31, 32, 33, 34, 35, 36, 37, 38, 39,
185 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
186 50, 51, 52, 53, 54, 55, 56, 57, 58, 59,
187 60, 61, 62, 63, 64, 65, 66, 67, 68, 69,
188 70, 71, 72, 73, 74, 75, 76, 77, 78, 79,
189 80, 81, 82, 83, 84, 85, 86, 87, 88, 89,
190 90, 91, 92, 93, 94, 95, 96, 97, 98, 99,
191 100, 101, 102, 103, 104, 105, 106, 107, 108, 109,
192 110, 111, 112, 113
193 );
194 $stock[13] = array
195 (
196 1, 2, 3, 4, 5, 6, 7, 8, 9,
197 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
198 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
199 30, 31, 32
200 );
201 $stock[14] = array
202 (
203 1, 2, 9, 11, 13, 15, 19, 20, 21, 22
204 );
205 $stock[16] = array
206 (
207 1, 2, 3, 4, 5, 6, 7, 8
208 );
209 $stock[17] = array
210 (
211 1, 2, 3, 4, 5, 6, 7, 8, 9,
212 10, 11, 12, 13, 14, 15, 16, 17, 18, 19,
213 20, 21, 22, 23, 24, 25, 26, 27, 28, 29,
214 30, 31, 32, 33, 34, 35, 36, 37, 38, 39,
215 40, 41, 42, 43, 44, 45, 46, 47, 48, 49,
216 50
217 );
218 $stock[18] = array
219 (
220 1, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14
221 );
222 $stock[19] = array
223 (
224 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11
225 );
226 $stock[20] = array
227 (
228 1, 2
229 );
230
231 // Load dictionary and transform into two tree structures for
232 // stock and user record sets.
233 $dict = array();
234 $q3 = 'select chapter_no, dict_key, dict_value from Dictionary order by chapter_no, dict_key';
235 $r3 = $dbxlink->query ($q3);
236
237 while ($row = $r3->fetch (PDO::FETCH_ASSOC))
238 {
239 $tree = 'user';
240 $dict_key = $row['dict_key'];
241 $chapter_no = $row['chapter_no'];
242 switch ($chapter_no)
243 {
244 case 1: // RackObjectType
245 case 2: // PortType
246 case 11: // server models
247 case 12: // network switch models
248 case 13: // server OS type
249 case 14: // network switch OS type
250 case 16: // router OS type
251 case 17: // router models
252 case 18: // disk array models
253 case 19: // tape library models
254 case 20: // Protocols
255 if (in_array ($dict_key, $stock[$chapter_no]))
256 $tree = 'stock';
257 break;
258 }
259 $dict[$tree][$chapter_no][$dict_key] = array ('value' => $row['dict_value']);
260 }
261 $r3->closeCursor();
262 unset ($r3);
263
264
265 // Now we store stock dataset first, bump up key value and store
266 // user's data. After that we will know the new dict_key for all
267 // records.
268 // The result of both datasets processing is saved in $new_dict.
269 // Save on calling LAST_ISERT_ID() each time by keeping own key.
270 $newkey = 1;
271 $new_dict = array();
272 foreach ($dict['stock'] as $chapter_no => $words)
273 {
274 $new_dict[$chapter_no] = array();
275 foreach ($words as $dict_key => $entry)
276 {
277 $query[] = "insert into Dictionary_0_14_7_new " .
278 "values (${chapter_no}, ${newkey}, '${entry['value']}')";
279 $new_dict[$chapter_no][$dict_key] = $entry;
280 $new_dict[$chapter_no][$dict_key]['newkey'] = $newkey;
281 $newkey++;
282 }
283 }
284 $newkey = 10000;
285 foreach ($dict['user'] as $chapter_no => $words)
286 {
287 // Some chapters may appear on the user dataset only.
288 if (!isset ($new_dict[$chapter_no]))
289 $new_dict[$chapter_no] = array();
290 foreach ($words as $dict_key => $entry)
291 {
292 $query[] = "insert into Dictionary_0_14_7_new " .
293 "values (${chapter_no}, ${newkey}, '${entry['value']}')";
294 $new_dict[$chapter_no][$dict_key] = $entry;
295 $new_dict[$chapter_no][$dict_key]['newkey'] = $newkey;
296 $newkey++;
297 }
298 }
299 // The new table should now have adequate AUTO_INCREMENT w/o our care.
300 // Install the new data.
301 $query[] = 'drop table Dictionary';
302 $query[] = 'alter table Dictionary_0_14_7_new rename to Dictionary';
303
304 // Now we iterate over the joint dataset, picking some chapters and
305 // performing additional processing:
306 // 1 (RackObjectType) --- adjust RackObject and regenerate AttributeMap
307 // 2 (PortType) --- adjust Port and regenerate PortCompat (at a latter point)
308 // 3 (RackRow) --- adjust Rack
309 // 20 (Protocols) --- adjust PortForwarding
310 // All other chapters listed in $chaplist --- adjust AttributeValue
311
312 $query[] = "delete from AttributeMap";
313 $query[] = "delete from AttributeValue";
314 foreach ($new_dict as $chapter_no => $words)
315 {
316 echo "Processing chapter ${chapter_no}\n";
317 foreach ($words as $oldkey => $data)
318 {
319 $value = $data['value'];
320 $newkey = $data['newkey'];
321 // Even if the key doesn't change, go on to have
322 // AttributeMap regenerated completely.
323 echo "oldkey == ${oldkey} newkey == ${newkey} value == ${value}\n";
324 if ($chapter_no == 1)
325 {
326 $q4 = "select id from RackObject where objtype_id = ${oldkey}";
327 $r4 = $dbxlink->query ($q4);
328 while ($row = $r4->fetch (PDO::FETCH_ASSOC))
329 $query[] = "update RackObject set objtype_id = ${newkey} where id = ${row['id']} limit 1";
330 $r4->closeCursor();
331 unset ($r4);
332
333 $q5 = "select attr_id, chapter_no from AttributeMap where objtype_id = ${oldkey}";
334 $r5 = $dbxlink->query ($q5);
335 while ($row = $r5->fetch (PDO::FETCH_ASSOC))
336 $query[] = "insert into AttributeMap (objtype_id, attr_id, chapter_no) values (${newkey}, ${row['attr_id']}, ${row['chapter_no']})";
337 $r5->closeCursor();
338 unset ($r5);
339 }
340 elseif ($chapter_no == 2)
341 {
342 $q46 = "select id from Port where type = ${oldkey}";
343 $r46 = $dbxlink->query ($q46);
344 if ($r46 == NULL)
345 echo 'ERROR';
346 while ($row = $r46->fetch (PDO::FETCH_ASSOC))
347 $query[] = "update Port set type = ${newkey} where id = ${row['id']} limit 1";
348 $r46->closeCursor();
349 unset ($r46);
350 }
351 elseif ($chapter_no == 3)
352 {
353 $q7 = "select id from Rack where row_id = ${oldkey}";
354 $r7 = $dbxlink->query ($q7);
355 while ($row = $r7->fetch (PDO::FETCH_ASSOC))
356 $query[] = "update Rack set row_id = ${newkey} where id = ${row['id']} limit 1";
357 $r7->closeCursor();
358 unset ($r7);
359 }
360 elseif ($chapter_no == 20)
361 {
362 $q8 = "select object_id, localip, localport, remoteip, remoteport from PortForwarding where proto = ${oldkey}";
363 $r8 = $dbxlink->query ($q8);
364 while ($row = $r8->fetch (PDO::FETCH_ASSOC))
365 $query[] = "update PortForwarding set proto = ${newkey} where " .
366 "object_id = ${row['object_id']} and localip = ${row['localip']} and " .
367 "localport = ${row['localport']} and remoteip = ${row['remoteip']} and " .
368 "remoteport = ${row['remoteport']} and proto = ${oldkey} limit 1";
369 $r8->closeCursor();
370 unset ($r8);
371 }
372 elseif (in_array ($chapter_no, $chaplist))
373 {
374 $q81 = "select object_id, attr_id from " .
375 "AttributeValue natural join Attribute natural join AttributeMap " .
376 "inner join RackObject on RackObject.id = object_id and RackObject.objtype_id = AttributeMap.objtype_id " .
377 "where attr_type = 'dict' and chapter_no = ${chapter_no} and uint_value = ${oldkey}";
378 $r81 = $dbxlink->query ($q81);
379 while ($row = $r81->fetch (PDO::FETCH_ASSOC))
380 $query[] = "insert into AttributeValue (object_id, attr_id, uint_value) " .
381 "values (${row['object_id']}, ${row['attr_id']}, ${newkey})";
382 $r81->closeCursor();
383 unset ($r81);
384 }
385 }
386 }
387 // Now it's possible to schedule PortCompat regeneration.
388 $query[] = "delete from PortCompat";
389 $q9 = "select type1, type2 from PortCompat";
390 $r9 = $dbxlink->query ($q9);
391 while ($row = $r9->fetch (PDO::FETCH_ASSOC))
392 {
393 $new_type1 = $new_dict[2][$row['type1']]['newkey'];
394 $new_type2 = $new_dict[2][$row['type2']]['newkey'];
395 $query[] = "insert into PortCompat (type1, type2) values (${new_type1}, ${new_type2})";
396 }
397 $r9->closeCursor();
398 unset ($r9);
399 echo '</pre>';
400
401 // Give the configuration some finish
402 $query[] = "update Config set is_hidden = 'yes' where varname = 'color_F'";
403 $query[] = "update Config set is_hidden = 'yes' where varname = 'color_A'";
404 $query[] = "update Config set is_hidden = 'yes' where varname = 'color_U'";
405 $query[] = "update Config set is_hidden = 'yes' where varname = 'color_T'";
406 $query[] = "update Config set is_hidden = 'yes' where varname = 'color_Th'";
407 $query[] = "update Config set is_hidden = 'yes' where varname = 'color_Tw'";
408 $query[] = "update Config set is_hidden = 'yes' where varname = 'color_Thw'";
409 $query[] = "update Config set description = 'Default port type' where varname = 'default_port_type'";
410 $query[] = "update Config set description = 'Picture scale for rack row display' where varname = 'ROW_SCALE'";
411 $query[] = "update Config set description = 'Organization name' where varname = 'enterprise'";
412 $query[] = "update Config set description = 'Expect common name configured for the following object types' where varname = 'NAMEFUL_OBJTYPES'";
413 $query[] = "update Config set description = '&lt;SELECT&gt; lists height' where varname = 'MAXSELSIZE'";
414 $query[] = "update Config set description = '&quot;Fast&quot; form is this many records tall' where varname = 'MASSCOUNT'";
415 $query[] = "update Config set is_hidden = 'no', description = 'Ports per row in VLANs tab' where varname = 'PORTS_PER_ROW'";
416 $query[] = "INSERT INTO `Config` VALUES ('IPV4_ADDRS_PER_PAGE','256','uint','no','no','IPv4 addresses per page')";
417 $query[] = "INSERT INTO `Config` VALUES ('DEFAULT_RACK_HEIGHT','42','uint','yes','no','Default rack height')";
418
419 // We are done.
420 # $query[] = "update Config set varvalue = '0.14.7' where varname = 'DB_VERSION'";
421 break; // --------------------------------------------
422 default:
423 showError ("executeUpgradeBatch () failed, because batch '${batchid}' isn't defined");
424 die;
425 break;
426 }
427 $failures = array();
428 $ndots = 0;
429 echo "<pre>Executing database upgrade batch '${batchid}: ";
430 print_r ($query);
431 foreach ($query as $q)
432 {
433 $result = $dbxlink->query ($q);
434 if ($result != NULL)
435 echo '.';
436 else
437 {
438 echo '!';
439 $errorInfo = $dbxlink->errorInfo();
440 $failures[] = array ($q, $errorInfo[2]);
441 }
442 if (++$ndots == 50)
443 {
444 echo "\n";
445 $ndots = 0;
446 }
447 }
448 echo '<br>';
449 if (!count ($failures))
450 echo "No errors!\n";
451 else
452 {
453 echo "The following queries failed:\n";
454 foreach ($failures as $f)
455 {
456 list ($q, $i) = $f;
457 echo "${q} // ${i}\n";
458 }
459 }
460 echo '</pre>';
461 }
462
463 // ******************************************************************
464 //
465 // Execution starts here
466 //
467 // ******************************************************************
468
469 $root = (empty($_SERVER['HTTPS'])?'http':'https').
470 '://'.
471 (isset($_SERVER['HTTP_HOST'])?$_SERVER['HTTP_HOST']:($_SERVER['SERVER_NAME'].($_SERVER['SERVER_PORT']=='80'?'':$_SERVER['SERVER_PORT']))).
472 dirname($_SERVER['PHP_SELF']).'/';
473
474 // The below will be necessary as long as we rely on showError()
475 require_once 'inc/interface.php';
476
477 require_once 'inc/config.php';
478 require_once 'inc/database.php';
479 if (file_exists ('inc/secret.php'))
480 require_once 'inc/secret.php';
481 else
482 die ("Database connection parameters are read from inc/secret.php file, " .
483 "which cannot be found.\nCopy provided inc/secret-sample.php to " .
484 "inc/secret.php and modify to your setup.\n\nThen reload the page.");
485
486 try
487 {
488 $dbxlink = new PDO ($pdo_dsn, $db_username, $db_password);
489 }
490 catch (PDOException $e)
491 {
492 die ("Database connection failed:\n\n" . $e->getMessage());
493 }
494
495 if (isset ($_SERVER['PHP_AUTH_USER']))
496 $_SERVER['PHP_AUTH_USER'] = escapeString ($_SERVER['PHP_AUTH_USER']);
497 if (isset ($_SERVER['PHP_AUTH_PW']))
498 $_SERVER['PHP_AUTH_PW'] = escapeString ($_SERVER['PHP_AUTH_PW']);
499
500 // Now we need to be sure that the current user is the administrator.
501 // The rest doesn't matter within this context.
502 // We still continue to use the current authenticator though, but this will
503 // last only till the UserAccounts remains the same. After that this file
504 // will have to dig into the DB for the user accounts.
505 require_once 'inc/auth.php';
506
507 // This will not fail sanely, because getUserAccounts() depends on showError()
508 $accounts = getUserAccounts();
509
510 // Auth prompt risk being a little broken here due to config cache absence.
511 $configCache = array();
512 authenticate();
513 if ($accounts[$_SERVER['PHP_AUTH_USER']]['user_id'] != 1)
514 die ('You are not allowed to upgrade the database. Ask your RackTables administrator to do this.');
515
516 $dbver = getDatabaseVersion();
517 echo 'Code version == ' . CODE_VERSION;
518 echo '<br>Database version == ' . $dbver;
519 if ($dbver == CODE_VERSION)
520 {
521 executeUpgradeBatch ('0.14.7');
522 die ("<p align=justify>Your database seems to be up-to-date. " .
523 "Now the best thing to do would be to follow to the <a href='${root}'>main page</a> " .
524 "and explore your data. Have a nice day.</p>");
525 }
526
527 foreach (getDBUpgradePath ($dbver, CODE_VERSION) as $batchid)
528 executeUpgradeBatch ($batchid);
529
530 echo '<br>Database version == ' . getDatabaseVersion();
531 echo "<p align=justify>Your database seems to be up-to-date. " .
532 "Now the best thing to do would be to follow to the <a href='${root}'>main page</a> " .
533 "and explore your data. Have a nice day.</p>";
534
535 ?>