Index: trunk/phase3/maintenance/updaters.inc |
— | — | @@ -1,727 +0,0 @@ |
2 | | -<?php |
3 | | -/** |
4 | | - * @file |
5 | | - * @ingroup Maintenance |
6 | | - */ |
7 | | - |
8 | | -if ( !defined( 'MEDIAWIKI' ) ) { |
9 | | - echo "This file is not a valid entry point\n"; |
10 | | - exit( 1 ); |
11 | | -} |
12 | | - |
13 | | -function archive( $name ) { |
14 | | - return DatabaseBase::patchPath( $name ); |
15 | | -} |
16 | | - |
17 | | -function do_interwiki_update() { |
18 | | - # Check that interwiki table exists; if it doesn't source it |
19 | | - global $IP; |
20 | | - $dbw = wfGetDB( DB_MASTER ); |
21 | | - if ( $dbw->tableExists( "interwiki" ) ) { |
22 | | - wfOut( "...already have interwiki table\n" ); |
23 | | - return true; |
24 | | - } |
25 | | - wfOut( "Creating interwiki table: " ); |
26 | | - $dbw->sourceFile( archive( "patch-interwiki.sql" ) ); |
27 | | - wfOut( "ok\n" ); |
28 | | - wfOut( "Adding default interwiki definitions: " ); |
29 | | - $dbw->sourceFile( "$IP/maintenance/interwiki.sql" ); |
30 | | - wfOut( "ok\n" ); |
31 | | -} |
32 | | - |
33 | | -function do_index_update() { |
34 | | - # Check that proper indexes are in place |
35 | | - $dbw = wfGetDB( DB_MASTER ); |
36 | | - $meta = $dbw->fieldInfo( "recentchanges", "rc_timestamp" ); |
37 | | - if ( !$meta->isMultipleKey() ) { |
38 | | - wfOut( "Updating indexes to 20031107: " ); |
39 | | - $dbw->sourceFile( archive( "patch-indexes.sql" ) ); |
40 | | - wfOut( "ok\n" ); |
41 | | - return true; |
42 | | - } |
43 | | - wfOut( "...indexes seem up to 20031107 standards\n" ); |
44 | | - return false; |
45 | | -} |
46 | | - |
47 | | -function do_image_name_unique_update() { |
48 | | - $dbw = wfGetDB( DB_MASTER ); |
49 | | - if ( $dbw->indexExists( 'image', 'PRIMARY' ) ) { |
50 | | - wfOut( "...image primary key already set.\n" ); |
51 | | - } else { |
52 | | - wfOut( "Making img_name the primary key... " ); |
53 | | - $dbw->sourceFile( archive( "patch-image_name_primary.sql" ) ); |
54 | | - wfOut( "ok\n" ); |
55 | | - } |
56 | | -} |
57 | | - |
58 | | -function do_watchlist_update() { |
59 | | - $dbw = wfGetDB( DB_MASTER ); |
60 | | - # Check if we need to add talk page rows to the watchlist |
61 | | - $talk = $dbw->selectField( 'watchlist', 'count(*)', 'wl_namespace & 1', __METHOD__ ); |
62 | | - $nontalk = $dbw->selectField( 'watchlist', 'count(*)', 'NOT (wl_namespace & 1)', __METHOD__ ); |
63 | | - if ( $talk != $nontalk ) { |
64 | | - wfOut( "Adding missing watchlist talk page rows... " ); |
65 | | - |
66 | | - $dbw->insertSelect( 'watchlist', 'watchlist', |
67 | | - array( |
68 | | - 'wl_user' => 'wl_user', |
69 | | - 'wl_namespace' => 'wl_namespace | 1', |
70 | | - 'wl_title' => 'wl_title', |
71 | | - 'wl_notificationtimestamp' => 'wl_notificationtimestamp' |
72 | | - ), array( 'NOT (wl_namespace & 1)' ), __METHOD__, 'IGNORE' ); |
73 | | - wfOut( "ok\n" ); |
74 | | - } else { |
75 | | - wfOut( "...watchlist talk page rows already present\n" ); |
76 | | - } |
77 | | -} |
78 | | - |
79 | | -/** |
80 | | - * 1.4 betas were missing the 'binary' marker from logging.log_title, |
81 | | - * which causes a collation mismatch error on joins in MySQL 4.1. |
82 | | - */ |
83 | | -function check_bin( $table, $field, $patchFile ) { |
84 | | - $dbw = wfGetDB( DB_MASTER ); |
85 | | - if ( $dbw->getType() != 'mysql' ) |
86 | | - return; |
87 | | - $tableName = $dbw->tableName( $table ); |
88 | | - $res = $dbw->query( "SELECT $field FROM $tableName LIMIT 0", __METHOD__ ); |
89 | | - $flags = explode( ' ', mysql_field_flags( $res->result, 0 ) ); |
90 | | - |
91 | | - if ( in_array( 'binary', $flags ) ) { |
92 | | - wfOut( "...$table table has correct $field encoding.\n" ); |
93 | | - } else { |
94 | | - wfOut( "Fixing $field encoding on $table table... " ); |
95 | | - $dbw->sourceFile( archive( $patchFile ) ); |
96 | | - wfOut( "ok\n" ); |
97 | | - } |
98 | | -} |
99 | | - |
100 | | -function do_schema_restructuring() { |
101 | | - $dbw = wfGetDB( DB_MASTER ); |
102 | | - if ( $dbw->tableExists( 'page' ) ) { |
103 | | - wfOut( "...page table already exists.\n" ); |
104 | | - } else { |
105 | | - wfOut( "...converting from cur/old to page/revision/text DB structure.\n" ); |
106 | | - wfOut( wfTimestamp( TS_DB ) ); |
107 | | - wfOut( "......checking for duplicate entries.\n" ); |
108 | | - |
109 | | - list ( $cur, $old, $page, $revision, $text ) = $dbw->tableNamesN( 'cur', 'old', 'page', 'revision', 'text' ); |
110 | | - |
111 | | - $rows = $dbw->query( "SELECT cur_title, cur_namespace, COUNT(cur_namespace) AS c |
112 | | - FROM $cur GROUP BY cur_title, cur_namespace HAVING c>1", __METHOD__ ); |
113 | | - |
114 | | - if ( $dbw->numRows( $rows ) > 0 ) { |
115 | | - wfOut( wfTimestamp( TS_DB ) ); |
116 | | - wfOut( "......<b>Found duplicate entries</b>\n" ); |
117 | | - wfOut( sprintf( "<b> %-60s %3s %5s</b>\n", 'Title', 'NS', 'Count' ) ); |
118 | | - while ( $row = $dbw->fetchObject( $rows ) ) { |
119 | | - if ( ! isset( $duplicate[$row->cur_namespace] ) ) { |
120 | | - $duplicate[$row->cur_namespace] = array(); |
121 | | - } |
122 | | - $duplicate[$row->cur_namespace][] = $row->cur_title; |
123 | | - wfOut( sprintf( " %-60s %3s %5s\n", $row->cur_title, $row->cur_namespace, $row->c ) ); |
124 | | - } |
125 | | - $sql = "SELECT cur_title, cur_namespace, cur_id, cur_timestamp FROM $cur WHERE "; |
126 | | - $firstCond = true; |
127 | | - foreach ( $duplicate as $ns => $titles ) { |
128 | | - if ( $firstCond ) { |
129 | | - $firstCond = false; |
130 | | - } else { |
131 | | - $sql .= ' OR '; |
132 | | - } |
133 | | - $sql .= "( cur_namespace = {$ns} AND cur_title in ("; |
134 | | - $first = true; |
135 | | - foreach ( $titles as $t ) { |
136 | | - if ( $first ) { |
137 | | - $sql .= $dbw->addQuotes( $t ); |
138 | | - $first = false; |
139 | | - } else { |
140 | | - $sql .= ', ' . $dbw->addQuotes( $t ); |
141 | | - } |
142 | | - } |
143 | | - $sql .= ") ) \n"; |
144 | | - } |
145 | | - # By sorting descending, the most recent entry will be the first in the list. |
146 | | - # All following entries will be deleted by the next while-loop. |
147 | | - $sql .= 'ORDER BY cur_namespace, cur_title, cur_timestamp DESC'; |
148 | | - |
149 | | - $rows = $dbw->query( $sql, __METHOD__ ); |
150 | | - |
151 | | - $prev_title = $prev_namespace = false; |
152 | | - $deleteId = array(); |
153 | | - |
154 | | - while ( $row = $dbw->fetchObject( $rows ) ) { |
155 | | - if ( $prev_title == $row->cur_title && $prev_namespace == $row->cur_namespace ) { |
156 | | - $deleteId[] = $row->cur_id; |
157 | | - } |
158 | | - $prev_title = $row->cur_title; |
159 | | - $prev_namespace = $row->cur_namespace; |
160 | | - } |
161 | | - $sql = "DELETE FROM $cur WHERE cur_id IN ( " . join( ',', $deleteId ) . ')'; |
162 | | - $rows = $dbw->query( $sql, __METHOD__ ); |
163 | | - wfOut( wfTimestamp( TS_DB ) ); |
164 | | - wfOut( "......<b>Deleted</b> " . $dbw->affectedRows() . " records.\n" ); |
165 | | - } |
166 | | - |
167 | | - |
168 | | - wfOut( wfTimestamp( TS_DB ) ); |
169 | | - wfOut( "......Creating tables.\n" ); |
170 | | - $dbw->query( "CREATE TABLE $page ( |
171 | | - page_id int(8) unsigned NOT NULL auto_increment, |
172 | | - page_namespace int NOT NULL, |
173 | | - page_title varchar(255) binary NOT NULL, |
174 | | - page_restrictions tinyblob NOT NULL, |
175 | | - page_counter bigint(20) unsigned NOT NULL default '0', |
176 | | - page_is_redirect tinyint(1) unsigned NOT NULL default '0', |
177 | | - page_is_new tinyint(1) unsigned NOT NULL default '0', |
178 | | - page_random real unsigned NOT NULL, |
179 | | - page_touched char(14) binary NOT NULL default '', |
180 | | - page_latest int(8) unsigned NOT NULL, |
181 | | - page_len int(8) unsigned NOT NULL, |
182 | | - |
183 | | - PRIMARY KEY page_id (page_id), |
184 | | - UNIQUE INDEX name_title (page_namespace,page_title), |
185 | | - INDEX (page_random), |
186 | | - INDEX (page_len) |
187 | | - ) ENGINE=InnoDB", __METHOD__ ); |
188 | | - $dbw->query( "CREATE TABLE $revision ( |
189 | | - rev_id int(8) unsigned NOT NULL auto_increment, |
190 | | - rev_page int(8) unsigned NOT NULL, |
191 | | - rev_comment tinyblob NOT NULL, |
192 | | - rev_user int(5) unsigned NOT NULL default '0', |
193 | | - rev_user_text varchar(255) binary NOT NULL default '', |
194 | | - rev_timestamp char(14) binary NOT NULL default '', |
195 | | - rev_minor_edit tinyint(1) unsigned NOT NULL default '0', |
196 | | - rev_deleted tinyint(1) unsigned NOT NULL default '0', |
197 | | - rev_len int(8) unsigned, |
198 | | - rev_parent_id int(8) unsigned default NULL, |
199 | | - PRIMARY KEY rev_page_id (rev_page, rev_id), |
200 | | - UNIQUE INDEX rev_id (rev_id), |
201 | | - INDEX rev_timestamp (rev_timestamp), |
202 | | - INDEX page_timestamp (rev_page,rev_timestamp), |
203 | | - INDEX user_timestamp (rev_user,rev_timestamp), |
204 | | - INDEX usertext_timestamp (rev_user_text,rev_timestamp) |
205 | | - ) ENGINE=InnoDB", __METHOD__ ); |
206 | | - |
207 | | - wfOut( wfTimestamp( TS_DB ) ); |
208 | | - wfOut( "......Locking tables.\n" ); |
209 | | - $dbw->query( "LOCK TABLES $page WRITE, $revision WRITE, $old WRITE, $cur WRITE", __METHOD__ ); |
210 | | - |
211 | | - $maxold = intval( $dbw->selectField( 'old', 'max(old_id)', '', __METHOD__ ) ); |
212 | | - wfOut( wfTimestamp( TS_DB ) ); |
213 | | - wfOut( "......maxold is {$maxold}\n" ); |
214 | | - |
215 | | - wfOut( wfTimestamp( TS_DB ) ); |
216 | | - global $wgLegacySchemaConversion; |
217 | | - if ( $wgLegacySchemaConversion ) { |
218 | | - // Create HistoryBlobCurStub entries. |
219 | | - // Text will be pulled from the leftover 'cur' table at runtime. |
220 | | - wfOut( "......Moving metadata from cur; using blob references to text in cur table.\n" ); |
221 | | - $cur_text = "concat('O:18:\"historyblobcurstub\":1:{s:6:\"mCurId\";i:',cur_id,';}')"; |
222 | | - $cur_flags = "'object'"; |
223 | | - } else { |
224 | | - // Copy all cur text in immediately: this may take longer but avoids |
225 | | - // having to keep an extra table around. |
226 | | - wfOut( "......Moving text from cur.\n" ); |
227 | | - $cur_text = 'cur_text'; |
228 | | - $cur_flags = "''"; |
229 | | - } |
230 | | - $dbw->query( "INSERT INTO $old (old_namespace, old_title, old_text, old_comment, old_user, old_user_text, |
231 | | - old_timestamp, old_minor_edit, old_flags) |
232 | | - SELECT cur_namespace, cur_title, $cur_text, cur_comment, cur_user, cur_user_text, cur_timestamp, cur_minor_edit, $cur_flags |
233 | | - FROM $cur", __METHOD__ ); |
234 | | - |
235 | | - wfOut( wfTimestamp( TS_DB ) ); |
236 | | - wfOut( "......Setting up revision table.\n" ); |
237 | | - $dbw->query( "INSERT INTO $revision (rev_id, rev_page, rev_comment, rev_user, rev_user_text, rev_timestamp, |
238 | | - rev_minor_edit) |
239 | | - SELECT old_id, cur_id, old_comment, old_user, old_user_text, |
240 | | - old_timestamp, old_minor_edit |
241 | | - FROM $old,$cur WHERE old_namespace=cur_namespace AND old_title=cur_title", __METHOD__ ); |
242 | | - |
243 | | - wfOut( wfTimestamp( TS_DB ) ); |
244 | | - wfOut( "......Setting up page table.\n" ); |
245 | | - $dbw->query( "INSERT INTO $page (page_id, page_namespace, page_title, page_restrictions, page_counter, |
246 | | - page_is_redirect, page_is_new, page_random, page_touched, page_latest, page_len) |
247 | | - SELECT cur_id, cur_namespace, cur_title, cur_restrictions, cur_counter, cur_is_redirect, cur_is_new, |
248 | | - cur_random, cur_touched, rev_id, LENGTH(cur_text) |
249 | | - FROM $cur,$revision |
250 | | - WHERE cur_id=rev_page AND rev_timestamp=cur_timestamp AND rev_id > {$maxold}", __METHOD__ ); |
251 | | - |
252 | | - wfOut( wfTimestamp( TS_DB ) ); |
253 | | - wfOut( "......Unlocking tables.\n" ); |
254 | | - $dbw->query( "UNLOCK TABLES", __METHOD__ ); |
255 | | - |
256 | | - wfOut( wfTimestamp( TS_DB ) ); |
257 | | - wfOut( "......Renaming old.\n" ); |
258 | | - $dbw->query( "ALTER TABLE $old RENAME TO $text", __METHOD__ ); |
259 | | - |
260 | | - wfOut( wfTimestamp( TS_DB ) ); |
261 | | - wfOut( "...done.\n" ); |
262 | | - } |
263 | | -} |
264 | | - |
265 | | -function do_pagelinks_update() { |
266 | | - $dbw = wfGetDB( DB_MASTER ); |
267 | | - if ( $dbw->tableExists( 'pagelinks' ) ) { |
268 | | - wfOut( "...already have pagelinks table.\n" ); |
269 | | - } else { |
270 | | - wfOut( "Converting links and brokenlinks tables to pagelinks... " ); |
271 | | - $dbw->sourceFile( archive( 'patch-pagelinks.sql' ) ); |
272 | | - wfOut( "ok\n" ); |
273 | | - |
274 | | - global $wgCanonicalNamespaceNames; |
275 | | - foreach ( $wgCanonicalNamespaceNames as $ns => $name ) { |
276 | | - if ( $ns != 0 ) { |
277 | | - do_pagelinks_namespace( $ns ); |
278 | | - } |
279 | | - } |
280 | | - } |
281 | | -} |
282 | | - |
283 | | -function do_pagelinks_namespace( $namespace ) { |
284 | | - global $wgContLang; |
285 | | - |
286 | | - $dbw = wfGetDB( DB_MASTER ); |
287 | | - $ns = intval( $namespace ); |
288 | | - wfOut( "Cleaning up broken links for namespace $ns... " ); |
289 | | - |
290 | | - $pagelinks = $dbw->tableName( 'pagelinks' ); |
291 | | - $name = $wgContLang->getNsText( $ns ); |
292 | | - $prefix = $dbw->strencode( $name ); |
293 | | - $likeprefix = str_replace( '_', '\\_', $prefix ); |
294 | | - |
295 | | - $sql = "UPDATE $pagelinks |
296 | | - SET pl_namespace=$ns, |
297 | | - pl_title=TRIM(LEADING '$prefix:' FROM pl_title) |
298 | | - WHERE pl_namespace=0 |
299 | | - AND pl_title LIKE '$likeprefix:%'"; |
300 | | - |
301 | | - $dbw->query( $sql, 'do_pagelinks_namespace' ); |
302 | | - wfOut( "ok\n" ); |
303 | | -} |
304 | | - |
305 | | -function do_old_links_update() { |
306 | | - $cl = new ConvertLinks(); |
307 | | - $cl->execute(); |
308 | | -} |
309 | | - |
310 | | -function fix_ancient_imagelinks() { |
311 | | - $dbw = wfGetDB( DB_MASTER ); |
312 | | - $info = $dbw->fieldInfo( 'imagelinks', 'il_from' ); |
313 | | - if ( $info && $info->type() === 'string' ) { |
314 | | - wfOut( "Fixing ancient broken imagelinks table.\n" ); |
315 | | - wfOut( "NOTE: you will have to run maintenance/refreshLinks.php after this.\n" ); |
316 | | - $dbw->sourceFile( archive( 'patch-fix-il_from.sql' ) ); |
317 | | - wfOut( "ok\n" ); |
318 | | - } else { |
319 | | - wfOut( "...il_from OK\n" ); |
320 | | - } |
321 | | -} |
322 | | - |
323 | | -function do_user_unique_update() { |
324 | | - $dbw = wfGetDB( DB_MASTER ); |
325 | | - $duper = new UserDupes( $dbw ); |
326 | | - if ( $duper->hasUniqueIndex() ) { |
327 | | - wfOut( "...already have unique user_name index.\n" ); |
328 | | - } else { |
329 | | - if ( !$duper->clearDupes() ) { |
330 | | - wfOut( "WARNING: This next step will probably fail due to unfixed duplicates...\n" ); |
331 | | - } |
332 | | - wfOut( "Adding unique index on user_name... " ); |
333 | | - $dbw->sourceFile( archive( 'patch-user_nameindex.sql' ) ); |
334 | | - wfOut( "ok\n" ); |
335 | | - } |
336 | | -} |
337 | | - |
338 | | -function do_user_groups_update() { |
339 | | - $dbw = wfGetDB( DB_MASTER ); |
340 | | - |
341 | | - if ( $dbw->tableExists( 'user_groups' ) ) { |
342 | | - wfOut( "...user_groups table already exists.\n" ); |
343 | | - return do_user_groups_reformat(); |
344 | | - } |
345 | | - |
346 | | - wfOut( "Adding user_groups table... " ); |
347 | | - $dbw->sourceFile( archive( 'patch-user_groups.sql' ) ); |
348 | | - wfOut( "ok\n" ); |
349 | | - |
350 | | - if ( !$dbw->tableExists( 'user_rights' ) ) { |
351 | | - if ( $dbw->fieldExists( 'user', 'user_rights' ) ) { |
352 | | - wfOut( "Upgrading from a 1.3 or older database? Breaking out user_rights for conversion..." ); |
353 | | - $dbw->sourceFile( archive( 'patch-user_rights.sql' ) ); |
354 | | - wfOut( "ok\n" ); |
355 | | - } else { |
356 | | - wfOut( "*** WARNING: couldn't locate user_rights table or field for upgrade.\n" ); |
357 | | - wfOut( "*** You may need to manually configure some sysops by manipulating\n" ); |
358 | | - wfOut( "*** the user_groups table.\n" ); |
359 | | - return; |
360 | | - } |
361 | | - } |
362 | | - |
363 | | - wfOut( "Converting user_rights table to user_groups... " ); |
364 | | - $result = $dbw->select( 'user_rights', |
365 | | - array( 'ur_user', 'ur_rights' ), |
366 | | - array( "ur_rights != ''" ), |
367 | | - __METHOD__ ); |
368 | | - |
369 | | - while ( $row = $dbw->fetchObject( $result ) ) { |
370 | | - $groups = array_unique( |
371 | | - array_map( 'trim', |
372 | | - explode( ',', $row->ur_rights ) ) ); |
373 | | - |
374 | | - foreach ( $groups as $group ) { |
375 | | - $dbw->insert( 'user_groups', |
376 | | - array( |
377 | | - 'ug_user' => $row->ur_user, |
378 | | - 'ug_group' => $group ), |
379 | | - __METHOD__ ); |
380 | | - } |
381 | | - } |
382 | | - wfOut( "ok\n" ); |
383 | | -} |
384 | | - |
385 | | -function do_user_groups_reformat() { |
386 | | - # Check for bogus formats from previous 1.5 alpha code. |
387 | | - $dbw = wfGetDB( DB_MASTER ); |
388 | | - $info = $dbw->fieldInfo( 'user_groups', 'ug_group' ); |
389 | | - |
390 | | - if ( $info->type() == 'int' ) { |
391 | | - $oldug = $dbw->tableName( 'user_groups' ); |
392 | | - $newug = $dbw->tableName( 'user_groups_bogus' ); |
393 | | - wfOut( "user_groups is in bogus intermediate format. Renaming to $newug... " ); |
394 | | - $dbw->query( "ALTER TABLE $oldug RENAME TO $newug" ); |
395 | | - wfOut( "ok\n" ); |
396 | | - |
397 | | - wfOut( "Re-adding fresh user_groups table... " ); |
398 | | - $dbw->sourceFile( archive( 'patch-user_groups.sql' ) ); |
399 | | - wfOut( "ok\n" ); |
400 | | - |
401 | | - wfOut( "***\n" ); |
402 | | - wfOut( "*** WARNING: You will need to manually fix up user permissions in the user_groups\n" ); |
403 | | - wfOut( "*** table. Old 1.5 alpha versions did some pretty funky stuff...\n" ); |
404 | | - wfOut( "***\n" ); |
405 | | - } else { |
406 | | - wfOut( "...user_groups is in current format.\n" ); |
407 | | - } |
408 | | - |
409 | | -} |
410 | | - |
411 | | -function do_watchlist_null() { |
412 | | - # Make sure wl_notificationtimestamp can be NULL, |
413 | | - # and update old broken items. |
414 | | - $dbw = wfGetDB( DB_MASTER ); |
415 | | - $info = $dbw->fieldInfo( 'watchlist', 'wl_notificationtimestamp' ); |
416 | | - |
417 | | - if ( !$info->nullable() ) { |
418 | | - wfOut( "Making wl_notificationtimestamp nullable... " ); |
419 | | - $dbw->sourceFile( archive( 'patch-watchlist-null.sql' ) ); |
420 | | - wfOut( "ok\n" ); |
421 | | - } else { |
422 | | - wfOut( "...wl_notificationtimestamp is already nullable.\n" ); |
423 | | - } |
424 | | - |
425 | | -} |
426 | | - |
427 | | -/** |
428 | | - * @bug 3946 |
429 | | - */ |
430 | | -function do_page_random_update() { |
431 | | - wfOut( "Setting page_random to a random value on rows where it equals 0..." ); |
432 | | - |
433 | | - $dbw = wfGetDB( DB_MASTER ); |
434 | | - $page = $dbw->tableName( 'page' ); |
435 | | - $dbw->query( "UPDATE $page SET page_random = RAND() WHERE page_random = 0", 'do_page_random_update' ); |
436 | | - $rows = $dbw->affectedRows(); |
437 | | - |
438 | | - wfOut( "changed $rows rows\n" ); |
439 | | -} |
440 | | - |
441 | | -function do_templatelinks_update() { |
442 | | - $dbw = wfGetDB( DB_MASTER ); |
443 | | - |
444 | | - if ( $dbw->tableExists( 'templatelinks' ) ) { |
445 | | - wfOut( "...templatelinks table already exists\n" ); |
446 | | - return; |
447 | | - } |
448 | | - wfOut( "Creating templatelinks table...\n" ); |
449 | | - $dbw->sourceFile( archive( 'patch-templatelinks.sql' ) ); |
450 | | - wfOut( "Populating...\n" ); |
451 | | - if ( wfGetLB()->getServerCount() > 1 ) { |
452 | | - // Slow, replication-friendly update |
453 | | - $res = $dbw->select( 'pagelinks', array( 'pl_from', 'pl_namespace', 'pl_title' ), |
454 | | - array( 'pl_namespace' => NS_TEMPLATE ), __METHOD__ ); |
455 | | - $count = 0; |
456 | | - while ( $row = $dbw->fetchObject( $res ) ) { |
457 | | - $count = ( $count + 1 ) % 100; |
458 | | - if ( $count == 0 ) { |
459 | | - if ( function_exists( 'wfWaitForSlaves' ) ) { |
460 | | - wfWaitForSlaves( 10 ); |
461 | | - } else { |
462 | | - sleep( 1 ); |
463 | | - } |
464 | | - } |
465 | | - $dbw->insert( 'templatelinks', |
466 | | - array( |
467 | | - 'tl_from' => $row->pl_from, |
468 | | - 'tl_namespace' => $row->pl_namespace, |
469 | | - 'tl_title' => $row->pl_title, |
470 | | - ), __METHOD__ |
471 | | - ); |
472 | | - |
473 | | - } |
474 | | - } else { |
475 | | - // Fast update |
476 | | - $dbw->insertSelect( 'templatelinks', 'pagelinks', |
477 | | - array( |
478 | | - 'tl_from' => 'pl_from', |
479 | | - 'tl_namespace' => 'pl_namespace', |
480 | | - 'tl_title' => 'pl_title' |
481 | | - ), array( |
482 | | - 'pl_namespace' => 10 |
483 | | - ), __METHOD__ |
484 | | - ); |
485 | | - } |
486 | | - wfOut( "Done. Please run maintenance/refreshLinks.php for a more thorough templatelinks update.\n" ); |
487 | | -} |
488 | | - |
489 | | -// Add index on ( rc_namespace, rc_user_text ) [Jul. 2006] |
490 | | -// Add index on ( rc_user_text, rc_timestamp ) [Nov. 2006] |
491 | | -function do_rc_indices_update() { |
492 | | - $dbw = wfGetDB( DB_MASTER ); |
493 | | - wfOut( "Checking for additional recent changes indices...\n" ); |
494 | | - |
495 | | - $indexes = array( |
496 | | - 'rc_ns_usertext' => 'patch-recentchanges-utindex.sql', |
497 | | - 'rc_user_text' => 'patch-rc_user_text-index.sql', |
498 | | - ); |
499 | | - |
500 | | - foreach ( $indexes as $index => $patch ) { |
501 | | - $info = $dbw->indexInfo( 'recentchanges', $index, __METHOD__ ); |
502 | | - if ( !$info ) { |
503 | | - wfOut( "...index `{$index}` not found; adding..." ); |
504 | | - $dbw->sourceFile( archive( $patch ) ); |
505 | | - wfOut( "done.\n" ); |
506 | | - } else { |
507 | | - wfOut( "...index `{$index}` seems ok.\n" ); |
508 | | - } |
509 | | - } |
510 | | -} |
511 | | - |
512 | | -function index_has_field( $table, $index, $field ) { |
513 | | - wfOut( "Checking if $table index $index includes field $field...\n" ); |
514 | | - $info = wfGetDB( DB_MASTER )->indexInfo( $table, $index, __METHOD__ ); |
515 | | - if ( $info ) { |
516 | | - foreach ( $info as $row ) { |
517 | | - if ( $row->Column_name == $field ) { |
518 | | - wfOut( "...index $index on table $table seems to be ok\n" ); |
519 | | - return true; |
520 | | - } |
521 | | - } |
522 | | - } |
523 | | - wfOut( "...index $index on table $table has no field $field; adding\n" ); |
524 | | - return false; |
525 | | -} |
526 | | - |
527 | | -function do_backlinking_indices_update() { |
528 | | - wfOut( "Checking for backlinking indices...\n" ); |
529 | | - if ( !index_has_field( 'pagelinks', 'pl_namespace', 'pl_from' ) || |
530 | | - !index_has_field( 'templatelinks', 'tl_namespace', 'tl_from' ) || |
531 | | - !index_has_field( 'imagelinks', 'il_to', 'il_from' ) ) |
532 | | - { |
533 | | - wfGetDB( DB_MASTER )->sourceFile( archive( 'patch-backlinkindexes.sql' ) ); |
534 | | - wfOut( "...backlinking indices updated\n" ); |
535 | | - } |
536 | | -} |
537 | | - |
538 | | -function do_categorylinks_indices_update() { |
539 | | - wfOut( "Checking for categorylinks indices...\n" ); |
540 | | - if ( !index_has_field( 'categorylinks', 'cl_sortkey', 'cl_from' ) ) |
541 | | - { |
542 | | - wfGetDB( DB_MASTER )->sourceFile( archive( 'patch-categorylinksindex.sql' ) ); |
543 | | - wfOut( "...categorylinks indices updated\n" ); |
544 | | - } |
545 | | -} |
546 | | - |
547 | | -function do_filearchive_indices_update() { |
548 | | - $dbw = wfGetDB( DB_MASTER ); |
549 | | - wfOut( "Checking filearchive indices...\n" ); |
550 | | - $info = $dbw->indexInfo( 'filearchive', 'fa_user_timestamp', __METHOD__ ); |
551 | | - if ( !$info ) |
552 | | - { |
553 | | - $dbw->sourceFile( archive( 'patch-filearchive-user-index.sql' ) ); |
554 | | - wfOut( "...filearchive indices updated\n" ); |
555 | | - } |
556 | | -} |
557 | | - |
558 | | -function maybe_do_profiling_memory_update() { |
559 | | - $dbw = wfGetDB( DB_MASTER ); |
560 | | - if ( !$dbw->tableExists( 'profiling' ) ) { |
561 | | - // Simply ignore |
562 | | - } elseif ( $dbw->fieldExists( 'profiling', 'pf_memory' ) ) { |
563 | | - wfOut( "...profiling table has pf_memory field.\n" ); |
564 | | - } else { |
565 | | - wfOut( "Adding pf_memory field to table profiling..." ); |
566 | | - $dbw->sourceFile( archive( 'patch-profiling-memory.sql' ) ); |
567 | | - wfOut( "ok\n" ); |
568 | | - } |
569 | | -} |
570 | | - |
571 | | -function do_active_users_init() { |
572 | | - $dbw = wfGetDB( DB_MASTER ); |
573 | | - $activeUsers = $dbw->selectField( 'site_stats', 'ss_active_users', false, __METHOD__ ); |
574 | | - if ( $activeUsers == -1 ) { |
575 | | - $activeUsers = $dbw->selectField( 'recentchanges', |
576 | | - 'COUNT( DISTINCT rc_user_text )', |
577 | | - array( 'rc_user != 0', 'rc_bot' => 0, "rc_log_type != 'newusers'" ), __METHOD__ |
578 | | - ); |
579 | | - $dbw->update( 'site_stats', |
580 | | - array( 'ss_active_users' => intval( $activeUsers ) ), |
581 | | - array( 'ss_row_id' => 1 ), __METHOD__, array( 'LIMIT' => 1 ) |
582 | | - ); |
583 | | - } |
584 | | - wfOut( "...ss_active_users user count set...\n" ); |
585 | | -} |
586 | | - |
587 | | -/** |
588 | | - * Adding page_restrictions table, obsoleting page.page_restrictions. |
589 | | - * Migrating old restrictions to new table |
590 | | - * -- Andrew Garrett, January 2007. |
591 | | - */ |
592 | | -function do_restrictions_update() { |
593 | | - $dbw = wfGetDB( DB_MASTER ); |
594 | | - if ( $dbw->tableExists( 'page_restrictions' ) ) { |
595 | | - wfOut( "...page_restrictions table already exists.\n" ); |
596 | | - } else { |
597 | | - wfOut( "Creating page_restrictions table..." ); |
598 | | - $dbw->sourceFile( archive( 'patch-page_restrictions.sql' ) ); |
599 | | - $dbw->sourceFile( archive( 'patch-page_restrictions_sortkey.sql' ) ); |
600 | | - wfOut( "ok\n" ); |
601 | | - |
602 | | - wfOut( "Migrating old restrictions to new table...\n" ); |
603 | | - $task = new UpdateRestrictions(); |
604 | | - $task->execute(); |
605 | | - } |
606 | | -} |
607 | | - |
608 | | -function do_category_population() { |
609 | | - if ( update_row_exists( 'populate category' ) ) { |
610 | | - wfOut( "...category table already populated.\n" ); |
611 | | - return; |
612 | | - } |
613 | | - |
614 | | - wfOut( |
615 | | - "Populating category table, printing progress markers. " . |
616 | | - "For large databases, you\n" . |
617 | | - "may want to hit Ctrl-C and do this manually with maintenance/\n" . |
618 | | - "populateCategory.php.\n" |
619 | | - ); |
620 | | - $task = new PopulateCategory(); |
621 | | - $task->execute(); |
622 | | - wfOut( "Done populating category table.\n" ); |
623 | | -} |
624 | | - |
625 | | -function do_populate_parent_id() { |
626 | | - if ( update_row_exists( 'populate rev_parent_id' ) ) { |
627 | | - wfOut( "...rev_parent_id column already populated.\n" ); |
628 | | - return; |
629 | | - } |
630 | | - |
631 | | - $task = new PopulateParentId(); |
632 | | - $task->execute(); |
633 | | -} |
634 | | - |
635 | | -function do_populate_rev_len() { |
636 | | - if ( update_row_exists( 'populate rev_len' ) ) { |
637 | | - wfOut( "...rev_len column already populated.\n" ); |
638 | | - return; |
639 | | - } |
640 | | - |
641 | | - $task = new PopulateRevisionLength(); |
642 | | - $task->execute(); |
643 | | -} |
644 | | - |
645 | | -function do_cl_fields_update() { |
646 | | - if ( update_row_exists( 'cl_fields_update' ) ) { |
647 | | - wfOut( "...categorylinks up-to-date.\n" ); |
648 | | - return; |
649 | | - } |
650 | | - wfOut( 'Updating categorylinks (again)...' ); |
651 | | - wfGetDB( DB_MASTER )->sourceFile( archive( 'patch-categorylinks-better-collation2.sql' ) ); |
652 | | - wfOut( "done.\n" ); |
653 | | -} |
654 | | - |
655 | | -function do_collation_update() { |
656 | | - global $wgCategoryCollation; |
657 | | - $dbw = wfGetDB( DB_MASTER ); |
658 | | - if ( $dbw->selectField( |
659 | | - 'categorylinks', |
660 | | - 'COUNT(*)', |
661 | | - 'cl_collation != ' . $dbw->addQuotes( $wgCategoryCollation ), |
662 | | - __FUNCTION__ |
663 | | - ) == 0 ) { |
664 | | - wfOut( "...collations up-to-date.\n" ); |
665 | | - return; |
666 | | - } |
667 | | - |
668 | | - $task = new UpdateCollation(); |
669 | | - $task->execute(); |
670 | | -} |
671 | | - |
672 | | -function do_unique_pl_tl_il() { |
673 | | - $dbw = wfGetDB( DB_MASTER ); |
674 | | - $info = $dbw->indexInfo( 'pagelinks', 'pl_namespace' ); |
675 | | - if ( is_array( $info ) && !$info[0]->Non_unique ) { |
676 | | - wfOut( "...pl_namespace, tl_namespace, il_to indices are already UNIQUE.\n" ); |
677 | | - } else { |
678 | | - wfOut( "Making pl_namespace, tl_namespace and il_to indices UNIQUE... " ); |
679 | | - $dbw->sourceFile( archive( 'patch-pl-tl-il-unique.sql' ) ); |
680 | | - wfOut( "ok\n" ); |
681 | | - } |
682 | | -} |
683 | | - |
684 | | -function do_log_search_population() { |
685 | | - if ( update_row_exists( 'populate log_search' ) ) { |
686 | | - wfOut( "...log_search table already populated.\n" ); |
687 | | - return; |
688 | | - } |
689 | | - wfOut( |
690 | | -"Populating log_search table, printing progress markers. For large\n" . |
691 | | -"databases, you may want to hit Ctrl-C and do this manually with\n" . |
692 | | -"maintenance/populateLogSearch.php.\n" ); |
693 | | - $task = new PopulateLogSearch(); |
694 | | - $task->execute(); |
695 | | - wfOut( "Done populating log_search table.\n" ); |
696 | | -} |
697 | | - |
698 | | -function rename_eu_wiki_id() { |
699 | | - $dbw = wfGetDB( DB_MASTER ); |
700 | | - if ( $dbw->fieldExists( 'external_user', 'eu_local_id' ) ) { |
701 | | - wfOut( "...eu_wiki_id already renamed to eu_local_id.\n" ); |
702 | | - return; |
703 | | - } |
704 | | - wfOut( "Renaming eu_wiki_id -> eu_local_id... " ); |
705 | | - $dbw->sourceFile( archive( 'patch-eu_local_id.sql' ) ); |
706 | | - wfOut( "ok\n" ); |
707 | | -} |
708 | | - |
709 | | -function do_update_transcache_field() { |
710 | | - if ( update_row_exists( 'convert transcache field' ) ) { |
711 | | - wfOut( "...transcache tc_time already converted.\n" ); |
712 | | - return; |
713 | | - } else { |
714 | | - wfOut( "Converting tc_time from UNIX epoch to MediaWiki timestamp... " ); |
715 | | - wfGetDB( DB_MASTER )->sourceFile( archive( 'patch-tc-timestamp.sql' ) ); |
716 | | - wfOut( "ok\n" ); |
717 | | - } |
718 | | -} |
719 | | - |
720 | | -function do_update_mime_minor_field() { |
721 | | - if ( update_row_exists( 'mime_minor_length' ) ) { |
722 | | - wfOut( "...*_mime_minor fields are already long enough.\n" ); |
723 | | - } else { |
724 | | - wfOut( "Altering all *_mime_minor fields to 100 bytes in size ... " ); |
725 | | - wfGetDB( DB_MASTER )->sourceFile( archive( 'patch-mime_minor_length.sql' ) ); |
726 | | - wfOut( "ok\n" ); |
727 | | - } |
728 | | -} |
Index: trunk/phase3/maintenance/sqlite/archives/patch-categorylinks-better-collation.sql |
— | — | @@ -0,0 +1,7 @@ |
| 2 | +ALTER TABLE /*_*/categorylinks ADD COLUMN cl_sortkey_prefix TEXT binary NOT NULL default ''; |
| 3 | +ALTER TABLE /*_*/categorylinks ADD COLUMN cl_collation BLOB NOT NULL default ''; |
| 4 | +ALTER TABLE /*_*/categorylinks ADD COLUMN cl_type ENUM('page', 'subcat', 'file') NOT NULL default 'page'; |
| 5 | +CREATE INDEX cl_collation ON /*_*/categorylinks (cl_collation); |
| 6 | +DROP INDEX cl_sortkey; |
| 7 | +CREATE INDEX cl_sortkey ON /*_*/categorylinks (cl_to, cl_type, cl_sortkey, cl_from); |
| 8 | +INSERT IGNORE INTO /*_*/updatelog (ul_key) VALUES ('cl_fields_update'); |
Property changes on: trunk/phase3/maintenance/sqlite/archives/patch-categorylinks-better-collation.sql |
___________________________________________________________________ |
Added: svn:eol-style |
1 | 9 | + native |
Index: trunk/phase3/maintenance/install-utils.inc |
— | — | @@ -189,19 +189,9 @@ |
190 | 190 | } |
191 | 191 | } |
192 | 192 | |
193 | | -/** |
194 | | - * Helper function: check if the given key is present in the updatelog table. |
195 | | - * Obviously, only use this for updates that occur after the updatelog table was |
196 | | - * created! |
197 | | - */ |
198 | | -function update_row_exists( $key ) { |
199 | | - $row = wfGetDB( DB_MASTER )->selectRow( |
200 | | - 'updatelog', |
201 | | - '1', |
202 | | - array( 'ul_key' => $key ), |
203 | | - __FUNCTION__ |
204 | | - ); |
205 | | - return (bool)$row; |
| 193 | +function archive( $name ) { |
| 194 | + wfDeprecated( __METHOD__ ); |
| 195 | + return DatabaseBase::patchPath( $name ); |
206 | 196 | } |
207 | 197 | |
208 | 198 | /** |
Index: trunk/phase3/includes/installer/DatabaseUpdater.php |
— | — | @@ -123,8 +123,7 @@ |
124 | 124 | * @param $purge Boolean: whether to clear the objectcache table after updates |
125 | 125 | */ |
126 | 126 | public function doUpdates( $purge = true ) { |
127 | | - global $IP, $wgVersion; |
128 | | - require_once( "$IP/maintenance/updaters.inc" ); |
| 127 | + global $wgVersion; |
129 | 128 | |
130 | 129 | $this->runUpdates( $this->getCoreUpdateList(), false ); |
131 | 130 | $this->runUpdates( $this->getOldGlobalUpdates(), false ); |
— | — | @@ -170,6 +169,21 @@ |
171 | 170 | } |
172 | 171 | |
173 | 172 | /** |
| 173 | + * Helper function: check if the given key is present in the updatelog table. |
| 174 | + * Obviously, only use this for updates that occur after the updatelog table was |
| 175 | + * created! |
| 176 | + */ |
| 177 | + public function updateRowExists( $key ) { |
| 178 | + $row = $this->db->selectRow( |
| 179 | + 'updatelog', |
| 180 | + '1', |
| 181 | + array( 'ul_key' => $key ), |
| 182 | + __METHOD__ |
| 183 | + ); |
| 184 | + return (bool)$row; |
| 185 | + } |
| 186 | + |
| 187 | + /** |
174 | 188 | * Updatelog was changed in 1.17 to have a ul_value column so we can record |
175 | 189 | * more information about what kind of updates we've done (that's what this |
176 | 190 | * class does). Pre-1.17 wikis won't have this column, and really old wikis |
— | — | @@ -395,4 +409,62 @@ |
396 | 410 | SiteStatsInit::doAllAndCommit( false ); |
397 | 411 | } |
398 | 412 | |
| 413 | + # Common updater functions |
| 414 | + |
| 415 | + protected function doActiveUsersInit() { |
| 416 | + $activeUsers = $this->db->selectField( 'site_stats', 'ss_active_users', false, __METHOD__ ); |
| 417 | + if ( $activeUsers == -1 ) { |
| 418 | + $activeUsers = $this->db->selectField( 'recentchanges', |
| 419 | + 'COUNT( DISTINCT rc_user_text )', |
| 420 | + array( 'rc_user != 0', 'rc_bot' => 0, "rc_log_type != 'newusers'" ), __METHOD__ |
| 421 | + ); |
| 422 | + $this->db->update( 'site_stats', |
| 423 | + array( 'ss_active_users' => intval( $activeUsers ) ), |
| 424 | + array( 'ss_row_id' => 1 ), __METHOD__, array( 'LIMIT' => 1 ) |
| 425 | + ); |
| 426 | + } |
| 427 | + wfOut( "...ss_active_users user count set...\n" ); |
| 428 | + } |
| 429 | + |
| 430 | + protected function doLogSearchPopulation() { |
| 431 | + if ( $this->updateRowExists( 'populate log_search' ) ) { |
| 432 | + wfOut( "...log_search table already populated.\n" ); |
| 433 | + return; |
| 434 | + } |
| 435 | + |
| 436 | + wfOut( |
| 437 | + "Populating log_search table, printing progress markers. For large\n" . |
| 438 | + "databases, you may want to hit Ctrl-C and do this manually with\n" . |
| 439 | + "maintenance/populateLogSearch.php.\n" ); |
| 440 | + $task = new PopulateLogSearch(); |
| 441 | + $task->execute(); |
| 442 | + wfOut( "Done populating log_search table.\n" ); |
| 443 | + } |
| 444 | + |
| 445 | + function doUpdateTranscacheField() { |
| 446 | + if ( $this->updateRowExists( 'convert transcache field' ) ) { |
| 447 | + wfOut( "...transcache tc_time already converted.\n" ); |
| 448 | + return; |
| 449 | + } |
| 450 | + |
| 451 | + wfOut( "Converting tc_time from UNIX epoch to MediaWiki timestamp... " ); |
| 452 | + $this->applyPatch( 'patch-tc-timestamp.sql' ); |
| 453 | + wfOut( "ok\n" ); |
| 454 | + } |
| 455 | + |
| 456 | + protected function doCollationUpdate() { |
| 457 | + global $wgCategoryCollation; |
| 458 | + if ( $this->db->selectField( |
| 459 | + 'categorylinks', |
| 460 | + 'COUNT(*)', |
| 461 | + 'cl_collation != ' . $this->db->addQuotes( $wgCategoryCollation ), |
| 462 | + __METHOD__ |
| 463 | + ) == 0 ) { |
| 464 | + wfOut( "...collations up-to-date.\n" ); |
| 465 | + return; |
| 466 | + } |
| 467 | + |
| 468 | + $task = new UpdateCollation(); |
| 469 | + $task->execute(); |
| 470 | + } |
399 | 471 | } |
Index: trunk/phase3/includes/installer/MysqlUpdater.php |
— | — | @@ -19,8 +19,8 @@ |
20 | 20 | // 1.2 |
21 | 21 | array( 'addField', 'ipblocks', 'ipb_id', 'patch-ipblocks.sql' ), |
22 | 22 | array( 'addField', 'ipblocks', 'ipb_expiry', 'patch-ipb_expiry.sql' ), |
23 | | - array( 'do_interwiki_update' ), |
24 | | - array( 'do_index_update' ), |
| 23 | + array( 'doInterwikiUpdate' ), |
| 24 | + array( 'doIndexUpdate' ), |
25 | 25 | array( 'addTable', 'hitcounter', 'patch-hitcounter.sql' ), |
26 | 26 | array( 'addField', 'recentchanges', 'rc_type', 'patch-rc_type.sql' ), |
27 | 27 | |
— | — | @@ -29,24 +29,24 @@ |
30 | 30 | array( 'addTable', 'querycache', 'patch-querycache.sql' ), |
31 | 31 | array( 'addTable', 'objectcache', 'patch-objectcache.sql' ), |
32 | 32 | array( 'addTable', 'categorylinks', 'patch-categorylinks.sql' ), |
33 | | - array( 'do_old_links_update' ), |
34 | | - array( 'fix_ancient_imagelinks' ), |
| 33 | + array( 'doOldLinksUpdate' ), |
| 34 | + array( 'doFixAncientImagelinks' ), |
35 | 35 | array( 'addField', 'recentchanges', 'rc_ip', 'patch-rc_ip.sql' ), |
36 | 36 | |
37 | 37 | // 1.4 |
38 | | - array( 'do_image_name_unique_update' ), |
| 38 | + array( 'addIndex', 'image', 'PRIMARY', 'patch-image_name_primary.sql' ), |
39 | 39 | array( 'addField', 'recentchanges', 'rc_id', 'patch-rc_id.sql' ), |
40 | 40 | array( 'addField', 'recentchanges', 'rc_patrolled', 'patch-rc-patrol.sql' ), |
41 | 41 | array( 'addTable', 'logging', 'patch-logging.sql' ), |
42 | 42 | array( 'addField', 'user', 'user_token', 'patch-user_token.sql' ), |
43 | 43 | array( 'addField', 'watchlist', 'wl_notificationtimestamp', 'patch-email-notification.sql' ), |
44 | | - array( 'do_watchlist_update' ), |
| 44 | + array( 'doWatchlistUpdate' ), |
45 | 45 | array( 'dropField', 'user', 'user_emailauthenticationtimestamp', 'patch-email-authentication.sql' ), |
46 | 46 | |
47 | 47 | // 1.5 |
48 | | - array( 'do_schema_restructuring' ), |
| 48 | + array( 'doSchemaRestructuring' ), |
49 | 49 | array( 'addField', 'logging', 'log_params', 'patch-log_params.sql' ), |
50 | | - array( 'check_bin', 'logging', 'log_title', 'patch-logging-title.sql', ), |
| 50 | + array( 'checkBin', 'logging', 'log_title', 'patch-logging-title.sql', ), |
51 | 51 | array( 'addField', 'archive', 'ar_rev_id', 'patch-archive-rev_id.sql' ), |
52 | 52 | array( 'addField', 'page', 'page_len', 'patch-page_len.sql' ), |
53 | 53 | array( 'dropField', 'revision', 'inverse_timestamp', 'patch-inverse_timestamp.sql' ), |
— | — | @@ -58,10 +58,10 @@ |
59 | 59 | array( 'addField', 'archive', 'ar_text_id', 'patch-archive-text_id.sql' ), |
60 | 60 | array( 'doNamespaceSize' ), |
61 | 61 | array( 'addField', 'image', 'img_media_type', 'patch-img_media_type.sql' ), |
62 | | - array( 'do_pagelinks_update' ), |
| 62 | + array( 'doPagelinksUpdate' ), |
63 | 63 | array( 'dropField', 'image', 'img_type', 'patch-drop_img_type.sql' ), |
64 | | - array( 'do_user_unique_update' ), |
65 | | - array( 'do_user_groups_update' ), |
| 64 | + array( 'doUserUniqueUpdate' ), |
| 65 | + array( 'doUserGroupsUpdate' ), |
66 | 66 | array( 'addField', 'site_stats', 'ss_total_pages', 'patch-ss_total_articles.sql' ), |
67 | 67 | array( 'addTable', 'user_newtalk', 'patch-usernewtalk2.sql' ), |
68 | 68 | array( 'addTable', 'transcache', 'patch-transcache.sql' ), |
— | — | @@ -69,12 +69,12 @@ |
70 | 70 | array( 'addTable', 'trackbacks', 'patch-trackbacks.sql' ), |
71 | 71 | |
72 | 72 | // 1.6 |
73 | | - array( 'do_watchlist_null' ), |
| 73 | + array( 'doWatchlistNull' ), |
74 | 74 | array( 'addIndex', 'logging', 'times', 'patch-logging-times-index.sql' ), |
75 | 75 | array( 'addField', 'ipblocks', 'ipb_range_start', 'patch-ipb_range_start.sql' ), |
76 | | - array( 'do_page_random_update' ), |
| 76 | + array( 'doPageRandomUpdate' ), |
77 | 77 | array( 'addField', 'user', 'user_registration', 'patch-user_registration.sql' ), |
78 | | - array( 'do_templatelinks_update' ), |
| 78 | + array( 'doTemplatelinksUpdate' ), |
79 | 79 | array( 'addTable', 'externallinks', 'patch-externallinks.sql' ), |
80 | 80 | array( 'addTable', 'job', 'patch-job.sql' ), |
81 | 81 | array( 'addField', 'site_stats', 'ss_images', 'patch-ss_images.sql' ), |
— | — | @@ -82,19 +82,20 @@ |
83 | 83 | array( 'addTable', 'querycache_info', 'patch-querycacheinfo.sql' ), |
84 | 84 | array( 'addTable', 'filearchive', 'patch-filearchive.sql' ), |
85 | 85 | array( 'addField', 'ipblocks', 'ipb_anon_only', 'patch-ipb_anon_only.sql' ), |
86 | | - array( 'do_rc_indices_update' ), |
| 86 | + array( 'addIndex', 'recentchanges', 'rc_ns_usertext', 'patch-recentchanges-utindex.sql' ), |
| 87 | + array( 'addIndex', 'recentchanges', 'rc_user_text', 'patch-rc_user_text-index.sql' ), |
87 | 88 | |
88 | 89 | // 1.9 |
89 | 90 | array( 'addField', 'user', 'user_newpass_time', 'patch-user_newpass_time.sql' ), |
90 | 91 | array( 'addTable', 'redirect', 'patch-redirect.sql' ), |
91 | 92 | array( 'addTable', 'querycachetwo', 'patch-querycachetwo.sql' ), |
92 | 93 | array( 'addField', 'ipblocks', 'ipb_enable_autoblock', 'patch-ipb_optional_autoblock.sql' ), |
93 | | - array( 'do_backlinking_indices_update' ), |
| 94 | + array( 'doBacklinkingIndicesUpdate' ), |
94 | 95 | array( 'addField', 'recentchanges', 'rc_old_len', 'patch-rc_len.sql' ), |
95 | 96 | array( 'addField', 'user', 'user_editcount', 'patch-user_editcount.sql' ), |
96 | 97 | |
97 | 98 | // 1.10 |
98 | | - array( 'do_restrictions_update' ), |
| 99 | + array( 'doRestrictionsUpdate' ), |
99 | 100 | array( 'addField', 'logging', 'log_id', 'patch-log_id.sql' ), |
100 | 101 | array( 'addField', 'revision', 'rev_parent_id', 'patch-rev_parent_id.sql' ), |
101 | 102 | array( 'addField', 'page_restrictions', 'pr_id', 'patch-page_restrictions_sortkey.sql' ), |
— | — | @@ -108,7 +109,7 @@ |
109 | 110 | |
110 | 111 | // 1.11 |
111 | 112 | array( 'addField', 'ipblocks', 'ipb_block_email', 'patch-ipb_emailban.sql' ), |
112 | | - array( 'do_categorylinks_indices_update' ), |
| 113 | + array( 'doCategorylinksIndicesUpdate' ), |
113 | 114 | array( 'addField', 'oldimage', 'oi_metadata', 'patch-oi_metadata.sql' ), |
114 | 115 | array( 'addIndex', 'archive', 'usertext_timestamp', 'patch-archive-user-index.sql' ), |
115 | 116 | array( 'addIndex', 'image', 'img_usertext_timestamp', 'patch-image-user-index.sql' ), |
— | — | @@ -124,21 +125,21 @@ |
125 | 126 | array( 'addTable', 'page_props', 'patch-page_props.sql' ), |
126 | 127 | array( 'addTable', 'updatelog', 'patch-updatelog.sql' ), |
127 | 128 | array( 'addTable', 'category', 'patch-category.sql' ), |
128 | | - array( 'do_category_population' ), |
| 129 | + array( 'doCategoryPopulation' ), |
129 | 130 | array( 'addField', 'archive', 'ar_parent_id', 'patch-ar_parent_id.sql' ), |
130 | 131 | array( 'addField', 'user_newtalk', 'user_last_timestamp', 'patch-user_last_timestamp.sql' ), |
131 | | - array( 'do_populate_parent_id' ), |
132 | | - array( 'check_bin', 'protected_titles', 'pt_title', 'patch-pt_title-encoding.sql', ), |
133 | | - array( 'maybe_do_profiling_memory_update' ), |
134 | | - array( 'do_filearchive_indices_update' ), |
| 132 | + array( 'doPopulateParentId' ), |
| 133 | + array( 'checkBin', 'protected_titles', 'pt_title', 'patch-pt_title-encoding.sql', ), |
| 134 | + array( 'doMaybeProfilingMemoryUpdate' ), |
| 135 | + array( 'doFilearchiveIndicesUpdate' ), |
135 | 136 | |
136 | 137 | // 1.14 |
137 | 138 | array( 'addField', 'site_stats', 'ss_active_users', 'patch-ss_active_users.sql' ), |
138 | | - array( 'do_active_users_init' ), |
| 139 | + array( 'doActiveUsersInit' ), |
139 | 140 | array( 'addField', 'ipblocks', 'ipb_allow_usertalk', 'patch-ipb_allow_usertalk.sql' ), |
140 | 141 | |
141 | 142 | // 1.15 |
142 | | - array( 'do_unique_pl_tl_il' ), |
| 143 | + array( 'doUniquePlTlIl' ), |
143 | 144 | array( 'addTable', 'change_tag', 'patch-change_tag.sql' ), |
144 | 145 | array( 'addTable', 'tag_summary', 'patch-change_tag.sql' ), |
145 | 146 | array( 'addTable', 'valid_tag', 'patch-change_tag.sql' ), |
— | — | @@ -146,17 +147,17 @@ |
147 | 148 | // 1.16 |
148 | 149 | array( 'addTable', 'user_properties', 'patch-user_properties.sql' ), |
149 | 150 | array( 'addTable', 'log_search', 'patch-log_search.sql' ), |
150 | | - array( 'do_log_search_population' ), |
| 151 | + array( 'doLogSearchPopulation' ), |
151 | 152 | array( 'addField', 'logging', 'log_user_text', 'patch-log_user_text.sql' ), |
152 | 153 | array( 'addTable', 'l10n_cache', 'patch-l10n_cache.sql' ), |
153 | 154 | array( 'addTable', 'external_user', 'patch-external_user.sql' ), |
154 | 155 | array( 'addIndex', 'log_search', 'ls_field_val', 'patch-log_search-rename-index.sql' ), |
155 | 156 | array( 'addIndex', 'change_tag', 'change_tag_rc_tag', 'patch-change_tag-indexes.sql' ), |
156 | 157 | array( 'addField', 'redirect', 'rd_interwiki', 'patch-rd_interwiki.sql' ), |
157 | | - array( 'do_update_transcache_field' ), |
158 | | - array( 'rename_eu_wiki_id' ), |
159 | | - array( 'do_update_mime_minor_field' ), |
160 | | - array( 'do_populate_rev_len' ), |
| 158 | + array( 'doUpdateTranscacheField' ), |
| 159 | + array( 'renameEuWikiId' ), |
| 160 | + array( 'doUpdateMimeMinorField' ), |
| 161 | + array( 'doPopulateRevLen' ), |
161 | 162 | |
162 | 163 | // 1.17 |
163 | 164 | array( 'addTable', 'iwlinks', 'patch-iwlinks.sql' ), |
— | — | @@ -166,13 +167,296 @@ |
167 | 168 | array( 'dropIndex', 'iwlinks', 'iwl_prefix', 'patch-kill-iwl_prefix.sql' ), |
168 | 169 | array( 'dropIndex', 'iwlinks', 'iwl_prefix_from_title', 'patch-kill-iwl_pft.sql' ), |
169 | 170 | array( 'addField', 'categorylinks', 'cl_collation', 'patch-categorylinks-better-collation.sql' ), |
170 | | - array( 'do_cl_fields_update' ), |
171 | | - array( 'do_collation_update' ), |
| 171 | + array( 'doClFieldsUpdate' ), |
| 172 | + array( 'doCollationUpdate' ), |
172 | 173 | array( 'addTable', 'msg_resource', 'patch-msg_resource.sql' ), |
173 | 174 | array( 'addTable', 'module_deps', 'patch-module_deps.sql' ), |
174 | 175 | ); |
175 | 176 | } |
176 | 177 | |
| 178 | + /** |
| 179 | + * 1.4 betas were missing the 'binary' marker from logging.log_title, |
| 180 | + * which causes a collation mismatch error on joins in MySQL 4.1. |
| 181 | + * |
| 182 | + * @param $table String: table name |
| 183 | + * @param $field String: field name to check |
| 184 | + * @param $patchFile String: path to the patch to correct the field |
| 185 | + */ |
| 186 | + protected function checkBin( $table, $field, $patchFile ) { |
| 187 | + $tableName = $this->db->tableName( $table ); |
| 188 | + $res = $this->db->query( "SELECT $field FROM $tableName LIMIT 0", __METHOD__ ); |
| 189 | + $flags = explode( ' ', mysql_field_flags( $res->result, 0 ) ); |
| 190 | + |
| 191 | + if ( in_array( 'binary', $flags ) ) { |
| 192 | + wfOut( "...$table table has correct $field encoding.\n" ); |
| 193 | + } else { |
| 194 | + wfOut( "Fixing $field encoding on $table table... " ); |
| 195 | + $this->db->applyPatch( $patchFile ); |
| 196 | + wfOut( "ok\n" ); |
| 197 | + } |
| 198 | + } |
| 199 | + |
| 200 | + /** |
| 201 | + * Check whether an index contain a field |
| 202 | + * |
| 203 | + * @param $table String: table name |
| 204 | + * @param $index String: index name to check |
| 205 | + * @param $field String: field that should be in the index |
| 206 | + * @return Boolean |
| 207 | + */ |
| 208 | + protected function indexHasField( $table, $index, $field ) { |
| 209 | + $info = $this->db->indexInfo( $table, $index, __METHOD__ ); |
| 210 | + if ( $info ) { |
| 211 | + foreach ( $info as $row ) { |
| 212 | + if ( $row->Column_name == $field ) { |
| 213 | + wfOut( "...index $index on table $table includes field $field\n" ); |
| 214 | + return true; |
| 215 | + } |
| 216 | + } |
| 217 | + } |
| 218 | + wfOut( "...index $index on table $table has no field $field; adding\n" ); |
| 219 | + return false; |
| 220 | + } |
| 221 | + |
| 222 | + /** |
| 223 | + * Check that interwiki table exists; if it doesn't source it |
| 224 | + */ |
| 225 | + protected function doInterwikiUpdate() { |
| 226 | + global $IP; |
| 227 | + |
| 228 | + if ( $this->db->tableExists( "interwiki" ) ) { |
| 229 | + wfOut( "...already have interwiki table\n" ); |
| 230 | + return; |
| 231 | + } |
| 232 | + |
| 233 | + wfOut( 'Creating interwiki table...' ); |
| 234 | + $this->applyPatch( 'patch-interwiki.sql' ); |
| 235 | + wfOut( "ok\n" ); |
| 236 | + wfOut( 'Adding default interwiki definitions...' ); |
| 237 | + $this->applyPatch( "$IP/maintenance/interwiki.sql", true ); |
| 238 | + wfOut( "ok\n" ); |
| 239 | + } |
| 240 | + |
| 241 | + /** |
| 242 | + * Check that proper indexes are in place |
| 243 | + */ |
| 244 | + protected function doIndexUpdate() { |
| 245 | + $meta = $this->db->fieldInfo( 'recentchanges', 'rc_timestamp' ); |
| 246 | + if ( $meta->isMultipleKey() ) { |
| 247 | + wfOut( "...indexes seem up to 20031107 standards\n" ); |
| 248 | + return; |
| 249 | + } |
| 250 | + |
| 251 | + wfOut( "Updating indexes to 20031107..." ); |
| 252 | + $this->applyPatch( 'patch-indexes.sql', true ); |
| 253 | + wfOut( "ok\n" ); |
| 254 | + } |
| 255 | + |
| 256 | + protected function doOldLinksUpdate() { |
| 257 | + $cl = new ConvertLinks(); |
| 258 | + $cl->execute(); |
| 259 | + } |
| 260 | + |
| 261 | + protected function doFixAncientImagelinks() { |
| 262 | + $info = $this->db->fieldInfo( 'imagelinks', 'il_from' ); |
| 263 | + if ( !$info || $info->type() !== 'string' ) { |
| 264 | + wfOut( "...il_from OK\n" ); |
| 265 | + return; |
| 266 | + } |
| 267 | + |
| 268 | + wfOut( "Fixing ancient broken imagelinks table.\n" ); |
| 269 | + wfOut( "NOTE: you will have to run maintenance/refreshLinks.php after this.\n" ); |
| 270 | + $this->applyPatch( 'patch-fix-il_from.sql' ); |
| 271 | + wfOut( "ok\n" ); |
| 272 | + } |
| 273 | + |
| 274 | + /** |
| 275 | + * Check if we need to add talk page rows to the watchlist |
| 276 | + */ |
| 277 | + function doWatchlistUpdate() { |
| 278 | + $talk = $this->db->selectField( 'watchlist', 'count(*)', 'wl_namespace & 1', __METHOD__ ); |
| 279 | + $nontalk = $this->db->selectField( 'watchlist', 'count(*)', 'NOT (wl_namespace & 1)', __METHOD__ ); |
| 280 | + if ( $talk == $nontalk ) { |
| 281 | + wfOut( "...watchlist talk page rows already present\n" ); |
| 282 | + return; |
| 283 | + } |
| 284 | + |
| 285 | + wfOut( "Adding missing watchlist talk page rows... " ); |
| 286 | + $this->db->insertSelect( 'watchlist', 'watchlist', |
| 287 | + array( |
| 288 | + 'wl_user' => 'wl_user', |
| 289 | + 'wl_namespace' => 'wl_namespace | 1', |
| 290 | + 'wl_title' => 'wl_title', |
| 291 | + 'wl_notificationtimestamp' => 'wl_notificationtimestamp' |
| 292 | + ), array( 'NOT (wl_namespace & 1)' ), __METHOD__, 'IGNORE' ); |
| 293 | + wfOut( "ok\n" ); |
| 294 | + } |
| 295 | + |
| 296 | + function doSchemaRestructuring() { |
| 297 | + if ( $this->db->tableExists( 'page' ) ) { |
| 298 | + wfOut( "...page table already exists.\n" ); |
| 299 | + return; |
| 300 | + } |
| 301 | + |
| 302 | + wfOut( "...converting from cur/old to page/revision/text DB structure.\n" ); |
| 303 | + wfOut( wfTimestamp( TS_DB ) ); |
| 304 | + wfOut( "......checking for duplicate entries.\n" ); |
| 305 | + |
| 306 | + list ( $cur, $old, $page, $revision, $text ) = $this->db->tableNamesN( 'cur', 'old', 'page', 'revision', 'text' ); |
| 307 | + |
| 308 | + $rows = $this->db->query( "SELECT cur_title, cur_namespace, COUNT(cur_namespace) AS c |
| 309 | + FROM $cur GROUP BY cur_title, cur_namespace HAVING c>1", __METHOD__ ); |
| 310 | + |
| 311 | + if ( $rows->numRows() > 0 ) { |
| 312 | + wfOut( wfTimestamp( TS_DB ) ); |
| 313 | + wfOut( "......<b>Found duplicate entries</b>\n" ); |
| 314 | + wfOut( sprintf( "<b> %-60s %3s %5s</b>\n", 'Title', 'NS', 'Count' ) ); |
| 315 | + foreach ( $rows as $row ) { |
| 316 | + if ( ! isset( $duplicate[$row->cur_namespace] ) ) { |
| 317 | + $duplicate[$row->cur_namespace] = array(); |
| 318 | + } |
| 319 | + $duplicate[$row->cur_namespace][] = $row->cur_title; |
| 320 | + wfOut( sprintf( " %-60s %3s %5s\n", $row->cur_title, $row->cur_namespace, $row->c ) ); |
| 321 | + } |
| 322 | + $sql = "SELECT cur_title, cur_namespace, cur_id, cur_timestamp FROM $cur WHERE "; |
| 323 | + $firstCond = true; |
| 324 | + foreach ( $duplicate as $ns => $titles ) { |
| 325 | + if ( $firstCond ) { |
| 326 | + $firstCond = false; |
| 327 | + } else { |
| 328 | + $sql .= ' OR '; |
| 329 | + } |
| 330 | + $sql .= "( cur_namespace = {$ns} AND cur_title in ("; |
| 331 | + $first = true; |
| 332 | + foreach ( $titles as $t ) { |
| 333 | + if ( $first ) { |
| 334 | + $sql .= $this->db->addQuotes( $t ); |
| 335 | + $first = false; |
| 336 | + } else { |
| 337 | + $sql .= ', ' . $this->db->addQuotes( $t ); |
| 338 | + } |
| 339 | + } |
| 340 | + $sql .= ") ) \n"; |
| 341 | + } |
| 342 | + # By sorting descending, the most recent entry will be the first in the list. |
| 343 | + # All following entries will be deleted by the next while-loop. |
| 344 | + $sql .= 'ORDER BY cur_namespace, cur_title, cur_timestamp DESC'; |
| 345 | + |
| 346 | + $rows = $this->db->query( $sql, __METHOD__ ); |
| 347 | + |
| 348 | + $prev_title = $prev_namespace = false; |
| 349 | + $deleteId = array(); |
| 350 | + |
| 351 | + foreach ( $rows as $row ) { |
| 352 | + if ( $prev_title == $row->cur_title && $prev_namespace == $row->cur_namespace ) { |
| 353 | + $deleteId[] = $row->cur_id; |
| 354 | + } |
| 355 | + $prev_title = $row->cur_title; |
| 356 | + $prev_namespace = $row->cur_namespace; |
| 357 | + } |
| 358 | + $sql = "DELETE FROM $cur WHERE cur_id IN ( " . join( ',', $deleteId ) . ')'; |
| 359 | + $rows = $this->db->query( $sql, __METHOD__ ); |
| 360 | + wfOut( wfTimestamp( TS_DB ) ); |
| 361 | + wfOut( "......<b>Deleted</b> " . $this->db->affectedRows() . " records.\n" ); |
| 362 | + } |
| 363 | + |
| 364 | + |
| 365 | + wfOut( wfTimestamp( TS_DB ) ); |
| 366 | + wfOut( "......Creating tables.\n" ); |
| 367 | + $this->db->query( "CREATE TABLE $page ( |
| 368 | + page_id int(8) unsigned NOT NULL auto_increment, |
| 369 | + page_namespace int NOT NULL, |
| 370 | + page_title varchar(255) binary NOT NULL, |
| 371 | + page_restrictions tinyblob NOT NULL, |
| 372 | + page_counter bigint(20) unsigned NOT NULL default '0', |
| 373 | + page_is_redirect tinyint(1) unsigned NOT NULL default '0', |
| 374 | + page_is_new tinyint(1) unsigned NOT NULL default '0', |
| 375 | + page_random real unsigned NOT NULL, |
| 376 | + page_touched char(14) binary NOT NULL default '', |
| 377 | + page_latest int(8) unsigned NOT NULL, |
| 378 | + page_len int(8) unsigned NOT NULL, |
| 379 | + |
| 380 | + PRIMARY KEY page_id (page_id), |
| 381 | + UNIQUE INDEX name_title (page_namespace,page_title), |
| 382 | + INDEX (page_random), |
| 383 | + INDEX (page_len) |
| 384 | + ) ENGINE=InnoDB", __METHOD__ ); |
| 385 | + $this->db->query( "CREATE TABLE $revision ( |
| 386 | + rev_id int(8) unsigned NOT NULL auto_increment, |
| 387 | + rev_page int(8) unsigned NOT NULL, |
| 388 | + rev_comment tinyblob NOT NULL, |
| 389 | + rev_user int(5) unsigned NOT NULL default '0', |
| 390 | + rev_user_text varchar(255) binary NOT NULL default '', |
| 391 | + rev_timestamp char(14) binary NOT NULL default '', |
| 392 | + rev_minor_edit tinyint(1) unsigned NOT NULL default '0', |
| 393 | + rev_deleted tinyint(1) unsigned NOT NULL default '0', |
| 394 | + rev_len int(8) unsigned, |
| 395 | + rev_parent_id int(8) unsigned default NULL, |
| 396 | + PRIMARY KEY rev_page_id (rev_page, rev_id), |
| 397 | + UNIQUE INDEX rev_id (rev_id), |
| 398 | + INDEX rev_timestamp (rev_timestamp), |
| 399 | + INDEX page_timestamp (rev_page,rev_timestamp), |
| 400 | + INDEX user_timestamp (rev_user,rev_timestamp), |
| 401 | + INDEX usertext_timestamp (rev_user_text,rev_timestamp) |
| 402 | + ) ENGINE=InnoDB", __METHOD__ ); |
| 403 | + |
| 404 | + wfOut( wfTimestamp( TS_DB ) ); |
| 405 | + wfOut( "......Locking tables.\n" ); |
| 406 | + $this->db->query( "LOCK TABLES $page WRITE, $revision WRITE, $old WRITE, $cur WRITE", __METHOD__ ); |
| 407 | + |
| 408 | + $maxold = intval( $this->db->selectField( 'old', 'max(old_id)', '', __METHOD__ ) ); |
| 409 | + wfOut( wfTimestamp( TS_DB ) ); |
| 410 | + wfOut( "......maxold is {$maxold}\n" ); |
| 411 | + |
| 412 | + wfOut( wfTimestamp( TS_DB ) ); |
| 413 | + global $wgLegacySchemaConversion; |
| 414 | + if ( $wgLegacySchemaConversion ) { |
| 415 | + // Create HistoryBlobCurStub entries. |
| 416 | + // Text will be pulled from the leftover 'cur' table at runtime. |
| 417 | + wfOut( "......Moving metadata from cur; using blob references to text in cur table.\n" ); |
| 418 | + $cur_text = "concat('O:18:\"historyblobcurstub\":1:{s:6:\"mCurId\";i:',cur_id,';}')"; |
| 419 | + $cur_flags = "'object'"; |
| 420 | + } else { |
| 421 | + // Copy all cur text in immediately: this may take longer but avoids |
| 422 | + // having to keep an extra table around. |
| 423 | + wfOut( "......Moving text from cur.\n" ); |
| 424 | + $cur_text = 'cur_text'; |
| 425 | + $cur_flags = "''"; |
| 426 | + } |
| 427 | + $this->db->query( "INSERT INTO $old (old_namespace, old_title, old_text, old_comment, old_user, old_user_text, |
| 428 | + old_timestamp, old_minor_edit, old_flags) |
| 429 | + SELECT cur_namespace, cur_title, $cur_text, cur_comment, cur_user, cur_user_text, cur_timestamp, cur_minor_edit, $cur_flags |
| 430 | + FROM $cur", __METHOD__ ); |
| 431 | + |
| 432 | + wfOut( wfTimestamp( TS_DB ) ); |
| 433 | + wfOut( "......Setting up revision table.\n" ); |
| 434 | + $this->db->query( "INSERT INTO $revision (rev_id, rev_page, rev_comment, rev_user, rev_user_text, rev_timestamp, |
| 435 | + rev_minor_edit) |
| 436 | + SELECT old_id, cur_id, old_comment, old_user, old_user_text, |
| 437 | + old_timestamp, old_minor_edit |
| 438 | + FROM $old,$cur WHERE old_namespace=cur_namespace AND old_title=cur_title", __METHOD__ ); |
| 439 | + |
| 440 | + wfOut( wfTimestamp( TS_DB ) ); |
| 441 | + wfOut( "......Setting up page table.\n" ); |
| 442 | + $this->db->query( "INSERT INTO $page (page_id, page_namespace, page_title, page_restrictions, page_counter, |
| 443 | + page_is_redirect, page_is_new, page_random, page_touched, page_latest, page_len) |
| 444 | + SELECT cur_id, cur_namespace, cur_title, cur_restrictions, cur_counter, cur_is_redirect, cur_is_new, |
| 445 | + cur_random, cur_touched, rev_id, LENGTH(cur_text) |
| 446 | + FROM $cur,$revision |
| 447 | + WHERE cur_id=rev_page AND rev_timestamp=cur_timestamp AND rev_id > {$maxold}", __METHOD__ ); |
| 448 | + |
| 449 | + wfOut( wfTimestamp( TS_DB ) ); |
| 450 | + wfOut( "......Unlocking tables.\n" ); |
| 451 | + $this->db->query( "UNLOCK TABLES", __METHOD__ ); |
| 452 | + |
| 453 | + wfOut( wfTimestamp( TS_DB ) ); |
| 454 | + wfOut( "......Renaming old.\n" ); |
| 455 | + $this->db->query( "ALTER TABLE $old RENAME TO $text", __METHOD__ ); |
| 456 | + |
| 457 | + wfOut( wfTimestamp( TS_DB ) ); |
| 458 | + wfOut( "...done.\n" ); |
| 459 | + } |
| 460 | + |
177 | 461 | protected function doNamespaceSize() { |
178 | 462 | $tables = array( |
179 | 463 | 'page' => 'page', |
— | — | @@ -198,4 +482,330 @@ |
199 | 483 | } |
200 | 484 | } |
201 | 485 | } |
| 486 | + |
| 487 | + protected function doPagelinksUpdate() { |
| 488 | + if ( $this->db->tableExists( 'pagelinks' ) ) { |
| 489 | + wfOut( "...already have pagelinks table.\n" ); |
| 490 | + return; |
| 491 | + } |
| 492 | + |
| 493 | + wfOut( "Converting links and brokenlinks tables to pagelinks... " ); |
| 494 | + $this->applyPatch( 'patch-pagelinks.sql' ); |
| 495 | + wfOut( "ok\n" ); |
| 496 | + |
| 497 | + global $wgContLang; |
| 498 | + foreach ( MWNamespace::getCanonicalNamespaces() as $ns => $name ) { |
| 499 | + if ( $ns == 0 ) { |
| 500 | + continue; |
| 501 | + } |
| 502 | + |
| 503 | + wfOut( "Cleaning up broken links for namespace $ns... " ); |
| 504 | + |
| 505 | + $pagelinks = $this->db->tableName( 'pagelinks' ); |
| 506 | + $name = $wgContLang->getNsText( $ns ); |
| 507 | + $prefix = $this->db->strencode( $name ); |
| 508 | + $likeprefix = str_replace( '_', '\\_', $prefix ); |
| 509 | + |
| 510 | + $sql = "UPDATE $pagelinks |
| 511 | + SET pl_namespace=$ns, |
| 512 | + pl_title=TRIM(LEADING '$prefix:' FROM pl_title) |
| 513 | + WHERE pl_namespace=0 |
| 514 | + AND pl_title LIKE '$likeprefix:%'"; |
| 515 | + |
| 516 | + $this->db->query( $sql, __METHOD__ ); |
| 517 | + wfOut( "ok\n" ); |
| 518 | + } |
| 519 | + } |
| 520 | + |
| 521 | + protected function doUserUniqueUpdate() { |
| 522 | + $duper = new UserDupes( $this->db ); |
| 523 | + if ( $duper->hasUniqueIndex() ) { |
| 524 | + wfOut( "...already have unique user_name index.\n" ); |
| 525 | + return; |
| 526 | + } |
| 527 | + |
| 528 | + if ( !$duper->clearDupes() ) { |
| 529 | + wfOut( "WARNING: This next step will probably fail due to unfixed duplicates...\n" ); |
| 530 | + } |
| 531 | + wfOut( "Adding unique index on user_name... " ); |
| 532 | + $this->applyPatch( 'patch-user_nameindex.sql' ); |
| 533 | + wfOut( "ok\n" ); |
| 534 | + } |
| 535 | + |
| 536 | + protected function doUserGroupsUpdate() { |
| 537 | + if ( $this->db->tableExists( 'user_groups' ) ) { |
| 538 | + $info = $this->db->fieldInfo( 'user_groups', 'ug_group' ); |
| 539 | + if ( $info->type() == 'int' ) { |
| 540 | + $oldug = $this->db->tableName( 'user_groups' ); |
| 541 | + $newug = $this->db->tableName( 'user_groups_bogus' ); |
| 542 | + wfOut( "user_groups table exists but is in bogus intermediate format. Renaming to $newug... " ); |
| 543 | + $this->db->query( "ALTER TABLE $oldug RENAME TO $newug", __METHOD__ ); |
| 544 | + wfOut( "ok\n" ); |
| 545 | + |
| 546 | + wfOut( "Re-adding fresh user_groups table... " ); |
| 547 | + $this->applyPatch( 'patch-user_groups.sql' ); |
| 548 | + wfOut( "ok\n" ); |
| 549 | + |
| 550 | + wfOut( "***\n" ); |
| 551 | + wfOut( "*** WARNING: You will need to manually fix up user permissions in the user_groups\n" ); |
| 552 | + wfOut( "*** table. Old 1.5 alpha versions did some pretty funky stuff...\n" ); |
| 553 | + wfOut( "***\n" ); |
| 554 | + } else { |
| 555 | + wfOut( "...user_groups table exists and is in current format.\n" ); |
| 556 | + } |
| 557 | + return; |
| 558 | + } |
| 559 | + |
| 560 | + wfOut( "Adding user_groups table... " ); |
| 561 | + $this->applyPatch( 'patch-user_groups.sql' ); |
| 562 | + wfOut( "ok\n" ); |
| 563 | + |
| 564 | + if ( !$this->db->tableExists( 'user_rights' ) ) { |
| 565 | + if ( $this->db->fieldExists( 'user', 'user_rights' ) ) { |
| 566 | + wfOut( "Upgrading from a 1.3 or older database? Breaking out user_rights for conversion..." ); |
| 567 | + $this->db->applyPatch( 'patch-user_rights.sql' ); |
| 568 | + wfOut( "ok\n" ); |
| 569 | + } else { |
| 570 | + wfOut( "*** WARNING: couldn't locate user_rights table or field for upgrade.\n" ); |
| 571 | + wfOut( "*** You may need to manually configure some sysops by manipulating\n" ); |
| 572 | + wfOut( "*** the user_groups table.\n" ); |
| 573 | + return; |
| 574 | + } |
| 575 | + } |
| 576 | + |
| 577 | + wfOut( "Converting user_rights table to user_groups... " ); |
| 578 | + $result = $this->db->select( 'user_rights', |
| 579 | + array( 'ur_user', 'ur_rights' ), |
| 580 | + array( "ur_rights != ''" ), |
| 581 | + __METHOD__ ); |
| 582 | + |
| 583 | + foreach ( $result as $row ) { |
| 584 | + $groups = array_unique( |
| 585 | + array_map( 'trim', |
| 586 | + explode( ',', $row->ur_rights ) ) ); |
| 587 | + |
| 588 | + foreach ( $groups as $group ) { |
| 589 | + $this->db->insert( 'user_groups', |
| 590 | + array( |
| 591 | + 'ug_user' => $row->ur_user, |
| 592 | + 'ug_group' => $group ), |
| 593 | + __METHOD__ ); |
| 594 | + } |
| 595 | + } |
| 596 | + wfOut( "ok\n" ); |
| 597 | + } |
| 598 | + |
| 599 | + /** |
| 600 | + * Make sure wl_notificationtimestamp can be NULL, |
| 601 | + * and update old broken items. |
| 602 | + */ |
| 603 | + protected function doWatchlistNull() { |
| 604 | + $info = $this->db->fieldInfo( 'watchlist', 'wl_notificationtimestamp' ); |
| 605 | + if ( $info->nullable() ) { |
| 606 | + wfOut( "...wl_notificationtimestamp is already nullable.\n" ); |
| 607 | + return; |
| 608 | + } |
| 609 | + |
| 610 | + wfOut( "Making wl_notificationtimestamp nullable... " ); |
| 611 | + $this->applyPatch( 'patch-watchlist-null.sql' ); |
| 612 | + wfOut( "ok\n" ); |
| 613 | + } |
| 614 | + |
| 615 | + /** |
| 616 | + * Set page_random field to a random value where it is equals to 0. |
| 617 | + * |
| 618 | + * @see bug 3946 |
| 619 | + */ |
| 620 | + protected function doPageRandomUpdate() { |
| 621 | + wfOut( "Setting page_random to a random value on rows where it equals 0..." ); |
| 622 | + |
| 623 | + $page = $this->db->tableName( 'page' ); |
| 624 | + $this->db->query( "UPDATE $page SET page_random = RAND() WHERE page_random = 0", __METHOD__ ); |
| 625 | + $rows = $this->db->affectedRows(); |
| 626 | + |
| 627 | + wfOut( "changed $rows rows\n" ); |
| 628 | + } |
| 629 | + |
| 630 | + protected function doTemplatelinksUpdate() { |
| 631 | + if ( $this->db->tableExists( 'templatelinks' ) ) { |
| 632 | + wfOut( "...templatelinks table already exists\n" ); |
| 633 | + return; |
| 634 | + } |
| 635 | + |
| 636 | + wfOut( "Creating templatelinks table...\n" ); |
| 637 | + $this->applyPatch( 'patch-templatelinks.sql' ); |
| 638 | + wfOut( "Populating...\n" ); |
| 639 | + if ( wfGetLB()->getServerCount() > 1 ) { |
| 640 | + // Slow, replication-friendly update |
| 641 | + $res = $this->db->select( 'pagelinks', array( 'pl_from', 'pl_namespace', 'pl_title' ), |
| 642 | + array( 'pl_namespace' => NS_TEMPLATE ), __METHOD__ ); |
| 643 | + $count = 0; |
| 644 | + foreach ( $res as $row ) { |
| 645 | + $count = ( $count + 1 ) % 100; |
| 646 | + if ( $count == 0 ) { |
| 647 | + wfWaitForSlaves( 10 ); |
| 648 | + } |
| 649 | + $this->db->insert( 'templatelinks', |
| 650 | + array( |
| 651 | + 'tl_from' => $row->pl_from, |
| 652 | + 'tl_namespace' => $row->pl_namespace, |
| 653 | + 'tl_title' => $row->pl_title, |
| 654 | + ), __METHOD__ |
| 655 | + ); |
| 656 | + |
| 657 | + } |
| 658 | + } else { |
| 659 | + // Fast update |
| 660 | + $this->db->insertSelect( 'templatelinks', 'pagelinks', |
| 661 | + array( |
| 662 | + 'tl_from' => 'pl_from', |
| 663 | + 'tl_namespace' => 'pl_namespace', |
| 664 | + 'tl_title' => 'pl_title' |
| 665 | + ), array( |
| 666 | + 'pl_namespace' => 10 |
| 667 | + ), __METHOD__ |
| 668 | + ); |
| 669 | + } |
| 670 | + wfOut( "Done. Please run maintenance/refreshLinks.php for a more thorough templatelinks update.\n" ); |
| 671 | + } |
| 672 | + |
| 673 | + protected function doBacklinkingIndicesUpdate() { |
| 674 | + if ( !$this->indexHasField( 'pagelinks', 'pl_namespace', 'pl_from' ) || |
| 675 | + !$this->indexHasField( 'templatelinks', 'tl_namespace', 'tl_from' ) || |
| 676 | + !$this->indexHasField( 'imagelinks', 'il_to', 'il_from' ) ) |
| 677 | + { |
| 678 | + $this->applyPatch( 'patch-backlinkindexes.sql' ); |
| 679 | + wfOut( "...backlinking indices updated\n" ); |
| 680 | + } |
| 681 | + } |
| 682 | + |
| 683 | + /** |
| 684 | + * Adding page_restrictions table, obsoleting page.page_restrictions. |
| 685 | + * Migrating old restrictions to new table |
| 686 | + * -- Andrew Garrett, January 2007. |
| 687 | + */ |
| 688 | + protected function doRestrictionsUpdate() { |
| 689 | + if ( $this->db->tableExists( 'page_restrictions' ) ) { |
| 690 | + wfOut( "...page_restrictions table already exists.\n" ); |
| 691 | + return; |
| 692 | + } |
| 693 | + |
| 694 | + wfOut( "Creating page_restrictions table..." ); |
| 695 | + $this->applyPatch( 'patch-page_restrictions.sql' ); |
| 696 | + $this->applyPatch( 'patch-page_restrictions_sortkey.sql' ); |
| 697 | + wfOut( "ok\n" ); |
| 698 | + |
| 699 | + wfOut( "Migrating old restrictions to new table...\n" ); |
| 700 | + $task = new UpdateRestrictions(); |
| 701 | + $task->execute(); |
| 702 | + } |
| 703 | + |
| 704 | + protected function doCategorylinksIndicesUpdate() { |
| 705 | + if ( !$this->indexHasField( 'categorylinks', 'cl_sortkey', 'cl_from' ) ) { |
| 706 | + $this->applyPatch( 'patch-categorylinksindex.sql' ); |
| 707 | + wfOut( "...categorylinks indices updated\n" ); |
| 708 | + } |
| 709 | + } |
| 710 | + |
| 711 | + protected function doCategoryPopulation() { |
| 712 | + if ( $this->updateRowExists( 'populate category' ) ) { |
| 713 | + wfOut( "...category table already populated.\n" ); |
| 714 | + return; |
| 715 | + } |
| 716 | + |
| 717 | + wfOut( |
| 718 | + "Populating category table, printing progress markers. " . |
| 719 | + "For large databases, you\n" . |
| 720 | + "may want to hit Ctrl-C and do this manually with maintenance/\n" . |
| 721 | + "populateCategory.php.\n" |
| 722 | + ); |
| 723 | + $task = new PopulateCategory(); |
| 724 | + $task->execute(); |
| 725 | + wfOut( "Done populating category table.\n" ); |
| 726 | + } |
| 727 | + |
| 728 | + protected function doPopulateParentId() { |
| 729 | + if ( $this->updateRowExists( 'populate rev_parent_id' ) ) { |
| 730 | + wfOut( "...rev_parent_id column already populated.\n" ); |
| 731 | + return; |
| 732 | + } |
| 733 | + |
| 734 | + $task = new PopulateParentId(); |
| 735 | + $task->execute(); |
| 736 | + } |
| 737 | + |
| 738 | + protected function doMaybeProfilingMemoryUpdate() { |
| 739 | + if ( !$this->db->tableExists( 'profiling' ) ) { |
| 740 | + // Simply ignore |
| 741 | + } elseif ( $this->db->fieldExists( 'profiling', 'pf_memory' ) ) { |
| 742 | + wfOut( "...profiling table has pf_memory field.\n" ); |
| 743 | + } else { |
| 744 | + wfOut( "Adding pf_memory field to table profiling..." ); |
| 745 | + $this->applyPatch( 'patch-profiling-memory.sql' ); |
| 746 | + wfOut( "ok\n" ); |
| 747 | + } |
| 748 | + } |
| 749 | + |
| 750 | + protected function doFilearchiveIndicesUpdate() { |
| 751 | + $info = $this->db->indexInfo( 'filearchive', 'fa_user_timestamp', __METHOD__ ); |
| 752 | + if ( !$info ) { |
| 753 | + $this->applyPatch( 'patch-filearchive-user-index.sql' ); |
| 754 | + wfOut( "...filearchive indices updated\n" ); |
| 755 | + } |
| 756 | + } |
| 757 | + |
| 758 | + protected function doUniquePlTlIl() { |
| 759 | + $info = $this->db->indexInfo( 'pagelinks', 'pl_namespace' ); |
| 760 | + if ( is_array( $info ) && !$info[0]->Non_unique ) { |
| 761 | + wfOut( "...pl_namespace, tl_namespace, il_to indices are already UNIQUE.\n" ); |
| 762 | + return; |
| 763 | + } |
| 764 | + |
| 765 | + wfOut( "Making pl_namespace, tl_namespace and il_to indices UNIQUE... " ); |
| 766 | + $this->applyPatch( 'patch-pl-tl-il-unique.sql' ); |
| 767 | + wfOut( "ok\n" ); |
| 768 | + } |
| 769 | + |
| 770 | + protected function renameEuWikiId() { |
| 771 | + if ( $this->db->fieldExists( 'external_user', 'eu_local_id' ) ) { |
| 772 | + wfOut( "...eu_wiki_id already renamed to eu_local_id.\n" ); |
| 773 | + return; |
| 774 | + } |
| 775 | + |
| 776 | + wfOut( "Renaming eu_wiki_id -> eu_local_id... " ); |
| 777 | + $this->applyPatch( 'patch-eu_local_id.sql' ); |
| 778 | + wfOut( "ok\n" ); |
| 779 | + } |
| 780 | + |
| 781 | + protected function doUpdateMimeMinorField() { |
| 782 | + if ( $this->updateRowExists( 'mime_minor_length' ) ) { |
| 783 | + wfOut( "...*_mime_minor fields are already long enough.\n" ); |
| 784 | + return; |
| 785 | + } |
| 786 | + |
| 787 | + wfOut( "Altering all *_mime_minor fields to 100 bytes in size ... " ); |
| 788 | + $this->applyPatch( 'patch-mime_minor_length.sql' ); |
| 789 | + wfOut( "ok\n" ); |
| 790 | + } |
| 791 | + |
| 792 | + protected function doPopulateRevLen() { |
| 793 | + if ( $this->updateRowExists( 'populate rev_len' ) ) { |
| 794 | + wfOut( "...rev_len column already populated.\n" ); |
| 795 | + return; |
| 796 | + } |
| 797 | + |
| 798 | + $task = new PopulateRevisionLength(); |
| 799 | + $task->execute(); |
| 800 | + } |
| 801 | + |
| 802 | + protected function doClFieldsUpdate() { |
| 803 | + if ( $this->updateRowExists( 'cl_fields_update' ) ) { |
| 804 | + wfOut( "...categorylinks up-to-date.\n" ); |
| 805 | + return; |
| 806 | + } |
| 807 | + |
| 808 | + wfOut( 'Updating categorylinks (again)...' ); |
| 809 | + $this->applyPatch( 'patch-categorylinks-better-collation2.sql' ); |
| 810 | + wfOut( "done.\n" ); |
| 811 | + } |
202 | 812 | } |
Index: trunk/phase3/includes/installer/SqliteUpdater.php |
— | — | @@ -18,7 +18,7 @@ |
19 | 19 | return array( |
20 | 20 | // 1.14 |
21 | 21 | array( 'addField', 'site_stats', 'ss_active_users', 'patch-ss_active_users.sql' ), |
22 | | - array( 'do_active_users_init' ), |
| 22 | + array( 'doActiveUsersInit' ), |
23 | 23 | array( 'addField', 'ipblocks', 'ipb_allow_usertalk', 'patch-ipb_allow_usertalk.sql' ), |
24 | 24 | array( 'sqliteInitialIndexes' ), |
25 | 25 | |
— | — | @@ -30,14 +30,14 @@ |
31 | 31 | // 1.16 |
32 | 32 | array( 'addTable', 'user_properties', 'patch-user_properties.sql' ), |
33 | 33 | array( 'addTable', 'log_search', 'patch-log_search.sql' ), |
34 | | - array( 'do_log_search_population' ), |
| 34 | + array( 'doLogSearchPopulation' ), |
35 | 35 | array( 'addField', 'logging', 'log_user_text', 'patch-log_user_text.sql' ), |
36 | 36 | array( 'addTable', 'l10n_cache', 'patch-l10n_cache.sql' ), |
37 | 37 | array( 'addTable', 'external_user', 'patch-external_user.sql' ), |
38 | 38 | array( 'addIndex', 'log_search', 'ls_field_val', 'patch-log_search-rename-index.sql' ), |
39 | 39 | array( 'addIndex', 'change_tag', 'change_tag_rc_tag', 'patch-change_tag-indexes.sql' ), |
40 | 40 | array( 'addField', 'redirect', 'rd_interwiki', 'patch-rd_interwiki.sql' ), |
41 | | - array( 'do_update_transcache_field' ), |
| 41 | + array( 'doUpdateTranscacheField' ), |
42 | 42 | array( 'sqliteSetupSearchindex' ), |
43 | 43 | |
44 | 44 | // 1.17 |
— | — | @@ -47,6 +47,8 @@ |
48 | 48 | array( 'addField', 'interwiki', 'iw_api', 'patch-iw_api_and_wikiid.sql' ), |
49 | 49 | array( 'dropIndex', 'iwlinks', 'iwl_prefix', 'patch-kill-iwl_prefix.sql' ), |
50 | 50 | array( 'dropIndex', 'iwlinks', 'iwl_prefix_from_title', 'patch-kill-iwl_pft.sql' ), |
| 51 | + array( 'addField', 'categorylinks', 'cl_collation', 'patch-categorylinks-better-collation.sql' ), |
| 52 | + array( 'doCollationUpdate' ), |
51 | 53 | array( 'addTable', 'msg_resource', 'patch-msg_resource.sql' ), |
52 | 54 | array( 'addTable', 'module_deps', 'patch-module_deps.sql' ), |
53 | 55 | ); |
— | — | @@ -54,7 +56,7 @@ |
55 | 57 | |
56 | 58 | protected function sqliteInitialIndexes() { |
57 | 59 | // initial-indexes.sql fails if the indexes are already present, so we perform a quick check if our database is newer. |
58 | | - if ( update_row_exists( 'initial_indexes' ) || $this->db->indexExists( 'user', 'user_name' ) ) { |
| 60 | + if ( $this->updateRowExists( 'initial_indexes' ) || $this->db->indexExists( 'user', 'user_name' ) ) { |
59 | 61 | wfOut( "...have initial indexes\n" ); |
60 | 62 | return; |
61 | 63 | } |
— | — | @@ -65,7 +67,7 @@ |
66 | 68 | |
67 | 69 | protected function sqliteSetupSearchindex() { |
68 | 70 | $module = $this->db->getFulltextSearchModule(); |
69 | | - $fts3tTable = update_row_exists( 'fts3' ); |
| 71 | + $fts3tTable = $this->updateRowExists( 'fts3' ); |
70 | 72 | if ( $fts3tTable && !$module ) { |
71 | 73 | wfOut( '...PHP is missing FTS3 support, downgrading tables...' ); |
72 | 74 | $this->applyPatch( 'searchindex-no-fts.sql' ); |