From 72e90545454c0e014318fa3c81658e035aac58c1 Mon Sep 17 00:00:00 2001 From: Pierre Schmitz Date: Wed, 10 Jun 2009 13:00:47 +0200 Subject: applying patch to version 1.15.0 --- maintenance/FiveUpgrade.inc | 2 +- maintenance/README | 2 +- maintenance/archives/patch-change_tag.sql | 32 + maintenance/archives/patch-fix-il_from.sql | 11 + maintenance/archives/patch-log_user_text.sql | 6 +- maintenance/archives/patch-pl-tl-il-unique.sql | 11 + maintenance/changePassword.php | 4 +- maintenance/checkImages.php | 8 +- maintenance/cleanupCaps.php | 68 +-- maintenance/cleanupTable.inc | 10 +- maintenance/cleanupWatchlist.php | 78 +-- maintenance/commandLine.inc | 23 +- maintenance/dumpBackup.php | 2 + maintenance/dumpInterwiki.php | 4 +- maintenance/findhooks.php | 5 +- maintenance/fuzz-tester.php | 2 +- maintenance/gearman/gearman.inc | 104 ++++ maintenance/gearman/gearmanRefreshLinks.php | 45 ++ maintenance/gearman/gearmanWorker.php | 41 ++ maintenance/generateSitemap.php | 1 + maintenance/ibm_db2/README | 41 ++ maintenance/ibm_db2/tables.sql | 604 +++++++++++++++++++ maintenance/importImages.php | 43 ++ maintenance/importTextFile.php | 57 +- maintenance/language/StatOutputs.php | 4 +- maintenance/language/dumpMessages.php | 4 +- maintenance/language/makeMessageDB.php | 45 ++ maintenance/language/messageTypes.inc | 11 +- maintenance/language/messages.inc | 98 ++- maintenance/mcc.php | 6 +- maintenance/namespaceDupes.php | 19 +- maintenance/orphans.php | 4 +- maintenance/parserTests.inc | 42 +- maintenance/parserTests.php | 2 +- maintenance/parserTests.txt | 116 +++- maintenance/populateCategory.php | 1 + maintenance/postgres/archives/patch-change_tag.sql | 28 + maintenance/postgres/compare_schemas.pl | 54 +- maintenance/postgres/tables.sql | 36 +- maintenance/rebuildFileCache.php | 5 +- maintenance/rebuildInterwiki.php | 4 +- maintenance/refreshLinks.inc | 74 ++- maintenance/refreshLinks.php | 33 +- maintenance/runJobs.php | 34 +- maintenance/showJobs.php | 5 - maintenance/sqlite/README | 12 + maintenance/sqlite/archives/initial-indexes.sql | 417 +++++++++++++ maintenance/sqlite/tables.sql | 340 ----------- maintenance/storage/blobs.sql | 2 +- maintenance/storage/recompressTracked.php | 8 +- maintenance/storage/trackBlobs.php | 12 +- maintenance/tables.sql | 662 +++++++++++---------- maintenance/updateRestrictions.php | 23 +- maintenance/updaters.inc | 457 +++++++------- 54 files changed, 2564 insertions(+), 1198 deletions(-) create mode 100644 maintenance/archives/patch-change_tag.sql create mode 100644 maintenance/archives/patch-fix-il_from.sql create mode 100644 maintenance/archives/patch-pl-tl-il-unique.sql create mode 100644 maintenance/gearman/gearman.inc create mode 100644 maintenance/gearman/gearmanRefreshLinks.php create mode 100644 maintenance/gearman/gearmanWorker.php create mode 100644 maintenance/ibm_db2/README create mode 100644 maintenance/ibm_db2/tables.sql create mode 100644 maintenance/language/makeMessageDB.php create mode 100644 maintenance/postgres/archives/patch-change_tag.sql create mode 100644 maintenance/sqlite/README create mode 100644 maintenance/sqlite/archives/initial-indexes.sql delete mode 100644 maintenance/sqlite/tables.sql (limited to 'maintenance') diff --git a/maintenance/FiveUpgrade.inc b/maintenance/FiveUpgrade.inc index 5632241a..b041a436 100644 --- a/maintenance/FiveUpgrade.inc +++ b/maintenance/FiveUpgrade.inc @@ -97,7 +97,7 @@ class FiveUpgrade { global $wgDBtype; $timeout = 3600 * 24; - $db =& $this->newConnection(); + $db = $this->newConnection(); $db->bufferResults( false ); if ($wgDBtype == 'mysql') { $db->query( "SET net_read_timeout=$timeout" ); diff --git a/maintenance/README b/maintenance/README index e4c01b53..e2215c1d 100644 --- a/maintenance/README +++ b/maintenance/README @@ -78,7 +78,7 @@ installations. rebuildImages.php Update image metadata records - rebuildMessages.php + rebuildmessages.php Update the MediaWiki namespace after changing site language rebuildtextindex.php diff --git a/maintenance/archives/patch-change_tag.sql b/maintenance/archives/patch-change_tag.sql new file mode 100644 index 00000000..030e086b --- /dev/null +++ b/maintenance/archives/patch-change_tag.sql @@ -0,0 +1,32 @@ +-- A table to track tags for revisions, logs and recent changes. +-- Andrew Garrett, 2009-01 +CREATE TABLE /*_*/change_tag ( + ct_rc_id int NULL, + ct_log_id int NULL, + ct_rev_id int NULL, + ct_tag varchar(255) NOT NULL, + ct_params BLOB NULL +) /*$wgDBTableOptions*/; + +CREATE UNIQUE INDEX /*i*/change_tag_rc_tag ON /*_*/change_tag (ct_rc_id,ct_tag); +CREATE UNIQUE INDEX /*i*/change_tag_log_tag ON /*_*/change_tag (ct_log_id,ct_tag); +CREATE UNIQUE INDEX /*i*/change_tag_rev_tag ON /*_*/change_tag (ct_rev_id,ct_tag); +-- Covering index, so we can pull all the info only out of the index. +CREATE INDEX /*i*/change_tag_tag_id ON /*_*/change_tag (ct_tag,ct_rc_id,ct_rev_id,ct_log_id); + +-- Rollup table to pull a LIST of tags simply without ugly GROUP_CONCAT that only works on MySQL 4.1+ +CREATE TABLE /*_*/tag_summary ( + ts_rc_id int NULL, + ts_log_id int NULL, + ts_rev_id int NULL, + ts_tags BLOB NOT NULL +) /*$wgDBTableOptions*/; + +CREATE UNIQUE INDEX /*i*/tag_summary_rc_id ON /*_*/tag_summary (ts_rc_id); +CREATE UNIQUE INDEX /*i*/tag_summary_log_id ON /*_*/tag_summary (ts_log_id); +CREATE UNIQUE INDEX /*i*/tag_summary_rev_id ON /*_*/tag_summary (ts_rev_id); + + +CREATE TABLE /*_*/valid_tag ( + vt_tag varchar(255) NOT NULL PRIMARY KEY +) /*$wgDBTableOptions*/; diff --git a/maintenance/archives/patch-fix-il_from.sql b/maintenance/archives/patch-fix-il_from.sql new file mode 100644 index 00000000..0a199e4d --- /dev/null +++ b/maintenance/archives/patch-fix-il_from.sql @@ -0,0 +1,11 @@ +-- Fix a bug from the 1.2 -> 1.3 upgrader by moving away the imagelinks table +-- and recreating it. +RENAME TABLE /*_*/imagelinks TO /*_*/imagelinks_old; +CREATE TABLE /*_*/imagelinks ( + il_from int unsigned NOT NULL default 0, + il_to varchar(255) binary NOT NULL default '' +) /*$wgDBTableOptions*/; + +CREATE UNIQUE INDEX /*i*/il_from ON /*_*/imagelinks (il_from,il_to); +CREATE UNIQUE INDEX /*i*/il_to ON /*_*/imagelinks (il_to,il_from); + diff --git a/maintenance/archives/patch-log_user_text.sql b/maintenance/archives/patch-log_user_text.sql index f89a35f6..dffbe8be 100644 --- a/maintenance/archives/patch-log_user_text.sql +++ b/maintenance/archives/patch-log_user_text.sql @@ -1,5 +1,7 @@ ALTER TABLE /*$wgDBprefix*/logging ADD log_user_text varchar(255) binary NOT NULL default '', ADD log_target_id int unsigned NULL, - CHANGE `log_type` `log_type` VARBINARY( 15 ) NOT NULL, - CHANGE `log_action` `log_action` VARBINARY( 15 ) NOT NULL; + CHANGE log_type log_type varbinary(32) NOT NULL, + CHANGE log_action log_action varbinary(32) NOT NULL; + +CREATE INDEX /*i*/user_type_time ON /*_*/logging (log_user, log_type, log_timestamp); diff --git a/maintenance/archives/patch-pl-tl-il-unique.sql b/maintenance/archives/patch-pl-tl-il-unique.sql new file mode 100644 index 00000000..186a2036 --- /dev/null +++ b/maintenance/archives/patch-pl-tl-il-unique.sql @@ -0,0 +1,11 @@ +-- +-- patch-pl-tl-il-unique-index.sql +-- +-- Make reorderings of UNIQUE indices UNIQUE as well + +DROP INDEX /*i*/pl_namespace ON /*_*/pagelinks; +CREATE UNIQUE INDEX /*i*/pl_namespace ON /*_*/pagelinks (pl_namespace, pl_title, pl_from); +DROP INDEX /*i*/tl_namespace ON /*_*/templatelinks; +CREATE UNIQUE INDEX /*i*/tl_namespace ON /*_*/templatelinks (tl_namespace, tl_title, tl_from); +DROP INDEX /*i*/il_to ON /*_*/imagelinks; +CREATE UNIQUE INDEX /*i*/il_to ON /*_*/imagelinks (il_to, il_from); diff --git a/maintenance/changePassword.php b/maintenance/changePassword.php index d4370376..0fe8c0be 100644 --- a/maintenance/changePassword.php +++ b/maintenance/changePassword.php @@ -13,7 +13,7 @@ $optionsWithArgs = array( 'user', 'password' ); require_once 'commandLine.inc'; -$USAGE = +$USAGE = "Usage: php changePassword.php [--user=user --password=password | --help]\n" . "\toptions:\n" . "\t\t--help show this message\n" . @@ -50,8 +50,6 @@ class ChangePassword { } function main() { - $fname = 'ChangePassword::main'; - $this->user->setPassword( $this->password ); $this->user->saveSettings(); } diff --git a/maintenance/checkImages.php b/maintenance/checkImages.php index 994cd5b9..378caa34 100644 --- a/maintenance/checkImages.php +++ b/maintenance/checkImages.php @@ -11,7 +11,8 @@ $numImages = 0; $numGood = 0; do { - $res = $dbr->select( 'image', '*', array( 'img_name > ' . $dbr->addQuotes( $start ) ) ); + $res = $dbr->select( 'image', '*', array( 'img_name > ' . $dbr->addQuotes( $start ) ), + 'checkImages.php', array( 'LIMIT' => $batchSize ) ); foreach ( $res as $row ) { $numImages++; $start = $row->img_name; @@ -27,6 +28,11 @@ do { continue; } + if ( $stat['mode'] & 040000 ) { + echo "{$row->img_name}: is a directory\n"; + continue; + } + if ( $stat['size'] == 0 && $row->img_size != 0 ) { echo "{$row->img_name}: truncated, was {$row->img_size}\n"; continue; diff --git a/maintenance/cleanupCaps.php b/maintenance/cleanupCaps.php index e959d4b7..46ca18d6 100644 --- a/maintenance/cleanupCaps.php +++ b/maintenance/cleanupCaps.php @@ -29,20 +29,17 @@ * @ingroup maintenance */ -$options = array( 'dry-run' ); +$optionsWithArgs = array( 'namespace' ); require_once( 'commandLine.inc' ); -require_once( 'FiveUpgrade.inc' ); +require_once( 'cleanupTable.inc' ); /** * @ingroup Maintenance */ -class CapsCleanup extends FiveUpgrade { - function CapsCleanup( $dryrun = false, $namespace=0 ) { - parent::FiveUpgrade(); - - $this->maxLag = 10; # if slaves are lagged more than 10 secs, wait - $this->dryrun = $dryrun; +class CapsCleanup extends TableCleanup { + function __construct( $dryrun = false, $namespace = 0 ) { + parent::__construct( 'page', $dryrun ); $this->namespace = intval( $namespace ); } @@ -53,62 +50,11 @@ class CapsCleanup extends FiveUpgrade { return false; } - $this->runTable( 'page', 'WHERE page_namespace=' . $this->namespace, + $this->runTable( $this->targetTable, + 'WHERE page_namespace=' . $this->namespace, array( &$this, 'processPage' ) ); } - function init( $count, $table ) { - $this->processed = 0; - $this->updated = 0; - $this->count = $count; - $this->startTime = wfTime(); - $this->table = $table; - } - - function progress( $updated ) { - $this->updated += $updated; - $this->processed++; - if( $this->processed % 100 != 0 ) { - return; - } - $portion = $this->processed / $this->count; - $updateRate = $this->updated / $this->processed; - - $now = wfTime(); - $delta = $now - $this->startTime; - $estimatedTotalTime = $delta / $portion; - $eta = $this->startTime + $estimatedTotalTime; - - printf( "%s: %6.2f%% done on %s; ETA %s [%d/%d] %.2f/sec <%.2f%% updated>\n", - wfTimestamp( TS_DB, intval( $now ) ), - $portion * 100.0, - $this->table, - wfTimestamp( TS_DB, intval( $eta ) ), - $this->processed, - $this->count, - $this->processed / $delta, - $updateRate * 100.0 ); - flush(); - } - - function runTable( $table, $where, $callback ) { - $fname = 'CapsCleanup::buildTable'; - - $count = $this->dbw->selectField( $table, 'count(*)', '', $fname ); - $this->init( $count, 'page' ); - $this->log( "Processing $table..." ); - - $tableName = $this->dbr->tableName( $table ); - $sql = "SELECT * FROM $tableName $where"; - $result = $this->dbr->query( $sql, $fname ); - - while( $row = $this->dbr->fetchObject( $result ) ) { - call_user_func( $callback, $row ); - } - $this->log( "Finished $table... $this->updated of $this->processed rows updated" ); - $this->dbr->freeResult( $result ); - } - function processPage( $row ) { global $wgContLang; diff --git a/maintenance/cleanupTable.inc b/maintenance/cleanupTable.inc index 26b0a0e2..75699c52 100644 --- a/maintenance/cleanupTable.inc +++ b/maintenance/cleanupTable.inc @@ -61,21 +61,19 @@ abstract class TableCleanup extends FiveUpgrade { } function runTable( $table, $where, $callback ) { - $fname = 'CapsCleanup::buildTable'; - - $count = $this->dbw->selectField( $table, 'count(*)', '', $fname ); + $count = $this->dbw->selectField( $table, 'count(*)', '', __METHOD__ ); $this->init( $count, $table ); $this->log( "Processing $table..." ); $tableName = $this->dbr->tableName( $table ); $sql = "SELECT * FROM $tableName $where"; - $result = $this->dbr->query( $sql, $fname ); + $result = $this->dbr->query( $sql, __METHOD__ ); - while( $row = $this->dbr->fetchObject( $result ) ) { + foreach( $result as $row ) { call_user_func( $callback, $row ); } $this->log( "Finished $table... $this->updated of $this->processed rows updated" ); - $this->dbr->freeResult( $result ); + $result->free(); } function hexChar( $matches ) { diff --git a/maintenance/cleanupWatchlist.php b/maintenance/cleanupWatchlist.php index a6cedb2e..bfc3a1e2 100644 --- a/maintenance/cleanupWatchlist.php +++ b/maintenance/cleanupWatchlist.php @@ -29,82 +29,18 @@ * @ingroup Maintenance */ -$options = array( 'fix' ); - require_once( 'commandLine.inc' ); -require_once( 'FiveUpgrade.inc' ); +require_once( 'cleanupTable.inc' ); /** * @ingroup Maintenance */ -class WatchlistCleanup extends FiveUpgrade { - function WatchlistCleanup( $dryrun = false ) { - parent::FiveUpgrade(); - - $this->maxLag = 10; # if slaves are lagged more than 10 secs, wait - $this->dryrun = $dryrun; - } - - function cleanup() { - $this->runTable( 'watchlist', - '', - array( &$this, 'processEntry' ) ); - } - - function init( $count, $table ) { - $this->processed = 0; - $this->updated = 0; - $this->count = $count; - $this->startTime = wfTime(); - $this->table = $table; - } - - function progress( $updated ) { - $this->updated += $updated; - $this->processed++; - if( $this->processed % 100 != 0 ) { - return; - } - $portion = $this->processed / $this->count; - $updateRate = $this->updated / $this->processed; - - $now = wfTime(); - $delta = $now - $this->startTime; - $estimatedTotalTime = $delta / $portion; - $eta = $this->startTime + $estimatedTotalTime; - - printf( "%s %s: %6.2f%% done on %s; ETA %s [%d/%d] %.2f/sec <%.2f%% updated>\n", - wfWikiID(), - wfTimestamp( TS_DB, intval( $now ) ), - $portion * 100.0, - $this->table, - wfTimestamp( TS_DB, intval( $eta ) ), - $this->processed, - $this->count, - $this->processed / $delta, - $updateRate * 100.0 ); - flush(); - } - - function runTable( $table, $where, $callback ) { - $fname = 'WatchlistCleanup::runTable'; - - $count = $this->dbw->selectField( $table, 'count(*)', '', $fname ); - $this->init( $count, 'watchlist' ); - $this->log( "Processing $table..." ); - - $tableName = $this->dbr->tableName( $table ); - $sql = "SELECT * FROM $tableName $where"; - $result = $this->dbr->query( $sql, $fname ); - - while( $row = $this->dbr->fetchObject( $result ) ) { - call_user_func( $callback, $row ); - } - $this->log( "Finished $table... $this->updated of $this->processed rows updated" ); - $this->dbr->freeResult( $result ); +class WatchlistCleanup extends TableCleanup { + function __construct( $dryrun = false ) { + parent::__construct( 'watchlist', $dryrun ); } - function processEntry( $row ) { + function processPage( $row ) { $current = Title::makeTitle( $row->wl_namespace, $row->wl_title ); $display = $current->getPrefixedText(); @@ -122,13 +58,13 @@ class WatchlistCleanup extends FiveUpgrade { } function removeWatch( $row ) { - if( !$this->dryrun) { + if( !$this->dryrun ) { $dbw = wfGetDB( DB_MASTER ); $dbw->delete( 'watchlist', array( 'wl_user' => $row->wl_user, 'wl_namespace' => $row->wl_namespace, 'wl_title' => $row->wl_title ), - 'WatchlistCleanup::removeWatch' ); + __METHOD__ ); $this->log( '- removed' ); } } diff --git a/maintenance/commandLine.inc b/maintenance/commandLine.inc index a23bb6eb..e83a1916 100644 --- a/maintenance/commandLine.inc +++ b/maintenance/commandLine.inc @@ -40,9 +40,9 @@ $optionsWithArgs[] = 'aconf'; # As above for AdminSettings.php $optionsWithArgs[] = 'wiki'; # For specifying the wiki ID $self = array_shift( $argv ); -$IP = ( getenv('MW_INSTALL_PATH') !== false +$IP = strval( getenv('MW_INSTALL_PATH') ) !== '' ? getenv('MW_INSTALL_PATH') - : realpath( dirname( __FILE__ ) . '/..' ) ); + : realpath( dirname( __FILE__ ) . '/..' ); #chdir( $IP ); require_once( "$IP/StartProfiler.php" ); @@ -112,9 +112,8 @@ if (!isset( $wgUseNormalUser ) ) { $wgUseNormalUser = false; } -if ( file_exists( '/home/wikipedia/common/langlist' ) ) { +if ( file_exists( dirname(__FILE__).'/wikimedia-mode' ) ) { $wgWikiFarm = true; - #$cluster = trim( file_get_contents( '/etc/cluster' ) ); $cluster = 'pmtpa'; require_once( "$IP/includes/AutoLoader.php" ); require_once( "$IP/includes/SiteConfiguration.php" ); @@ -166,16 +165,10 @@ if ( file_exists( '/home/wikipedia/common/langlist' ) ) { } #require_once( $IP.'/includes/ProfilerStub.php' ); - require_once( $IP.'/includes/Defines.php' ); - require_once( $IP.'/CommonSettings.php' ); - - $bin = '/home/wikipedia/bin'; - if ( $wgUseRootUser ) { - $wgDBuser = $wgDBadminuser = 'root'; - $wgDBpassword = $wgDBadminpassword = trim(`$bin/mysql_root_pass`); - } elseif ( !$wgUseNormalUser ) { - $wgDBuser = $wgDBadminuser = 'wikiadmin'; - $wgDBpassword = $wgDBadminpassword = trim(`$bin/wikiadmin_pass`); + require( $IP.'/includes/Defines.php' ); + require( $IP.'/CommonSettings.php' ); + if ( !$wgUseNormalUser ) { + require( $IP.'/AdminSettings.php' ); } } else { $wgWikiFarm = false; @@ -264,3 +257,5 @@ require_once( "$IP/includes/Setup.php" ); require_once( "$IP/install-utils.inc" ); $wgTitle = null; # Much much faster startup than creating a title object @set_time_limit(0); + +$wgProfiling = false; // only for Profiler.php mode; avoids OOM errors diff --git a/maintenance/dumpBackup.php b/maintenance/dumpBackup.php index de7ce655..0e28734c 100644 --- a/maintenance/dumpBackup.php +++ b/maintenance/dumpBackup.php @@ -63,6 +63,8 @@ if( isset( $options['full'] ) ) { $dumper->dump( WikiExporter::FULL, $textMode ); } elseif( isset( $options['current'] ) ) { $dumper->dump( WikiExporter::CURRENT, $textMode ); +} elseif( isset( $options['stable'] ) ) { + $dumper->dump( WikiExporter::STABLE, $textMode ); } elseif( isset( $options['logs'] ) ) { $dumper->dump( WikiExporter::LOGS ); } else { diff --git a/maintenance/dumpInterwiki.php b/maintenance/dumpInterwiki.php index 91cdbe8a..f5f22f3c 100644 --- a/maintenance/dumpInterwiki.php +++ b/maintenance/dumpInterwiki.php @@ -12,8 +12,8 @@ $oldCwd = getcwd(); $optionsWithArgs = array( "o" ); -include_once( "commandLine.inc" ); -include_once( "dumpInterwiki.inc" ); +require( "commandLine.inc" ); +require( "dumpInterwiki.inc" ); chdir( $oldCwd ); # Output diff --git a/maintenance/findhooks.php b/maintenance/findhooks.php index d7cad253..64fe9a54 100644 --- a/maintenance/findhooks.php +++ b/maintenance/findhooks.php @@ -21,8 +21,7 @@ */ /** This is a command line script*/ -include('commandLine.inc'); - +require('commandLine.inc'); # GLOBALS $doc = $IP . '/docs/hooks.txt'; @@ -156,4 +155,4 @@ printArray('not found', $deprecated ); printArray('unclear hook calls', $bad ); if ( count( $todo ) == 0 && count( $deprecated ) == 0 && count( $bad ) == 0 ) - echo "Looks good!\n"; \ No newline at end of file + echo "Looks good!\n"; diff --git a/maintenance/fuzz-tester.php b/maintenance/fuzz-tester.php index 1ca496ae..9c1ddaff 100644 --- a/maintenance/fuzz-tester.php +++ b/maintenance/fuzz-tester.php @@ -169,7 +169,7 @@ TODO: /////////////////////////// COMMAND LINE HELP //////////////////////////////////// // This is a command line script, load MediaWiki env (gives command line options); -include('commandLine.inc'); +require('commandLine.inc'); // if the user asked for an explanation of command line options. if ( isset( $options["help"] ) ) { diff --git a/maintenance/gearman/gearman.inc b/maintenance/gearman/gearman.inc new file mode 100644 index 00000000..a2a4018a --- /dev/null +++ b/maintenance/gearman/gearman.inc @@ -0,0 +1,104 @@ +complete( array( 'result' => true ) ); + socket_close( $this->conn ); + + # Close some more sockets + wfGetLBFactory()->shutdown(); + global $wgMemc; + $wgMemc->disconnect_all(); + + # Find PHP + $php = readlink( '/proc/' . posix_getpid() . '/exe' ); + + # Run the worker script + $args = array( $_SERVER['PHP_SELF'], + '--wiki', $wiki, + '--fake-job', serialize( $params ) ); + $args = array_merge( $args, $GLOBALS['args'] ); + pcntl_exec( $php, $args, $_ENV ); + echo "Error running exec\n"; + } + + function run( $params ) { + if ( wfWikiID() !== $params['wiki'] ) { + $this->switchWiki( $params['wiki'], $params ); + } + return self::runNoSwitch( $params ); + } + + static function runNoSwitch( $params ) { + echo implode( ' ', $params ) . "\n"; + $title = Title::newFromText( $params['title'] ); + $mwJob = Job::factory( $params['command'], $title, $params['params'] ); + return $mwJob->run(); + } +} + +class NonScaryGearmanWorker extends Net_Gearman_Worker { + + /** + * Copied from Net_Gearman_Worker but with the scary "run any PHP file in + * the filesystem" feature removed. + */ + protected function doWork($socket) { + Net_Gearman_Connection::send($socket, 'grab_job'); + + $resp = array('function' => 'noop'); + while (count($resp) && $resp['function'] == 'noop') { + $resp = Net_Gearman_Connection::blockingRead($socket); + } + + if (in_array($resp['function'], array('noop', 'no_job'))) { + return false; + } + + if ($resp['function'] != 'job_assign') { + throw new Net_Gearman_Exception('Holy Cow! What are you doing?!'); + } + + $name = $resp['data']['func']; + $handle = $resp['data']['handle']; + $arg = array(); + + if (isset($resp['data']['arg']) && + Net_Gearman_Connection::stringLength($resp['data']['arg'])) { + $arg = json_decode($resp['data']['arg'], true); + } + + ### START MW DIFFERENT BIT + if ( $name != 'mw_job' ) { + throw new Net_Gearman_Job_Exception('Invalid function'); + } + $job = new MWGearmanJob($socket, $handle); + ### END MW DIFFERENT BIT + + try { + $this->start($handle, $name, $arg); + $res = $job->run($arg); + if (!is_array($res)) { + $res = array('result' => $res); + } + + $job->complete($res); + $this->complete($handle, $name, $res); + } catch (Net_Gearman_Job_Exception $e) { + $job->fail(); + $this->fail($handle, $name, $e); + } + + // Force the job's destructor to run + $job = null; + + return true; + } +} + diff --git a/maintenance/gearman/gearmanRefreshLinks.php b/maintenance/gearman/gearmanRefreshLinks.php new file mode 100644 index 00000000..eb3104eb --- /dev/null +++ b/maintenance/gearman/gearmanRefreshLinks.php @@ -0,0 +1,45 @@ +selectField( 'page', 'MAX(page_id)', false, __METHOD__ ); +while ( true ) { + $res = $dbr->select( + 'page', + array( 'page_namespace', 'page_title', 'page_id' ), + array( 'page_id > ' . intval( $startId ) ), + __METHOD__, + array( 'LIMIT' => $batchSize ) + ); + + if ( $res->numRows() == 0 ) { + break; + } + $set = new Net_Gearman_Set; + foreach ( $res as $row ) { + $startId = $row->page_id; + $title = Title::makeTitle( $row->page_namespace, $row->page_title ); + $params = array( + 'wiki' => wfWikiID(), + 'title' => $title->getPrefixedDBkey(), + 'command' => 'refreshLinks', + 'params' => false, + ); + $task = new Net_Gearman_Task( 'mw_job', $params ); + $set->addTask( $task ); + } + $client->runSet( $set ); + print "$startId / $endId\n"; +} + diff --git a/maintenance/gearman/gearmanWorker.php b/maintenance/gearman/gearmanWorker.php new file mode 100644 index 00000000..0b26ff9f --- /dev/null +++ b/maintenance/gearman/gearmanWorker.php @@ -0,0 +1,41 @@ + 1000 ) { + echo "Invalid number of processes, please specify a number between 1 and 1000\n"; + exit( 1 ); + } + $fc = new ForkController( $procs, ForkController::RESTART_ON_ERROR ); + if ( $fc->start() != 'child' ) { + exit( 0 ); + } +} + +if ( !$args ) { + $args = array( 'localhost' ); +} + +if ( isset( $options['fake-job'] ) ) { + $params = unserialize( $options['fake-job'] ); + MWGearmanJob::runNoSwitch( $params ); +} + +$worker = new NonScaryGearmanWorker( $args ); +$worker->addAbility( 'mw_job' ); +$worker->beginWork( 'wfGearmanMonitor' ); + +function wfGearmanMonitor( $idle, $lastJob ) { + static $lastSleep = 0; + $interval = 5; + $now = time(); + if ( $now - $lastSleep >= $interval ) { + wfWaitForSlaves( $interval ); + $lastSleep = $now; + } + return false; +} diff --git a/maintenance/generateSitemap.php b/maintenance/generateSitemap.php index 52dc33ae..737c4eba 100644 --- a/maintenance/generateSitemap.php +++ b/maintenance/generateSitemap.php @@ -476,6 +476,7 @@ Usage: php generateSitemap.php [options] --help show this message --fspath= The file system path to save to, e.g /tmp/sitemap + Saves to current directory if not given. --server= The protocol and server name to use in URLs, e.g. http://en.wikipedia.org. This is sometimes necessary because diff --git a/maintenance/ibm_db2/README b/maintenance/ibm_db2/README new file mode 100644 index 00000000..4a2c0f60 --- /dev/null +++ b/maintenance/ibm_db2/README @@ -0,0 +1,41 @@ +== Syntax differences between other databases and IBM DB2 == +{| border cellspacing=0 cellpadding=4 +!MySQL!!IBM DB2 +|- + +|SELECT 1 FROM $table LIMIT 1 +|SELECT COUNT(*) FROM SYSIBM.SYSTABLES ST +WHERE ST.NAME = '$table' AND ST.CREATOR = '$schema' +|- +|MySQL code tries to read one row and interprets lack of error as proof of existence. +|DB2 code counts the number of TABLES of that name in the database. There ought to be 1 for it to exist. +|- +|BEGIN +|(implicit) +|- +|TEXT +|VARCHAR(255) or CLOB +|- +|TIMESTAMPTZ +|TIMESTAMP +|- +|BYTEA +|VARGRAPHIC(255) +|- +|DEFAULT nextval('some_kind_of_sequence'), +|GENERATED ALWAYS AS IDENTITY (START WITH 0, INCREMENT BY 1), +|- +|CIDR +|VARCHAR(255) +|- +|LIMIT 10 +|FETCH FIRST 10 ROWS ONLY +|- +|ROLLBACK TO +|ROLLBACK TO SAVEPOINT +|- +|RELEASE +|RELEASE SAVEPOINT +|} +== See also == +*[http://ca.php.net/manual/en/function.db2-connect.php PHP Manual for DB2 functions] \ No newline at end of file diff --git a/maintenance/ibm_db2/tables.sql b/maintenance/ibm_db2/tables.sql new file mode 100644 index 00000000..5e91102d --- /dev/null +++ b/maintenance/ibm_db2/tables.sql @@ -0,0 +1,604 @@ +-- DB2 + +-- SQL to create the initial tables for the MediaWiki database. +-- This is read and executed by the install script; you should +-- not have to run it by itself unless doing a manual install. +-- This is the IBM DB2 version. +-- For information about each table, please see the notes in maintenance/tables.sql +-- Please make sure all dollar-quoting uses $mw$ at the start of the line +-- TODO: Change CHAR/SMALLINT to BOOL (still used in a non-bool fashion in PHP code) + + + + +CREATE SEQUENCE user_user_id_seq AS INTEGER START WITH 0 INCREMENT BY 1; +CREATE TABLE mwuser ( -- replace reserved word 'user' + user_id INTEGER NOT NULL PRIMARY KEY, -- DEFAULT nextval('user_user_id_seq'), + user_name VARCHAR(255) NOT NULL UNIQUE, + user_real_name VARCHAR(255), + user_password clob(1K), + user_newpassword clob(1K), + user_newpass_time TIMESTAMP, + user_token VARCHAR(255), + user_email VARCHAR(255), + user_email_token VARCHAR(255), + user_email_token_expires TIMESTAMP, + user_email_authenticated TIMESTAMP, + user_options CLOB(64K), + user_touched TIMESTAMP, + user_registration TIMESTAMP, + user_editcount INTEGER +); +CREATE INDEX user_email_token_idx ON mwuser (user_email_token); + +-- Create a dummy user to satisfy fk contraints especially with revisions +INSERT INTO mwuser + VALUES (NEXTVAL FOR user_user_id_seq,'Anonymous','', NULL,NULL,CURRENT_TIMESTAMP,NULL, NULL,NULL,NULL,NULL, NULL,CURRENT_TIMESTAMP,CURRENT_TIMESTAMP,0); + +CREATE TABLE user_groups ( + ug_user INTEGER REFERENCES mwuser(user_id) ON DELETE CASCADE, + ug_group VARCHAR(255) NOT NULL +); +CREATE UNIQUE INDEX user_groups_unique ON user_groups (ug_user, ug_group); + +CREATE TABLE user_newtalk ( + user_id INTEGER NOT NULL REFERENCES mwuser(user_id) ON DELETE CASCADE, + user_ip VARCHAR(255), + user_last_timestamp TIMESTAMP +); +CREATE INDEX user_newtalk_id_idx ON user_newtalk (user_id); +CREATE INDEX user_newtalk_ip_idx ON user_newtalk (user_ip); + + +CREATE SEQUENCE page_page_id_seq; +CREATE TABLE page ( + page_id INTEGER NOT NULL PRIMARY KEY, -- DEFAULT NEXT VALUE FOR user_user_id_seq, + page_namespace SMALLINT NOT NULL, + page_title VARCHAR(255) NOT NULL, + page_restrictions clob(1K), + page_counter BIGINT NOT NULL DEFAULT 0, + page_is_redirect SMALLINT NOT NULL DEFAULT 0, + page_is_new SMALLINT NOT NULL DEFAULT 0, + page_random NUMERIC(15,14) NOT NULL, + page_touched TIMESTAMP, + page_latest INTEGER NOT NULL, -- FK? + page_len INTEGER NOT NULL +); +CREATE UNIQUE INDEX page_unique_name ON page (page_namespace, page_title); +--CREATE INDEX page_main_title ON page (page_title) WHERE page_namespace = 0; +--CREATE INDEX page_talk_title ON page (page_title) WHERE page_namespace = 1; +--CREATE INDEX page_user_title ON page (page_title) WHERE page_namespace = 2; +--CREATE INDEX page_utalk_title ON page (page_title) WHERE page_namespace = 3; +--CREATE INDEX page_project_title ON page (page_title) WHERE page_namespace = 4; +CREATE INDEX page_random_idx ON page (page_random); +CREATE INDEX page_len_idx ON page (page_len); + +--CREATE FUNCTION page_deleted() RETURNS TRIGGER LANGUAGE plpgsql AS +--$mw$ +--BEGIN +--DELETE FROM recentchanges WHERE rc_namespace = OLD.page_namespace AND rc_title = OLD.page_title; +--RETURN NULL; +--END; +--$mw$; + +--CREATE TRIGGER page_deleted AFTER DELETE ON page +-- FOR EACH ROW EXECUTE PROCEDURE page_deleted(); + +CREATE SEQUENCE rev_rev_id_val; +CREATE TABLE revision ( + rev_id INTEGER NOT NULL UNIQUE, --DEFAULT nextval('rev_rev_id_val'), + rev_page INTEGER REFERENCES page (page_id) ON DELETE CASCADE, + rev_text_id INTEGER, -- FK + rev_comment clob(1K), -- changed from VARCHAR(255) + rev_user INTEGER NOT NULL REFERENCES mwuser(user_id) ON DELETE RESTRICT, + rev_user_text VARCHAR(255) NOT NULL, + rev_timestamp TIMESTAMP NOT NULL, + rev_minor_edit SMALLINT NOT NULL DEFAULT 0, + rev_deleted SMALLINT NOT NULL DEFAULT 0, + rev_len INTEGER, + rev_parent_id INTEGER +); +CREATE UNIQUE INDEX revision_unique ON revision (rev_page, rev_id); +CREATE INDEX rev_text_id_idx ON revision (rev_text_id); +CREATE INDEX rev_timestamp_idx ON revision (rev_timestamp); +CREATE INDEX rev_user_idx ON revision (rev_user); +CREATE INDEX rev_user_text_idx ON revision (rev_user_text); + + +CREATE SEQUENCE text_old_id_val; +CREATE TABLE pagecontent ( -- replaces reserved word 'text' + old_id INTEGER NOT NULL, + --PRIMARY KEY DEFAULT nextval('text_old_id_val'), + old_text CLOB(16M), + old_flags clob(1K) +); + +CREATE SEQUENCE pr_id_val; +CREATE TABLE page_restrictions ( + pr_id INTEGER NOT NULL UNIQUE, + --DEFAULT nextval('pr_id_val'), + pr_page INTEGER NOT NULL + --(used to be nullable) + REFERENCES page (page_id) ON DELETE CASCADE, + pr_type VARCHAR(255) NOT NULL, + pr_level VARCHAR(255) NOT NULL, + pr_cascade SMALLINT NOT NULL, + pr_user INTEGER, + pr_expiry TIMESTAMP, + PRIMARY KEY (pr_page, pr_type) +); +--ALTER TABLE page_restrictions ADD CONSTRAINT page_restrictions_pk PRIMARY KEY (pr_page,pr_type); + +CREATE TABLE page_props ( + pp_page INTEGER NOT NULL REFERENCES page (page_id) ON DELETE CASCADE, + pp_propname VARCHAR(255) NOT NULL, + pp_value CLOB(64K) NOT NULL, + PRIMARY KEY (pp_page,pp_propname) +); +--ALTER TABLE page_props ADD CONSTRAINT page_props_pk PRIMARY KEY (pp_page,pp_propname); +CREATE INDEX page_props_propname ON page_props (pp_propname); + + + +CREATE TABLE archive ( + ar_namespace SMALLINT NOT NULL, + ar_title VARCHAR(255) NOT NULL, + ar_text CLOB(16M), + ar_page_id INTEGER, + ar_parent_id INTEGER, + ar_comment clob(1K), + ar_user INTEGER REFERENCES mwuser(user_id) ON DELETE SET NULL, + ar_user_text VARCHAR(255) NOT NULL, + ar_timestamp TIMESTAMP NOT NULL, + ar_minor_edit SMALLINT NOT NULL DEFAULT 0, + ar_flags clob(1K), + ar_rev_id INTEGER, + ar_text_id INTEGER, + ar_deleted SMALLINT NOT NULL DEFAULT 0, + ar_len INTEGER +); +CREATE INDEX archive_name_title_timestamp ON archive (ar_namespace,ar_title,ar_timestamp); +CREATE INDEX archive_user_text ON archive (ar_user_text); + + + +CREATE TABLE redirect ( + rd_from INTEGER NOT NULL REFERENCES page(page_id) ON DELETE CASCADE, + rd_namespace SMALLINT NOT NULL, + rd_title VARCHAR(255) NOT NULL +); +CREATE INDEX redirect_ns_title ON redirect (rd_namespace,rd_title,rd_from); + + +CREATE TABLE pagelinks ( + pl_from INTEGER NOT NULL REFERENCES page(page_id) ON DELETE CASCADE, + pl_namespace SMALLINT NOT NULL, + pl_title VARCHAR(255) NOT NULL +); +CREATE UNIQUE INDEX pagelink_unique ON pagelinks (pl_from,pl_namespace,pl_title); + +CREATE TABLE templatelinks ( + tl_from INTEGER NOT NULL REFERENCES page(page_id) ON DELETE CASCADE, + tl_namespace SMALLINT NOT NULL, + tl_title VARCHAR(255) NOT NULL +); +CREATE UNIQUE INDEX templatelinks_unique ON templatelinks (tl_namespace,tl_title,tl_from); + +CREATE TABLE imagelinks ( + il_from INTEGER NOT NULL REFERENCES page(page_id) ON DELETE CASCADE, + il_to VARCHAR(255) NOT NULL +); +CREATE UNIQUE INDEX il_from ON imagelinks (il_to,il_from); + +CREATE TABLE categorylinks ( + cl_from INTEGER NOT NULL REFERENCES page(page_id) ON DELETE CASCADE, + cl_to VARCHAR(255) NOT NULL, + cl_sortkey VARCHAR(255), + cl_timestamp TIMESTAMP NOT NULL +); +CREATE UNIQUE INDEX cl_from ON categorylinks (cl_from, cl_to); +CREATE INDEX cl_sortkey ON categorylinks (cl_to, cl_sortkey, cl_from); + + + +CREATE TABLE externallinks ( + el_from INTEGER NOT NULL REFERENCES page(page_id) ON DELETE CASCADE, + el_to VARCHAR(255) NOT NULL, + el_index VARCHAR(255) NOT NULL +); +CREATE INDEX externallinks_from_to ON externallinks (el_from,el_to); +CREATE INDEX externallinks_index ON externallinks (el_index); + +CREATE TABLE langlinks ( + ll_from INTEGER NOT NULL REFERENCES page (page_id) ON DELETE CASCADE, + ll_lang VARCHAR(255), + ll_title VARCHAR(255) +); +CREATE UNIQUE INDEX langlinks_unique ON langlinks (ll_from,ll_lang); +CREATE INDEX langlinks_lang_title ON langlinks (ll_lang,ll_title); + + +CREATE TABLE site_stats ( + ss_row_id INTEGER NOT NULL UNIQUE, + ss_total_views INTEGER DEFAULT 0, + ss_total_edits INTEGER DEFAULT 0, + ss_good_articles INTEGER DEFAULT 0, + ss_total_pages INTEGER DEFAULT -1, + ss_users INTEGER DEFAULT -1, + ss_admins INTEGER DEFAULT -1, + ss_images INTEGER DEFAULT 0 +); + +CREATE TABLE hitcounter ( + hc_id BIGINT NOT NULL +); + +CREATE SEQUENCE ipblocks_ipb_id_val; +CREATE TABLE ipblocks ( + ipb_id INTEGER NOT NULL PRIMARY KEY, + --DEFAULT nextval('ipblocks_ipb_id_val'), + ipb_address VARCHAR(255), + ipb_user INTEGER REFERENCES mwuser(user_id) ON DELETE SET NULL, + ipb_by INTEGER NOT NULL REFERENCES mwuser(user_id) ON DELETE CASCADE, + ipb_by_text VARCHAR(255) NOT NULL DEFAULT '', + ipb_reason VARCHAR(255) NOT NULL, + ipb_timestamp TIMESTAMP NOT NULL, + ipb_auto SMALLINT NOT NULL DEFAULT 0, + ipb_anon_only SMALLINT NOT NULL DEFAULT 0, + ipb_create_account SMALLINT NOT NULL DEFAULT 1, + ipb_enable_autoblock SMALLINT NOT NULL DEFAULT 1, + ipb_expiry TIMESTAMP NOT NULL, + ipb_range_start VARCHAR(255), + ipb_range_end VARCHAR(255), + ipb_deleted SMALLINT NOT NULL DEFAULT 0, + ipb_block_email SMALLINT NOT NULL DEFAULT 0 + +); +CREATE INDEX ipb_address ON ipblocks (ipb_address); +CREATE INDEX ipb_user ON ipblocks (ipb_user); +CREATE INDEX ipb_range ON ipblocks (ipb_range_start,ipb_range_end); + + + +CREATE TABLE image ( + img_name VARCHAR(255) NOT NULL PRIMARY KEY, + img_size INTEGER NOT NULL, + img_width INTEGER NOT NULL, + img_height INTEGER NOT NULL, + img_metadata CLOB(16M) NOT NULL DEFAULT '', + img_bits SMALLINT, + img_media_type VARCHAR(255), + img_major_mime VARCHAR(255) DEFAULT 'unknown', + img_minor_mime VARCHAR(255) DEFAULT 'unknown', + img_description clob(1K) NOT NULL DEFAULT '', + img_user INTEGER REFERENCES mwuser(user_id) ON DELETE SET NULL, + img_user_text VARCHAR(255) NOT NULL DEFAULT '', + img_timestamp TIMESTAMP, + img_sha1 VARCHAR(255) NOT NULL DEFAULT '' +); +CREATE INDEX img_size_idx ON image (img_size); +CREATE INDEX img_timestamp_idx ON image (img_timestamp); +CREATE INDEX img_sha1 ON image (img_sha1); + +CREATE TABLE oldimage ( + oi_name VARCHAR(255) NOT NULL, + oi_archive_name VARCHAR(255) NOT NULL, + oi_size INTEGER NOT NULL, + oi_width INTEGER NOT NULL, + oi_height INTEGER NOT NULL, + oi_bits SMALLINT NOT NULL, + oi_description clob(1K), + oi_user INTEGER REFERENCES mwuser(user_id) ON DELETE SET NULL, + oi_user_text VARCHAR(255) NOT NULL, + oi_timestamp TIMESTAMP NOT NULL, + oi_metadata CLOB(16M) NOT NULL DEFAULT '', + oi_media_type VARCHAR(255) , + oi_major_mime VARCHAR(255) NOT NULL DEFAULT 'unknown', + oi_minor_mime VARCHAR(255) NOT NULL DEFAULT 'unknown', + oi_deleted SMALLINT NOT NULL DEFAULT 0, + oi_sha1 VARCHAR(255) NOT NULL DEFAULT '', + FOREIGN KEY (oi_name) REFERENCES image(img_name) ON DELETE CASCADE +); +--ALTER TABLE oldimage ADD CONSTRAINT oldimage_oi_name_fkey_cascade FOREIGN KEY (oi_name) REFERENCES image(img_name) ON DELETE CASCADE; +CREATE INDEX oi_name_timestamp ON oldimage (oi_name,oi_timestamp); +CREATE INDEX oi_name_archive_name ON oldimage (oi_name,oi_archive_name); +CREATE INDEX oi_sha1 ON oldimage (oi_sha1); + + +CREATE SEQUENCE filearchive_fa_id_seq; +CREATE TABLE filearchive ( + fa_id INTEGER NOT NULL PRIMARY KEY, + --PRIMARY KEY DEFAULT nextval('filearchive_fa_id_seq'), + fa_name VARCHAR(255) NOT NULL, + fa_archive_name VARCHAR(255), + fa_storage_group VARCHAR(255), + fa_storage_key VARCHAR(255), + fa_deleted_user INTEGER REFERENCES mwuser(user_id) ON DELETE SET NULL, + fa_deleted_timestamp TIMESTAMP NOT NULL, + fa_deleted_reason VARCHAR(255), + fa_size INTEGER NOT NULL, + fa_width INTEGER NOT NULL, + fa_height INTEGER NOT NULL, + fa_metadata CLOB(16M) NOT NULL DEFAULT '', + fa_bits SMALLINT, + fa_media_type VARCHAR(255), + fa_major_mime VARCHAR(255) DEFAULT 'unknown', + fa_minor_mime VARCHAR(255) DEFAULT 'unknown', + fa_description clob(1K) NOT NULL, + fa_user INTEGER REFERENCES mwuser(user_id) ON DELETE SET NULL, + fa_user_text VARCHAR(255) NOT NULL, + fa_timestamp TIMESTAMP, + fa_deleted SMALLINT NOT NULL DEFAULT 0 +); +CREATE INDEX fa_name_time ON filearchive (fa_name, fa_timestamp); +CREATE INDEX fa_dupe ON filearchive (fa_storage_group, fa_storage_key); +CREATE INDEX fa_notime ON filearchive (fa_deleted_timestamp); +CREATE INDEX fa_nouser ON filearchive (fa_deleted_user); + +CREATE SEQUENCE rc_rc_id_seq; +CREATE TABLE recentchanges ( + rc_id INTEGER NOT NULL PRIMARY KEY, + --PRIMARY KEY DEFAULT nextval('rc_rc_id_seq'), + rc_timestamp TIMESTAMP NOT NULL, + rc_cur_time TIMESTAMP NOT NULL, + rc_user INTEGER REFERENCES mwuser(user_id) ON DELETE SET NULL, + rc_user_text VARCHAR(255) NOT NULL, + rc_namespace SMALLINT NOT NULL, + rc_title VARCHAR(255) NOT NULL, + rc_comment VARCHAR(255), + rc_minor SMALLINT NOT NULL DEFAULT 0, + rc_bot SMALLINT NOT NULL DEFAULT 0, + rc_new SMALLINT NOT NULL DEFAULT 0, + rc_cur_id INTEGER REFERENCES page(page_id) ON DELETE SET NULL, + rc_this_oldid INTEGER NOT NULL, + rc_last_oldid INTEGER NOT NULL, + rc_type SMALLINT NOT NULL DEFAULT 0, + rc_moved_to_ns SMALLINT, + rc_moved_to_title VARCHAR(255), + rc_patrolled SMALLINT NOT NULL DEFAULT 0, + rc_ip VARCHAR(255), -- was CIDR type + rc_old_len INTEGER, + rc_new_len INTEGER, + rc_deleted SMALLINT NOT NULL DEFAULT 0, + rc_logid INTEGER NOT NULL DEFAULT 0, + rc_log_type VARCHAR(255), + rc_log_action VARCHAR(255), + rc_params CLOB(64K) +); +CREATE INDEX rc_timestamp ON recentchanges (rc_timestamp); +CREATE INDEX rc_namespace_title ON recentchanges (rc_namespace, rc_title); +CREATE INDEX rc_cur_id ON recentchanges (rc_cur_id); +CREATE INDEX new_name_timestamp ON recentchanges (rc_new, rc_namespace, rc_timestamp); +CREATE INDEX rc_ip ON recentchanges (rc_ip); + + + +CREATE TABLE watchlist ( + wl_user INTEGER NOT NULL REFERENCES mwuser(user_id) ON DELETE CASCADE, + wl_namespace SMALLINT NOT NULL DEFAULT 0, + wl_title VARCHAR(255) NOT NULL, + wl_notificationtimestamp TIMESTAMP +); +CREATE UNIQUE INDEX wl_user_namespace_title ON watchlist (wl_namespace, wl_title, wl_user); + + +CREATE TABLE math ( + math_inputhash VARGRAPHIC(255) NOT NULL UNIQUE, + math_outputhash VARGRAPHIC(255) NOT NULL, + math_html_conservativeness SMALLINT NOT NULL, + math_html VARCHAR(255), + math_mathml VARCHAR(255) +); + + +CREATE TABLE interwiki ( + iw_prefix VARCHAR(255) NOT NULL UNIQUE, + iw_url CLOB(64K) NOT NULL, + iw_local SMALLINT NOT NULL, + iw_trans SMALLINT NOT NULL DEFAULT 0 +); + + +CREATE TABLE querycache ( + qc_type VARCHAR(255) NOT NULL, + qc_value INTEGER NOT NULL, + qc_namespace SMALLINT NOT NULL, + qc_title VARCHAR(255) NOT NULL +); +CREATE INDEX querycache_type_value ON querycache (qc_type, qc_value); + + + +CREATE TABLE querycache_info ( + qci_type VARCHAR(255) UNIQUE NOT NULL, + qci_timestamp TIMESTAMP +); + + +CREATE TABLE querycachetwo ( + qcc_type VARCHAR(255) NOT NULL, + qcc_value INTEGER NOT NULL DEFAULT 0, + qcc_namespace INTEGER NOT NULL DEFAULT 0, + qcc_title VARCHAR(255) NOT NULL DEFAULT '', + qcc_namespacetwo INTEGER NOT NULL DEFAULT 0, + qcc_titletwo VARCHAR(255) NOT NULL DEFAULT '' +); +CREATE INDEX querycachetwo_type_value ON querycachetwo (qcc_type, qcc_value); +CREATE INDEX querycachetwo_title ON querycachetwo (qcc_type,qcc_namespace,qcc_title); +CREATE INDEX querycachetwo_titletwo ON querycachetwo (qcc_type,qcc_namespacetwo,qcc_titletwo); + +CREATE TABLE objectcache ( + keyname VARCHAR(255) NOT NULL UNIQUE, -- was nullable + value CLOB(16M) NOT NULL DEFAULT '', + exptime TIMESTAMP NOT NULL +); +CREATE INDEX objectcacache_exptime ON objectcache (exptime); + + + +CREATE TABLE transcache ( + tc_url VARCHAR(255) NOT NULL UNIQUE, + tc_contents VARCHAR(255) NOT NULL, + tc_time TIMESTAMP NOT NULL +); + +CREATE SEQUENCE log_log_id_seq; +CREATE TABLE logging ( + log_id INTEGER NOT NULL PRIMARY KEY, + --PRIMARY KEY DEFAULT nextval('log_log_id_seq'), + log_type VARCHAR(255) NOT NULL, + log_action VARCHAR(255) NOT NULL, + log_timestamp TIMESTAMP NOT NULL, + log_user INTEGER REFERENCES mwuser(user_id) ON DELETE SET NULL, + log_namespace SMALLINT NOT NULL, + log_title VARCHAR(255) NOT NULL, + log_comment VARCHAR(255), + log_params CLOB(64K), + log_deleted SMALLINT NOT NULL DEFAULT 0 +); +CREATE INDEX logging_type_name ON logging (log_type, log_timestamp); +CREATE INDEX logging_user_time ON logging (log_timestamp, log_user); +CREATE INDEX logging_page_time ON logging (log_namespace, log_title, log_timestamp); + +CREATE SEQUENCE trackbacks_tb_id_seq; +CREATE TABLE trackbacks ( + tb_id INTEGER NOT NULL PRIMARY KEY, + --PRIMARY KEY DEFAULT nextval('trackbacks_tb_id_seq'), + tb_page INTEGER REFERENCES page(page_id) ON DELETE CASCADE, + tb_title VARCHAR(255) NOT NULL, + tb_url CLOB(64K) NOT NULL, + tb_ex VARCHAR(255), + tb_name VARCHAR(255) +); +CREATE INDEX trackback_page ON trackbacks (tb_page); + + +CREATE SEQUENCE job_job_id_seq; +CREATE TABLE job ( + job_id INTEGER NOT NULL PRIMARY KEY, + --PRIMARY KEY DEFAULT nextval('job_job_id_seq'), + job_cmd VARCHAR(255) NOT NULL, + job_namespace SMALLINT NOT NULL, + job_title VARCHAR(255) NOT NULL, + job_params CLOB(64K) NOT NULL +); +CREATE INDEX job_cmd_namespace_title ON job (job_cmd, job_namespace, job_title); + + + +-- Postgres' Tsearch2 dropped +--ALTER TABLE page ADD titlevector tsvector; +--CREATE FUNCTION ts2_page_title() RETURNS TRIGGER LANGUAGE plpgsql AS +--$mw$ +--BEGIN +--IF TG_OP = 'INSERT' THEN +-- NEW.titlevector = to_tsvector('default',REPLACE(NEW.page_title,'/',' ')); +--ELSIF NEW.page_title != OLD.page_title THEN +-- NEW.titlevector := to_tsvector('default',REPLACE(NEW.page_title,'/',' ')); +--END IF; +--RETURN NEW; +--END; +--$mw$; + +--CREATE TRIGGER ts2_page_title BEFORE INSERT OR UPDATE ON page +-- FOR EACH ROW EXECUTE PROCEDURE ts2_page_title(); + + +--ALTER TABLE pagecontent ADD textvector tsvector; +--CREATE FUNCTION ts2_page_text() RETURNS TRIGGER LANGUAGE plpgsql AS +--$mw$ +--BEGIN +--IF TG_OP = 'INSERT' THEN +-- NEW.textvector = to_tsvector('default',NEW.old_text); +--ELSIF NEW.old_text != OLD.old_text THEN +-- NEW.textvector := to_tsvector('default',NEW.old_text); +--END IF; +--RETURN NEW; +--END; +--$mw$; + +--CREATE TRIGGER ts2_page_text BEFORE INSERT OR UPDATE ON pagecontent +-- FOR EACH ROW EXECUTE PROCEDURE ts2_page_text(); + +-- These are added by the setup script due to version compatibility issues +-- If using 8.1, we switch from "gin" to "gist" + +--CREATE INDEX ts2_page_title ON page USING gin(titlevector); +--CREATE INDEX ts2_page_text ON pagecontent USING gin(textvector); + +--TODO +--CREATE FUNCTION add_interwiki (TEXT,INT,SMALLINT) RETURNS INT LANGUAGE SQL AS +--$mw$ +-- INSERT INTO interwiki (iw_prefix, iw_url, iw_local) VALUES ($1,$2,$3); +-- SELECT 1; +--$mw$; + +-- hack implementation +-- should be replaced with OmniFind, Contains(), etc +CREATE TABLE searchindex ( + si_page int NOT NULL, + si_title varchar(255) NOT NULL default '', + si_text clob NOT NULL +); + +-- This table is not used unless profiling is turned on +CREATE TABLE profiling ( + pf_count INTEGER NOT NULL DEFAULT 0, + pf_time NUMERIC(18,10) NOT NULL DEFAULT 0, + pf_memory NUMERIC(18,10) NOT NULL DEFAULT 0, + pf_name VARCHAR(255) NOT NULL, + pf_server VARCHAR(255) +); +CREATE UNIQUE INDEX pf_name_server ON profiling (pf_name, pf_server); + +CREATE TABLE protected_titles ( + pt_namespace SMALLINT NOT NULL, + pt_title VARCHAR(255) NOT NULL, + pt_user INTEGER REFERENCES mwuser(user_id) ON DELETE SET NULL, + pt_reason clob(1K), + pt_timestamp TIMESTAMP NOT NULL, + pt_expiry TIMESTAMP , + pt_create_perm VARCHAR(255) NOT NULL DEFAULT '' +); +CREATE UNIQUE INDEX protected_titles_unique ON protected_titles(pt_namespace, pt_title); + + + +CREATE TABLE updatelog ( + ul_key VARCHAR(255) NOT NULL PRIMARY KEY +); + +CREATE SEQUENCE category_id_seq; +CREATE TABLE category ( + cat_id INTEGER NOT NULL PRIMARY KEY, + --PRIMARY KEY DEFAULT nextval('category_id_seq'), + cat_title VARCHAR(255) NOT NULL, + cat_pages INTEGER NOT NULL DEFAULT 0, + cat_subcats INTEGER NOT NULL DEFAULT 0, + cat_files INTEGER NOT NULL DEFAULT 0, + cat_hidden SMALLINT NOT NULL DEFAULT 0 +); +CREATE UNIQUE INDEX category_title ON category(cat_title); +CREATE INDEX category_pages ON category(cat_pages); + +CREATE TABLE mediawiki_version ( + type VARCHAR(255) NOT NULL, + mw_version VARCHAR(255) NOT NULL, + notes VARCHAR(255) , + + pg_version VARCHAR(255) , + pg_dbname VARCHAR(255) , + pg_user VARCHAR(255) , + pg_port VARCHAR(255) , + mw_schema VARCHAR(255) , + ts2_schema VARCHAR(255) , + ctype VARCHAR(255) , + + sql_version VARCHAR(255) , + sql_date VARCHAR(255) , + cdate TIMESTAMP NOT NULL DEFAULT CURRENT TIMESTAMP +); + +INSERT INTO mediawiki_version (type,mw_version,sql_version,sql_date) + VALUES ('Creation','??','$LastChangedRevision: 34049 $','$LastChangedDate: 2008-04-30 10:20:36 -0400 (Wed, 30 Apr 2008) $'); + diff --git a/maintenance/importImages.php b/maintenance/importImages.php index 4c6082b2..7997b0d5 100644 --- a/maintenance/importImages.php +++ b/maintenance/importImages.php @@ -21,6 +21,13 @@ if( count( $args ) > 0 ) { $dir = $args[0]; + # Check Protection + if (isset($options['protect']) && isset($options['unprotect'])) + die("Cannot specify both protect and unprotect. Only 1 is allowed.\n"); + + if ($options['protect'] == 1) + die("You must specify a protection option.\n"); + # Prepare the list of allowed extensions global $wgFileExtensions; $extensions = isset( $options['extensions'] ) @@ -114,6 +121,25 @@ if( count( $args ) > 0 ) { continue; } } + + $doProtect = false; + $restrictions = array(); + + global $wgRestrictionLevels; + + $protectLevel = isset($options['protect']) ? $options['protect'] : null; + + if ( $protectLevel && in_array( $protectLevel, $wgRestrictionLevels ) ) { + $restrictions['move'] = $protectLevel; + $restrictions['edit'] = $protectLevel; + $doProtect = true; + } + if (isset($options['unprotect'])) { + $restrictions['move'] = ''; + $restrictions['edit'] = ''; + $doProtect = true; + } + $$svar++; if ( isset( $options['dry'] ) ) { @@ -121,6 +147,21 @@ if( count( $args ) > 0 ) { } else if ( $image->recordUpload( $archive->value, $commentText, $license ) ) { # We're done! echo( "done.\n" ); + if ($doProtect) { + # Protect the file + $article = new Article( $title ); + echo "\nWaiting for slaves...\n"; + // Wait for slaves. + sleep(2.0); + wfWaitForSlaves( 1.0 ); + + echo( "\nSetting image restrictions ... " ); + if ( $article->updateRestrictions($restrictions) ) + echo( "done.\n" ); + else + echo( "failed.\n" ); + } + } else { echo( "failed.\n" ); } @@ -166,6 +207,8 @@ Options: but the extension . --license= Use an optional license template --dry Dry run, don't import anything +--protect= Specify the protect value (autoconfirmed,sysop) +--unprotect Unprotects all uploaded images END; exit(); diff --git a/maintenance/importTextFile.php b/maintenance/importTextFile.php index 0a0068d7..bfb852e0 100644 --- a/maintenance/importTextFile.php +++ b/maintenance/importTextFile.php @@ -9,7 +9,7 @@ * @author Rob Church */ -$options = array( 'help', 'nooverwrite', 'norc' ); +$options = array( 'help', 'nooverwrite', 'norc' ); $optionsWithArgs = array( 'title', 'user', 'comment' ); require_once( 'commandLine.inc' ); echo( "Import Text File\n\n" ); @@ -21,43 +21,43 @@ if( count( $args ) < 1 || isset( $options['help'] ) ) { $filename = $args[0]; echo( "Using {$filename}..." ); if( is_file( $filename ) ) { - + $title = isset( $options['title'] ) ? $options['title'] : titleFromFilename( $filename ); $title = Title::newFromUrl( $title ); - + if( is_object( $title ) ) { - + echo( "\nUsing title '" . $title->getPrefixedText() . "'..." ); if( !$title->exists() || !isset( $options['nooverwrite'] ) ) { - + $text = file_get_contents( $filename ); $user = isset( $options['user'] ) ? $options['user'] : 'Maintenance script'; $user = User::newFromName( $user ); - + if( is_object( $user ) ) { - + echo( "\nUsing username '" . $user->getName() . "'..." ); $wgUser =& $user; $comment = isset( $options['comment'] ) ? $options['comment'] : 'Importing text file'; $flags = 0 | ( isset( $options['norc'] ) ? EDIT_SUPPRESS_RC : 0 ); - + echo( "\nPerforming edit..." ); $article = new Article( $title ); $article->doEdit( $text, $comment, $flags ); echo( "done.\n" ); - + } else { echo( "invalid username.\n" ); } - + } else { echo( "page exists.\n" ); } - + } else { echo( "invalid title.\n" ); } - + } else { echo( "does not exist.\n" ); } @@ -71,16 +71,25 @@ function titleFromFilename( $filename ) { } function showHelp() { - echo( "Import the contents of a text file into a wiki page.\n" ); - echo( "USAGE: php importTextFile.php \n\n" ); - echo( " : Path to the file containing page content to import\n\n" ); - echo( "Options:\n\n" ); - echo( "--title \n\tTitle for the new page; default is to use the filename as a base\n" ); - echo( "--user <user>\n\tUser to be associated with the edit\n" ); - echo( "--comment <comment>\n\tEdit summary\n" ); - echo( "--nooverwrite\n\tDon't overwrite existing content\n" ); - echo( "--norc\n\tDon't update recent changes\n" ); - echo( "--help\n\tShow this information\n" ); - echo( "\n" ); -} +print <<<EOF +USAGE: php importTextFile.php <options> <filename> +<filename> : Path to the file containing page content to import + +Options: + +--title <title> + Title for the new page; default is to use the filename as a base +--user <user> + User to be associated with the edit +--comment <comment> + Edit summary +--nooverwrite + Don't overwrite existing content +--norc + Don't update recent changes +--help + Show this information + +EOF; +} diff --git a/maintenance/language/StatOutputs.php b/maintenance/language/StatOutputs.php index f65b263e..b41278b4 100644 --- a/maintenance/language/StatOutputs.php +++ b/maintenance/language/StatOutputs.php @@ -48,7 +48,7 @@ class wikiStatsOutput extends statsOutput { echo ''; } function element( $in, $heading = false ) { - echo ($heading ? '!' : '|') . " $in\n"; + echo ($heading ? '!' : '|') . "$in\n"; } function formatPercent( $subset, $total, $revert = false, $accuracy = 2 ) { $v = @round(255 * $subset / $total); @@ -68,7 +68,7 @@ class wikiStatsOutput extends statsOutput { $color = $red . $green . $blue; $percent = statsOutput::formatPercent( $subset, $total, $revert, $accuracy ); - return 'bgcolor="#'. $color .'" | '. $percent; + return 'bgcolor="#'. $color .'"|'. $percent; } } diff --git a/maintenance/language/dumpMessages.php b/maintenance/language/dumpMessages.php index 5669e58c..35aeeb75 100644 --- a/maintenance/language/dumpMessages.php +++ b/maintenance/language/dumpMessages.php @@ -7,11 +7,9 @@ /** */ require_once( dirname(__FILE__).'/../commandLine.inc' ); -$wgMessageCache->disableTransform(); $messages = array(); $wgEnglishMessages = array_keys( Language::getMessagesFor( 'en' ) ); -foreach ( $wgEnglishMessages as $key ) -{ +foreach ( $wgEnglishMessages as $key ) { $messages[$key] = wfMsg( $key ); } print "MediaWiki $wgVersion language file\n"; diff --git a/maintenance/language/makeMessageDB.php b/maintenance/language/makeMessageDB.php new file mode 100644 index 00000000..f853b395 --- /dev/null +++ b/maintenance/language/makeMessageDB.php @@ -0,0 +1,45 @@ +<?php + +/** + * Proof of principle script + */ + +require( dirname( __FILE__ ) . '/../commandLine.inc' ); + +$obj = new MakeMessagesDB; +$obj->run(); + +class MakeMessagesDB { + + function run() { + global $wgExtensionMessagesFiles, $wgMessageCache, $IP; + + $nameHash = md5( implode( "\n", array_keys( $wgExtensionMessagesFiles ) ) ); + $dir = "$IP/cache/ext-msgs"; + wfMkdirParents( $dir ); + $db = dba_open( "$dir/$nameHash.cdb", 'n', 'cdb' ); + if ( !$db ) { + echo "Cannot open DB file\n"; + exit( 1 ); + } + + # Load extension messages + foreach ( $wgExtensionMessagesFiles as $file ) { + $messages = $magicWords = array(); + require( $file ); + foreach ( $messages as $lang => $unused ) { + $wgMessageCache->processMessagesArray( $messages, $lang ); + } + } + + # Write them to the file + foreach ( $wgMessageCache->mExtensionMessages as $lang => $messages ) { + foreach ( $messages as $key => $text ) { + dba_insert( "$lang:$key", $text, $db ); + } + } + + dba_close( $db ); + } +} + diff --git a/maintenance/language/messageTypes.inc b/maintenance/language/messageTypes.inc index 1b95fe98..d155db94 100644 --- a/maintenance/language/messageTypes.inc +++ b/maintenance/language/messageTypes.inc @@ -108,8 +108,6 @@ $wgIgnoredMessages = array( 'statistics-summary', 'statistics-footer', 'talkpagetext', - 'trackback', - 'trackbackexcerpt', 'uploadfooter', 'listgrouprights-link', 'search-interwiki-custom', @@ -153,7 +151,6 @@ $wgIgnoredMessages = array( 'unusedtemplates-summary', 'fewestrevisions-summary', 'upload-summary', - 'pagetitle-view-mainpage', 'newuserlogentry', 'restrictlogpage', 'wantedtemplates-summary', @@ -180,6 +177,9 @@ $wgOptionalMessages = array( 'variantname-zh-my', 'variantname-zh-sg', 'variantname-zh', + 'variantname-gan-hans', + 'variantname-gan-hant', + 'variantname-gan', 'variantname-sr-ec', 'variantname-sr-el', 'variantname-sr', @@ -264,7 +264,6 @@ $wgOptionalMessages = array( 'pagetitle', 'filename-prefix-blacklist', 'edittools', - 'patrol-log-diff', 'size-bytes', 'size-kilobytes', 'size-megabytes', @@ -328,12 +327,16 @@ $wgOptionalMessages = array( 'pipe-separator', 'word-separator', 'ellipsis', + 'percent', 'autocomment-prefix', 'listgrouprights-right-display', 'timezone-utc', 'whatlinkshere-backlink', 'recentchangeslinked-backlink', 'diff-with-additional', + 'pagetitle-view-mainpage', + 'trackback', + 'trackbackexcerpt', ); /** EXIF messages, which may be set as optional in several checks, but are generally mandatory */ diff --git a/maintenance/language/messages.inc b/maintenance/language/messages.inc index d7475428..fb22bc9c 100644 --- a/maintenance/language/messages.inc +++ b/maintenance/language/messages.inc @@ -16,6 +16,8 @@ $wgMessageStructure = array( 'tog-highlightbroken', 'tog-justify', 'tog-hideminor', + 'tog-hidepatrolled', + 'tog-newpageshidepatrolled', 'tog-extendwatchlist', 'tog-usenewrc', 'tog-numberheadings', @@ -50,6 +52,7 @@ $wgMessageStructure = array( 'tog-watchlisthideminor', 'tog-watchlisthideliu', 'tog-watchlisthideanons', + 'tog-watchlisthidepatrolled', 'tog-nolangconversion', 'tog-ccmeonemails', 'tog-diffonly', @@ -395,6 +398,11 @@ $wgMessageStructure = array( 'yournick', 'badsig', 'badsiglength', + 'yourgender', + 'gender-unknown', + 'gender-male', + 'gender-female', + 'prefs-help-gender', 'email', 'prefs-help-realname', 'loginerror', @@ -453,6 +461,10 @@ $wgMessageStructure = array( 'resetpass-submit-loggedin', 'resetpass-wrong-oldpass', 'resetpass-temp-password', + 'resetpass-log', + 'resetpass-logtext', + 'resetpass-logentry', + 'resetpass-comment', ), 'toolbar' => array( 'bold_sample', @@ -629,13 +641,22 @@ $wgMessageStructure = array( 'rev-deleted-event', 'rev-deleted-text-permission', 'rev-deleted-text-view', + 'rev-deleted-no-diff', + 'rev-deleted-unhide-diff', 'rev-delundel', 'revisiondelete', 'revdelete-nooldid-title', 'revdelete-nooldid-text', + 'revdelete-nologtype-title', + 'revdelete-nologtype-text', + 'revdelete-toomanytargets-title', + 'revdelete-toomanytargets-text', + 'revdelete-nologid-title', + 'revdelete-nologid-text', 'revdelete-selected', 'logdelete-selected', 'revdelete-text', + 'revdelete-suppress-text', 'revdelete-legend', 'revdelete-hide-text', 'revdelete-hide-name', @@ -690,6 +711,7 @@ $wgMessageStructure = array( 'mergehistory-autocomment', 'mergehistory-comment', 'mergehistory-same-destination', + 'mergehistory-reason' ), 'mergelog' => array( 'mergelog', @@ -776,6 +798,9 @@ $wgMessageStructure = array( 'notextmatches', 'prevn', 'nextn', + 'prevn-title', + 'nextn-title', + 'shown-title', 'viewprevnext', 'searchmenu-legend', 'searchmenu-exists', @@ -869,6 +894,7 @@ $wgMessageStructure = array( 'prefs-resetpass', 'saveprefs', 'resetprefs', + 'restoreprefs', 'textboxsize', 'prefs-edit-boxsize', 'rows', @@ -891,6 +917,16 @@ $wgMessageStructure = array( 'timezoneoffset', 'servertime', 'guesstimezone', + 'timezoneregion-africa', + 'timezoneregion-america', + 'timezoneregion-antarctica', + 'timezoneregion-arctic', + 'timezoneregion-asia', + 'timezoneregion-atlantic', + 'timezoneregion-australia', + 'timezoneregion-europe', + 'timezoneregion-indian', + 'timezoneregion-pacific', 'allowemail', 'prefs-searchoptions', 'prefs-namespaces', @@ -898,6 +934,8 @@ $wgMessageStructure = array( 'default', 'defaultns', 'files', + 'prefs-custom-css', + 'prefs-custom-js', ), 'userrights' => array( 'userrights', @@ -999,6 +1037,8 @@ $wgMessageStructure = array( 'right-userrights', 'right-userrights-interwiki', 'right-siteadmin', + 'right-reset-passwords', + 'right-override-export-depth', ), 'rightslog' => array( 'rightslog', @@ -1107,6 +1147,7 @@ $wgMessageStructure = array( 'filename', 'filedesc', 'fileuploadsummary', + 'filereuploadsummary', 'filestatus', 'filesource', 'uploadedfiles', @@ -1140,6 +1181,7 @@ $wgMessageStructure = array( 'overwroteimage', 'uploaddisabled', 'uploaddisabledtext', + 'php-uploaddisabledtext', 'uploadscripted', 'uploadcorrupt', 'uploadvirus', @@ -1213,14 +1255,11 @@ $wgMessageStructure = array( 'shareduploadwiki-desc', 'shareduploadwiki-linktext', 'shareddescriptionfollows', - 'shareduploadduplicate', - 'shareduploadduplicate-linktext', - 'shareduploadconflict', - 'shareduploadconflict-linktext', 'noimage', 'noimage-linktext', 'uploadnewversion-linktext', - 'imagepage-searchdupe', + 'shared-repo-from', + 'shared-repo', ), 'filerevert' => array( 'filerevert', @@ -1359,6 +1398,7 @@ $wgMessageStructure = array( 'wantedcategories-summary', 'wantedpages', 'wantedpages-summary', + 'wantedpages-badtitle', 'wantedfiles', 'wantedfiles-summary', 'wantedtemplates', @@ -1397,7 +1437,9 @@ $wgMessageStructure = array( 'listusers', 'listusers-summary', 'listusers-editsonly', + 'listusers-creationsort', 'usereditcount', + 'usercreated', 'newpages', 'newpages-summary', 'newpages-username', @@ -1465,6 +1507,7 @@ $wgMessageStructure = array( ), 'deletedcontribs' => array( 'deletedcontributions', + 'deletedcontributions-title', ), 'linksearch' => array( 'linksearch', @@ -1728,6 +1771,7 @@ $wgMessageStructure = array( 'sp-contributions-newbies-sub', 'sp-contributions-newbies-title', 'sp-contributions-blocklog', + 'sp-contributions-logs', 'sp-contributions-search', 'sp-contributions-username', 'sp-contributions-submit', @@ -1828,9 +1872,11 @@ $wgMessageStructure = array( 'block-log-flags-noemail', 'block-log-flags-nousertalk', 'block-log-flags-angry-autoblock', + 'block-log-flags-hiddenname', 'range_block_disabled', 'ipb_expiry_invalid', 'ipb_expiry_temp', + 'ipb_hide_invalid', 'ipb_already_blocked', 'ipb-needreblock', 'ipb_cant_unblock', @@ -1899,6 +1945,9 @@ $wgMessageStructure = array( 'move-redirect-suppressed', 'movelogpage', 'movelogpagetext', + 'movesubpage', + 'movesubpagetext', + 'movenosubpage', 'movereason', 'revertmove', 'delete_and_move', @@ -1926,8 +1975,11 @@ $wgMessageStructure = array( 'export-submit', 'export-addcattext', 'export-addcat', + 'export-addnstext', + 'export-addns', 'export-download', 'export-templates', + 'export-pagelinks', ), 'allmessages' => array( 'allmessages', @@ -1954,6 +2006,7 @@ $wgMessageStructure = array( 'import-interwiki-text', 'import-interwiki-source', 'import-interwiki-history', + 'import-interwiki-templates', 'import-interwiki-submit', 'import-interwiki-namespace', 'import-upload-filename', @@ -2270,6 +2323,11 @@ $wgMessageStructure = array( 'variantname-zh-my', 'variantname-zh', ), + 'variantname-gan' => array( + 'variantname-gan-hans', + 'variantname-gan-hant', + 'variantname-gan', + ), 'variantname-sr' => array( 'variantname-sr-ec', 'variantname-sr-el', @@ -2684,6 +2742,7 @@ $wgMessageStructure = array( 'pipe-separator', 'word-separator', 'ellipsis', + 'percent', ), 'imgmulti' => array( 'imgmultipageprev', @@ -2877,6 +2936,28 @@ $wgMessageStructure = array( 'external_images' => array( 'external_image_whitelist', ), + 'special-tags' => array( + 'tags', + 'tag-filter', + 'tag-filter-submit', + 'tags-title', + 'tags-intro', + 'tags-tag', + 'tags-display-header', + 'tags-description-header', + 'tags-hitcount-header', + 'tags-edit', + 'tags-hitcount', + ), + 'db-error-messages' => array( + 'dberr-header', + 'dberr-problems', + 'dberr-again', + 'dberr-info', + 'dberr-usegoogle', + 'dberr-outofdate', + 'dberr-cachederror', + ), ); /** Comments for each block */ @@ -3003,6 +3084,7 @@ XHTML id names.", To disable showing a particular link, set it to 'disable', e.g. 'variantname-zh-sg' => 'disable', Variants for Chinese language", + 'variantname-gan' => 'Variants for Gan language', 'variantname-sr' => 'Variants for Serbian language', 'variantname-kk' => 'Variants for Kazakh language', 'variantname-ku' => 'Variants for Kurdish language', @@ -3073,6 +3155,8 @@ Variants for Chinese language", 'special-specialpages' => 'Special:SpecialPages', 'special-blank' => 'Special:BlankPage', 'external_images' => 'External image whitelist', + 'special-tags' => 'Special:Tags', + 'db-error-messages' => 'Database error messages', ); /** Short comments for standalone messages */ @@ -3081,6 +3165,9 @@ $wgMessageComments = array( 'lastmodifiedat' => '$1 date, $2 time', 'sitenotice' => 'the equivalent to wgSiteNotice', 'history-feed-item-nocomment' => 'user at time', + 'sharedupload' => '$1 is the repo name, $2 is shareduploadwiki(-desc)', + 'shared-repo-from' => '$1 is the repository name', + 'shared-repo' => 'used when shared-repo-NAME does not exist', 'editcomment' => 'only shown if there is an edit comment', 'revertpage' => 'Additionally available: $3: revid of the revision reverted to, $4: timestamp of the revision reverted to, $5: revid of the revision reverted from, $6: timestamp of the revision reverted from', 'lastmodifiedatby' => '$1 date, $2 time, $3 user', @@ -3100,4 +3187,5 @@ $wgMessageComments = array( 'userrights' => 'Not used as normal message but as header for the special page itself', 'revision-info' => 'Additionally available: $3: revision id', 'revision-info-current' => 'Available parameters: $1: timestamp; $2: userlinks; $3: revision id', + 'nocontribs' => 'Optional parameter: $1 is the user name', ); diff --git a/maintenance/mcc.php b/maintenance/mcc.php index 89605871..53645df8 100644 --- a/maintenance/mcc.php +++ b/maintenance/mcc.php @@ -88,7 +88,11 @@ do { break; case 'get': - print "Getting {$args[0]}[{$args[1]}]\n"; + $sub = ''; + if ( array_key_exists( 1, $args ) ) { + $sub = $args[1]; + } + print "Getting {$args[0]}[$sub]\n"; $res = $mcc->get( $args[0] ); if ( array_key_exists( 1, $args ) ) { $res = $res[$args[1]]; diff --git a/maintenance/namespaceDupes.php b/maintenance/namespaceDupes.php index fcc7d3a1..c5b3ce96 100644 --- a/maintenance/namespaceDupes.php +++ b/maintenance/namespaceDupes.php @@ -224,12 +224,19 @@ class NamespaceConflictChecker { function resolveConflict( $row, $resolvable, $suffix ) { if( !$resolvable ) { echo "... *** old title {$row->title}\n"; - $row->title .= $suffix; - echo "... *** new title {$row->title}\n"; - $title = Title::makeTitleSafe( $row->namespace, $row->title ); - if ( ! $title ) { - echo "... !!! invalid title\n"; - return false; + while( true ) { + $row->title .= $suffix; + echo "... *** new title {$row->title}\n"; + $title = Title::makeTitleSafe( $row->namespace, $row->title ); + if ( ! $title ) { + echo "... !!! invalid title\n"; + return false; + } + if ( $id = $title->getArticleId() ) { + echo "... *** page exists with ID $id ***\n"; + } else { + break; + } } echo "... *** using suffixed form [[" . $title->getPrefixedText() . "]] ***\n"; } diff --git a/maintenance/orphans.php b/maintenance/orphans.php index 8ecd9b81..480b7220 100644 --- a/maintenance/orphans.php +++ b/maintenance/orphans.php @@ -63,12 +63,12 @@ function checkOrphans( $fix ) { while( $row = $dbw->fetchObject( $result ) ) { $comment = ( $row->rev_comment == '' ) ? '' - : '(' . $wgContLang->truncate( $row->rev_comment, 40, '...' ) . ')'; + : '(' . $wgContLang->truncate( $row->rev_comment, 40 ) . ')'; printf( "%10d %10d %14s %20s %s\n", $row->rev_id, $row->rev_page, $row->rev_timestamp, - $wgContLang->truncate( $row->rev_user_text, 17, '...' ), + $wgContLang->truncate( $row->rev_user_text, 17 ), $comment ); if( $fix ) { $dbw->delete( 'revision', array( 'rev_id' => $row->rev_id ) ); diff --git a/maintenance/parserTests.inc b/maintenance/parserTests.inc index 7971e64e..b689fc1b 100644 --- a/maintenance/parserTests.inc +++ b/maintenance/parserTests.inc @@ -353,6 +353,9 @@ class ParserTest { else { $data['options'] = $this->chomp( $data['options'] ); } + if (!isset( $data['config'] ) ) + $data['config'] = ''; + if (preg_match('/\\bdisabled\\b/i', $data['options']) || !preg_match("/{$this->regex}/i", $data['test'])) { # disabled test @@ -364,7 +367,9 @@ class ParserTest { $this->chomp( $data['test'] ), $this->chomp( $data['input'] ), $this->chomp( $data['result'] ), - $this->chomp( $data['options'] ) ); + $this->chomp( $data['options'] ), + $this->chomp( $data['config'] ) + ); $ok = $ok && $result; $this->recorder->record( $this->chomp( $data['test'] ), $result ); $data = array(); @@ -414,12 +419,12 @@ class ParserTest { * @param string $result Result to output * @return bool */ - private function runTest( $desc, $input, $result, $opts ) { + private function runTest( $desc, $input, $result, $opts, $config ) { if( $this->showProgress ) { $this->showTesting( $desc ); } - $this->setupGlobals($opts); + $this->setupGlobals($opts, $config); $user = new User(); $options = ParserOptions::newFromUser( $user ); @@ -502,7 +507,7 @@ class ParserTest { * Set up the global variables for a consistent environment for each test. * Ideally this should replace the global configuration entirely. */ - private function setupGlobals($opts = '') { + private function setupGlobals($opts = '', $config = '') { if( !isset( $this->uploadDir ) ) { $this->uploadDir = $this->setupUploadDir(); } @@ -545,6 +550,7 @@ class ParserTest { 'wgMaxTocLevel' => $maxtoclevel, 'wgCapitalLinks' => true, 'wgNoFollowLinks' => true, + 'wgNoFollowDomainExceptions' => array(), 'wgThumbnailScriptPath' => false, 'wgUseTeX' => false, 'wgLocaltimezone' => 'UTC', @@ -564,7 +570,20 @@ class ParserTest { 'wgForeignFileRepos' => array(), 'wgLinkHolderBatchSize' => $linkHolderBatchSize, 'wgEnforceHtmlIds' => true, + 'wgExternalLinkTarget' => false, + 'wgAlwaysUseTidy' => false, ); + + if ($config) { + $configLines = explode( "\n", $config ); + + foreach( $configLines as $line ) { + list( $var, $value ) = explode( '=', $line, 2 ); + + $settings[$var] = eval("return $value;" ); + } + } + $this->savedGlobals = array(); foreach( $settings as $var => $val ) { $this->savedGlobals[$var] = $GLOBALS[$var]; @@ -613,7 +632,7 @@ class ParserTest { * the db will be visible to later tests in the run. */ private function setupDatabase() { - global $wgDBprefix; + global $wgDBprefix, $wgDBtype; if ( $this->databaseSetupDone ) { return; } @@ -635,15 +654,16 @@ class ParserTest { $db = wfGetDB( DB_MASTER ); $tables = $this->listTables(); - if (!(strcmp($db->getServerVersion(), '4.1') < 0 and stristr($db->getSoftwareLink(), 'MySQL'))) { + if ( !( $wgDBtype == 'mysql' && strcmp( $db->getServerVersion(), '4.1' ) < 0 ) ) { # Database that supports CREATE TABLE ... LIKE - global $wgDBtype; + if( $wgDBtype == 'postgres' ) { $def = 'INCLUDING DEFAULTS'; + $temporary = 'TEMPORARY'; } else { $def = ''; } - foreach ($tables as $tbl) { + foreach ( $tables as $tbl ) { # Clean up from previous aborted run. So that table escaping # works correctly across DB engines, we need to change the pre- # fix back and forth so tableName() works right. @@ -652,11 +672,11 @@ class ParserTest { $this->changePrefix( 'parsertest_' ); $newTableName = $db->tableName( $tbl ); - if ( $db->tableExists( $tbl ) ) { - $db->query("DROP TABLE $newTableName"); + if ( $db->tableExists( $tbl ) && $wgDBtype != 'postgres' ) { + $db->query( "DROP TABLE $newTableName" ); } # Create new table - $db->query("CREATE $temporary TABLE $newTableName (LIKE $oldTableName $def)"); + $db->query( "CREATE $temporary TABLE $newTableName (LIKE $oldTableName $def)" ); } } else { # Hack for MySQL versions < 4.1, which don't support diff --git a/maintenance/parserTests.php b/maintenance/parserTests.php index 0d50feb1..9a1a4807 100644 --- a/maintenance/parserTests.php +++ b/maintenance/parserTests.php @@ -71,5 +71,5 @@ if ( isset( $options['fuzz'] ) ) { $tester->fuzzTest( $files ); } else { $ok = $tester->runTestsFromFiles( $files ); - exit ($ok ? 0 : -1); + exit ($ok ? 0 : 1); } diff --git a/maintenance/parserTests.txt b/maintenance/parserTests.txt index c84e0e35..1a427005 100644 --- a/maintenance/parserTests.txt +++ b/maintenance/parserTests.txt @@ -461,7 +461,7 @@ Definition list with wikilink containing colon !! input ; [[Help:FAQ]]: The least-read page on Wikipedia !! result -<dl><dt> <a href="/index.php?title=Help:FAQ&action=edit&redlink=1" class="new" title="Help:FAQ (not yet written)">Help:FAQ</a></dt><dd> The least-read page on Wikipedia +<dl><dt> <a href="/index.php?title=Help:FAQ&action=edit&redlink=1" class="new" title="Help:FAQ (page does not exist)">Help:FAQ</a></dt><dd> The least-read page on Wikipedia </dd></dl> !! end @@ -887,7 +887,7 @@ External links: wiki links within external link (Bug 3695) !! input [http://example.com [[wikilink]] embedded in ext link] !! result -<p><a href="http://example.com" class="external text" title="http://example.com" rel="nofollow"></a><a href="/index.php?title=Wikilink&action=edit&redlink=1" class="new" title="Wikilink (not yet written)">wikilink</a><a href="http://example.com" class="external text" title="http://example.com" rel="nofollow"> embedded in ext link</a> +<p><a href="http://example.com" class="external text" title="http://example.com" rel="nofollow"></a><a href="/index.php?title=Wikilink&action=edit&redlink=1" class="new" title="Wikilink (page does not exist)">wikilink</a><a href="http://example.com" class="external text" title="http://example.com" rel="nofollow"> embedded in ext link</a> </p> !! end @@ -1318,7 +1318,7 @@ Broken link !! input [[Zigzagzogzagzig]] !! result -<p><a href="/index.php?title=Zigzagzogzagzig&action=edit&redlink=1" class="new" title="Zigzagzogzagzig (not yet written)">Zigzagzogzagzig</a> +<p><a href="/index.php?title=Zigzagzogzagzig&action=edit&redlink=1" class="new" title="Zigzagzogzagzig (page does not exist)">Zigzagzogzagzig</a> </p> !! end @@ -1327,7 +1327,7 @@ Broken link with fragment !! input [[Zigzagzogzagzig#zug]] !! result -<p><a href="/index.php?title=Zigzagzogzagzig&action=edit&redlink=1" class="new" title="Zigzagzogzagzig (not yet written)">Zigzagzogzagzig#zug</a> +<p><a href="/index.php?title=Zigzagzogzagzig&action=edit&redlink=1" class="new" title="Zigzagzogzagzig (page does not exist)">Zigzagzogzagzig#zug</a> </p> !! end @@ -1345,7 +1345,7 @@ Nonexistent special page link with fragment !! input [[Special:ThisNameWillHopefullyNeverBeUsed#anchor]] !! result -<p><a href="/wiki/Special:ThisNameWillHopefullyNeverBeUsed" class="new" title="Special:ThisNameWillHopefullyNeverBeUsed (not yet written)">Special:ThisNameWillHopefullyNeverBeUsed#anchor</a> +<p><a href="/wiki/Special:ThisNameWillHopefullyNeverBeUsed" class="new" title="Special:ThisNameWillHopefullyNeverBeUsed (page does not exist)">Special:ThisNameWillHopefullyNeverBeUsed#anchor</a> </p> !! end @@ -1399,7 +1399,7 @@ Link to namespaces !! input [[Talk:Parser testing]], [[Meta:Disclaimers]] !! result -<p><a href="/index.php?title=Talk:Parser_testing&action=edit&redlink=1" class="new" title="Talk:Parser testing (not yet written)">Talk:Parser testing</a>, <a href="/index.php?title=Meta:Disclaimers&action=edit&redlink=1" class="new" title="Meta:Disclaimers (not yet written)">Meta:Disclaimers</a> +<p><a href="/index.php?title=Talk:Parser_testing&action=edit&redlink=1" class="new" title="Talk:Parser testing (page does not exist)">Talk:Parser testing</a>, <a href="/index.php?title=Meta:Disclaimers&action=edit&redlink=1" class="new" title="Meta:Disclaimers (page does not exist)">Meta:Disclaimers</a> </p> !! end @@ -1408,7 +1408,7 @@ Piped link to namespace !! input [[Meta:Disclaimers|The disclaimers]] !! result -<p><a href="/index.php?title=Meta:Disclaimers&action=edit&redlink=1" class="new" title="Meta:Disclaimers (not yet written)">The disclaimers</a> +<p><a href="/index.php?title=Meta:Disclaimers&action=edit&redlink=1" class="new" title="Meta:Disclaimers (page does not exist)">The disclaimers</a> </p> !! end @@ -1426,7 +1426,7 @@ Link containing % (not as a hex sequence) !! input [[7% Solution]] !! result -<p><a href="/index.php?title=7%25_Solution&action=edit&redlink=1" class="new" title="7% Solution (not yet written)">7% Solution</a> +<p><a href="/index.php?title=7%25_Solution&action=edit&redlink=1" class="new" title="7% Solution (page does not exist)">7% Solution</a> </p> !! end @@ -1435,7 +1435,7 @@ Link containing % as a single hex sequence interpreted to char !! input [[7%25 Solution]] !! result -<p><a href="/index.php?title=7%25_Solution&action=edit&redlink=1" class="new" title="7% Solution (not yet written)">7% Solution</a> +<p><a href="/index.php?title=7%25_Solution&action=edit&redlink=1" class="new" title="7% Solution (page does not exist)">7% Solution</a> </p> !!end @@ -1481,7 +1481,7 @@ Link containing double-single-quotes '' in text (bug 4598 sanity check) !! input Some [[Link|pretty ''italics'' and stuff]]! !! result -<p>Some <a href="/index.php?title=Link&action=edit&redlink=1" class="new" title="Link (not yet written)">pretty <i>italics</i> and stuff</a>! +<p>Some <a href="/index.php?title=Link&action=edit&redlink=1" class="new" title="Link (page does not exist)">pretty <i>italics</i> and stuff</a>! </p> !! end @@ -1490,7 +1490,7 @@ Link containing double-single-quotes '' in text embedded in italics (bug 4598 sa !! input ''Some [[Link|pretty ''italics'' and stuff]]! !! result -<p><i>Some </i><a href="/index.php?title=Link&action=edit&redlink=1" class="new" title="Link (not yet written)"><i>pretty </i>italics<i> and stuff</i></a><i>!</i> +<p><i>Some </i><a href="/index.php?title=Link&action=edit&redlink=1" class="new" title="Link (page does not exist)"><i>pretty </i>italics<i> and stuff</i></a><i>!</i> </p> !! end @@ -2171,7 +2171,7 @@ Magic links: internal link to RFC (bug 479) !! input [[RFC 123]] !! result -<p><a href="/index.php?title=RFC_123&action=edit&redlink=1" class="new" title="RFC 123 (not yet written)">RFC 123</a> +<p><a href="/index.php?title=RFC_123&action=edit&redlink=1" class="new" title="RFC 123 (page does not exist)">RFC 123</a> </p> !! end @@ -2211,7 +2211,7 @@ Nonexistent template !! input {{thistemplatedoesnotexist}} !! result -<p><a href="/index.php?title=Template:Thistemplatedoesnotexist&action=edit&redlink=1" class="new" title="Template:Thistemplatedoesnotexist (not yet written)">Template:Thistemplatedoesnotexist</a> +<p><a href="/index.php?title=Template:Thistemplatedoesnotexist&action=edit&redlink=1" class="new" title="Template:Thistemplatedoesnotexist (page does not exist)">Template:Thistemplatedoesnotexist</a> </p> !! end @@ -2393,7 +2393,7 @@ Template with thumb image (with link in description) {{paramtest| param =[[Image:noimage.png|thumb|[[no link|link]] [[no link|caption]]]]}} !! result -This is a test template with parameter <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/index.php?title=Special:Upload&wpDestFile=Noimage.png" class="new" title="File:Noimage.png">File:Noimage.png</a> <div class="thumbcaption"><a href="/index.php?title=No_link&action=edit&redlink=1" class="new" title="No link (not yet written)">link</a> <a href="/index.php?title=No_link&action=edit&redlink=1" class="new" title="No link (not yet written)">caption</a></div></div></div> +This is a test template with parameter <div class="thumb tright"><div class="thumbinner" style="width:182px;"><a href="/index.php?title=Special:Upload&wpDestFile=Noimage.png" class="new" title="File:Noimage.png">File:Noimage.png</a> <div class="thumbcaption"><a href="/index.php?title=No_link&action=edit&redlink=1" class="new" title="No link (page does not exist)">link</a> <a href="/index.php?title=No_link&action=edit&redlink=1" class="new" title="No link (page does not exist)">caption</a></div></div></div> !! end @@ -3233,7 +3233,7 @@ Add test with existing image page !! input [[:Image:test]] !! result -<p><a href="/index.php?title=File:Test&action=edit&redlink=1" class="new" title="File:Test (not yet written)">Image:test</a> +<p><a href="/index.php?title=File:Test&action=edit&redlink=1" class="new" title="File:Test (page does not exist)">Image:test</a> </p> !! end @@ -3442,7 +3442,7 @@ Disabled subpages !! input [[/subpage]] !! result -<p><a href="/index.php?title=/subpage&action=edit&redlink=1" class="new" title="/subpage (not yet written)">/subpage</a> +<p><a href="/index.php?title=/subpage&action=edit&redlink=1" class="new" title="/subpage (page does not exist)">/subpage</a> </p> !! end @@ -3453,7 +3453,7 @@ subpage title=[[Page]] !! input {{/Subpage}} !! result -<p><a href="/index.php?title=Page/Subpage&action=edit&redlink=1" class="new" title="Page/Subpage (not yet written)">Page/Subpage</a> +<p><a href="/index.php?title=Page/Subpage&action=edit&redlink=1" class="new" title="Page/Subpage (page does not exist)">Page/Subpage</a> </p> !! end @@ -4008,7 +4008,7 @@ Image link to nonexistent file (bug 1850 - good) !! input [[:Image:No such.jpg]] !! result -<p><a href="/index.php?title=File:No_such.jpg&action=edit&redlink=1" class="new" title="File:No such.jpg (not yet written)">Image:No such.jpg</a> +<p><a href="/index.php?title=File:No_such.jpg&action=edit&redlink=1" class="new" title="File:No such.jpg (page does not exist)">Image:No such.jpg</a> </p> !! end @@ -5242,7 +5242,7 @@ Special page transclusion !! result <p><br /> </p> -<table style="background: inherit;" border="0" width="100%"><tr><td><a href="/wiki/Xyzzyx" title="Xyzzyx">Xyzzyx</a></td></tr></table> +<table border="0" id="mw-prefixindex-list-table"><tr><td><a href="/wiki/Xyzzyx" title="Xyzzyx">Xyzzyx</a></td></tr></table> !! end @@ -5255,10 +5255,10 @@ Special page transclusion twice (bug 5021) !! result <p><br /> </p> -<table style="background: inherit;" border="0" width="100%"><tr><td><a href="/wiki/Xyzzyx" title="Xyzzyx">Xyzzyx</a></td></tr></table> +<table border="0" id="mw-prefixindex-list-table"><tr><td><a href="/wiki/Xyzzyx" title="Xyzzyx">Xyzzyx</a></td></tr></table> <p><br /> </p> -<table style="background: inherit;" border="0" width="100%"><tr><td><a href="/wiki/Xyzzyx" title="Xyzzyx">Xyzzyx</a></td></tr></table> +<table border="0" id="mw-prefixindex-list-table"><tr><td><a href="/wiki/Xyzzyx" title="Xyzzyx">Xyzzyx</a></td></tr></table> !! end @@ -5276,7 +5276,7 @@ Transclusion of nonexistent MediaWiki message !! input {{MediaWiki:Mainpagexxx}} !!result -<p><a href="/index.php?title=MediaWiki:Mainpagexxx&action=edit&redlink=1" class="new" title="MediaWiki:Mainpagexxx (not yet written)">MediaWiki:Mainpagexxx</a> +<p><a href="/index.php?title=MediaWiki:Mainpagexxx&action=edit&redlink=1" class="new" title="MediaWiki:Mainpagexxx (page does not exist)">MediaWiki:Mainpagexxx</a> </p> !! end @@ -6178,7 +6178,7 @@ Say the magic word </li><li> Talk </li><li> </li><li> -</li><li> <a href="/index.php?title=Template:Dynamic&action=edit&redlink=1" class="new" title="Template:Dynamic (not yet written)">Template:Dynamic</a> +</li><li> <a href="/index.php?title=Template:Dynamic&action=edit&redlink=1" class="new" title="Template:Dynamic (page does not exist)">Template:Dynamic</a> </li></ul> !! end @@ -6303,7 +6303,7 @@ Double RFC with a wiki link !! input RFC [[RFC 1234]] !! result -<p>RFC <a href="/index.php?title=RFC_1234&action=edit&redlink=1" class="new" title="RFC 1234 (not yet written)">RFC 1234</a> +<p>RFC <a href="/index.php?title=RFC_1234&action=edit&redlink=1" class="new" title="RFC 1234 (page does not exist)">RFC 1234</a> </p> !! end @@ -6435,7 +6435,7 @@ subpage title=[[Subpage test/L1/L2/L3]] !! input [[../|L2]] !! result -<p><a href="/index.php?title=Subpage_test/L1/L2&action=edit&redlink=1" class="new" title="Subpage test/L1/L2 (not yet written)">L2</a> +<p><a href="/index.php?title=Subpage_test/L1/L2&action=edit&redlink=1" class="new" title="Subpage test/L1/L2 (page does not exist)">L2</a> </p> !! end @@ -6447,7 +6447,7 @@ subpage title=[[Subpage test/L1/L2/L3]] !! input [[../]] !! result -<p><a href="/index.php?title=Subpage_test/L1/L2&action=edit&redlink=1" class="new" title="Subpage test/L1/L2 (not yet written)">Subpage test/L1/L2</a> +<p><a href="/index.php?title=Subpage_test/L1/L2&action=edit&redlink=1" class="new" title="Subpage test/L1/L2 (page does not exist)">Subpage test/L1/L2</a> </p> !! end @@ -6461,7 +6461,7 @@ subpage title=[[Subpage test/L1/L2/L3]] !! input [[../../|L1]]2 !! result -<p><a href="/index.php?title=Subpage_test/L1&action=edit&redlink=1" class="new" title="Subpage test/L1 (not yet written)">L1</a> +<p><a href="/index.php?title=Subpage_test/L1&action=edit&redlink=1" class="new" title="Subpage test/L1 (page does not exist)">L1</a> </p> !! end @@ -6483,7 +6483,7 @@ subpage title=[[Subpage test/L1/L2/L3]] !! input [[../../////]] !! result -<p><a href="/index.php?title=Subpage_test/L1////&action=edit&redlink=1" class="new" title="Subpage test/L1//// (not yet written)">///</a> +<p><a href="/index.php?title=Subpage_test/L1////&action=edit&redlink=1" class="new" title="Subpage test/L1//// (page does not exist)">///</a> </p> !! end @@ -6524,7 +6524,7 @@ RAW magic word !! input {{RAW:QUERTY}} !! result -<p><a href="/index.php?title=Template:QUERTY&action=edit&redlink=1" class="new" title="Template:QUERTY (not yet written)">Template:QUERTY</a> +<p><a href="/index.php?title=Template:QUERTY&action=edit&redlink=1" class="new" title="Template:QUERTY (page does not exist)">Template:QUERTY</a> </p> !! end @@ -7233,6 +7233,64 @@ language=fa </p> !! end +!! test +Multibyte character in padleft +!! input +{{padleft:-Hello|7|Æ}} +!! result +<p>Æ-Hello +</p> +!! end + +!! test +Multibyte character in padright +!! input +{{padright:Hello-|7|Æ}} +!! result +<p>Hello-Æ +</p> +!! end + +!! test +Formatted date +!! config +wgUseDynamicDates=1 +!! input +[[2009-03-24]] +!! result +<p><span class="mw-formatted-date" title="2009-03-24"><a href="/index.php?title=2009&action=edit&redlink=1" class="new" title="2009 (page does not exist)">2009</a>-<a href="/index.php?title=March_24&action=edit&redlink=1" class="new" title="March 24 (page does not exist)">03-24</a></span> +</p> +!!end + +!!test +formatdate parser function +!!input +{{#formatdate:2009-03-24}} +!! result +<p><span class="mw-formatted-date" title="2009-03-24">2009-03-24</span> +</p> +!! end + +!!test +formatdate parser function, with default format +!!input +{{#formatdate:2009-03-24|mdy}} +!! result +<p><span class="mw-formatted-date" title="2009-03-24">March 24, 2009</span> +</p> +!! end + +!! test +Linked date with autoformatting disabled +!! config +wgUseDynamicDates=false +!! input +[[2009-03-24]] +!! result +<p><a href="/index.php?title=2009-03-24&action=edit&redlink=1" class="new" title="2009-03-24 (page does not exist)">2009-03-24</a> +</p> +!!end + # # # diff --git a/maintenance/populateCategory.php b/maintenance/populateCategory.php index cb22e7f8..1dca7b74 100644 --- a/maintenance/populateCategory.php +++ b/maintenance/populateCategory.php @@ -36,6 +36,7 @@ vided name. Default: empty (start from beginning). drops before continuing. Default: 10. --throttle: Wait this many milliseconds after each category. Default: 0. --force: Run regardless of whether the database says it's been run already. + TEXT; exit( 0 ); } diff --git a/maintenance/postgres/archives/patch-change_tag.sql b/maintenance/postgres/archives/patch-change_tag.sql new file mode 100644 index 00000000..1f52c474 --- /dev/null +++ b/maintenance/postgres/archives/patch-change_tag.sql @@ -0,0 +1,28 @@ + +CREATE TABLE change_tag ( + ct_rc_id INTEGER NULL, + ct_log_id INTEGER NULL, + ct_rev_id INTEGER NULL, + ct_tag TEXT NOT NULL, + ct_params TEXT NULL +); +CREATE UNIQUE INDEX change_tag_rc_tag ON change_tag(ct_rc_id,ct_tag); +CREATE UNIQUE INDEX change_tag_log_tag ON change_tag(ct_log_id,ct_tag); +CREATE UNIQUE INDEX change_tag_rev_tag ON change_tag(ct_rev_id,ct_tag); +CREATE INDEX change_tag_tag_id ON change_tag(ct_tag,ct_rc_id,ct_rev_id,ct_log_id); + + +CREATE TABLE tag_summary ( + ts_rc_id INTEGER NULL, + ts_log_id INTEGER NULL, + ts_rev_id INTEGER NULL, + ts_tags TEXT NOT NULL +); +CREATE UNIQUE INDEX tag_summary_rc_id ON tag_summary(ts_rc_id); +CREATE UNIQUE INDEX tag_summary_log_id ON tag_summary(ts_log_id); +CREATE UNIQUE INDEX tag_summary_rev_id ON tag_summary(ts_rev_id); + + +CREATE TABLE valid_tag ( + vt_tag TEXT NOT NULL PRIMARY KEY +); diff --git a/maintenance/postgres/compare_schemas.pl b/maintenance/postgres/compare_schemas.pl index 144663df..850244ba 100644 --- a/maintenance/postgres/compare_schemas.pl +++ b/maintenance/postgres/compare_schemas.pl @@ -9,7 +9,7 @@ use warnings; use Data::Dumper; use Cwd; -check_valid_sql(); +#check_valid_sql(); my @old = ('../tables.sql'); my $new = 'tables.sql'; @@ -48,7 +48,7 @@ $datatype = qr{($datatype)}; my $typeval = qr{(\(\d+\))?}; -my $typeval2 = qr{ signed| unsigned| binary| NOT NULL| NULL| auto_increment| default ['\-\d\w"]+| REFERENCES .+CASCADE}; +my $typeval2 = qr{ signed| unsigned| binary| NOT NULL| NULL| PRIMARY KEY| AUTO_INCREMENT| default ['\-\d\w"]+| REFERENCES .+CASCADE}; my $indextype = join '|' => qw(INDEX KEY FULLTEXT), 'PRIMARY KEY', 'UNIQUE INDEX', 'UNIQUE KEY'; $indextype = qr{$indextype}; @@ -96,9 +96,15 @@ sub parse_sql { chomp; if (/CREATE\s*TABLE/i) { - m{^CREATE TABLE /\*\$wgDBprefix\*/(\w+) \($} - or die qq{Invalid CREATE TABLE at line $. of $oldfile\n}; - $table = $1; + if (m{^CREATE TABLE /\*_\*/(\w+) \($}) { + $table = $1; + } + elsif (m{^CREATE TABLE /\*\$wgDBprefix\*/(\w+) \($}) { + $table = $1; + } + else { + die qq{Invalid CREATE TABLE at line $. of $oldfile\n}; + } $info{$table}{name}=$table; } elsif (m{^\) /\*\$wgDBTableOptions\*/}) { @@ -114,14 +120,14 @@ sub parse_sql { $info{$table}{type}=$2; $info{$table}{charset}=$3; } - elsif (/^ (\w+) $datatype$typeval$typeval2{0,3},?$/) { + elsif (/^ (\w+) $datatype$typeval$typeval2{0,4},?$/) { $info{$table}{column}{$1} = $2; my $extra = $3 || ''; $info{$table}{columnfull}{$1} = "$2$extra"; } - elsif (/^ ($indextype)(?: (\w+))? \(([\w, \(\)]+)\),?$/) { - $info{$table}{lc $1.'_name'} = $2 ? $2 : ''; - $info{$table}{lc $1.'pk_target'} = $3; + elsif (m{^ UNIQUE KEY (\w+) \((.+?)\)}) { + } + elsif (m{^CREATE (?:UNIQUE )?(?:FULLTEXT )?INDEX /\*i\*/(\w+) ON /\*_\*/(\w+) \((.+?)\);}) { } else { die "Cannot parse line $. of $oldfile:\n$_\n"; @@ -152,15 +158,18 @@ while (<$pfh>) { close $pfh or die qq{Could not close "$parsefile": $!\n}; my $OK_NOT_IN_PTABLE = ' +change_tag filearchive logging profiling querycache_info searchindex +tag_summary trackbacks transcache user_newtalk updatelog +valid_tag '; ## Make sure all tables in main tables.sql are accounted for in the parsertest. @@ -301,6 +310,7 @@ rc_log_type varbinary(255) TEXT ## Simple text-only strings: ar_flags tinyblob TEXT +ct_params blob TEXT fa_minor_mime varbinary(32) TEXT fa_storage_group varbinary(16) TEXT # Just 'deleted' for now, should stay plain text fa_storage_key varbinary(64) TEXT # sha1 plus text extension @@ -331,6 +341,7 @@ qcc_type varbinary(32) TEXT qci_type varbinary(32) TEXT rc_params blob TEXT rlc_to_blob blob TEXT +ts_tags blob TEXT ug_group varbinary(16) TEXT user_email_token binary(32) TEXT user_ip varbinary(40) TEXT @@ -497,6 +508,8 @@ sub find_problems { my $file = shift; open my $fh, '<', $file or die qq{Could not open "$file": $!\n}; + my $lastline = ''; + my $inarray = 0; while (<$fh>) { if (/FORCE INDEX/ and $file !~ /Database\w*\.php/) { warn "Found FORCE INDEX string at line $. of $file\n"; @@ -513,6 +526,29 @@ sub find_problems { if (/\bGROUP\s+BY\s*\d\b/i and $file !~ /Database\w*\.php/) { warn "Found GROUP BY # at line $. of $file\n"; } + if (/wfGetDB\s*\(\s+\)/io) { + warn "wfGETDB is missing parameters at line $. of $file\n"; + } + if (/=\s*array\s*\(\s*$/) { + $inarray = 1; + next; + } + if ($inarray) { + if (/\s*\);\s*$/) { + $inarray = 0; + next; + } + next if ! /\w/ or /array\(\s*$/ or /^\s*#/ or m{^\s*//}; + if (! /,/) { + my $nextline = <$fh>; + last if ! defined $nextline; + if ($nextline =~ /^\s*\)[;,]/) { + $inarray = 0; + next; + } + #warn "Array is missing a comma? Line $. of $file\n"; + } + } } close $fh or die qq{Could not close "$file": $!\n}; return; diff --git a/maintenance/postgres/tables.sql b/maintenance/postgres/tables.sql index 93cee862..e8d5eb77 100644 --- a/maintenance/postgres/tables.sql +++ b/maintenance/postgres/tables.sql @@ -276,15 +276,15 @@ CREATE TABLE oldimage ( oi_size INTEGER NOT NULL, oi_width INTEGER NOT NULL, oi_height INTEGER NOT NULL, - oi_bits SMALLINT NOT NULL, + oi_bits SMALLINT NULL, oi_description TEXT, oi_user INTEGER NULL REFERENCES mwuser(user_id) ON DELETE SET NULL, oi_user_text TEXT NOT NULL, - oi_timestamp TIMESTAMPTZ NOT NULL, + oi_timestamp TIMESTAMPTZ NULL, oi_metadata BYTEA NOT NULL DEFAULT '', oi_media_type TEXT NULL, - oi_major_mime TEXT NOT NULL DEFAULT 'unknown', - oi_minor_mime TEXT NOT NULL DEFAULT 'unknown', + oi_major_mime TEXT NULL DEFAULT 'unknown', + oi_minor_mime TEXT NULL DEFAULT 'unknown', oi_deleted SMALLINT NOT NULL DEFAULT 0, oi_sha1 TEXT NOT NULL DEFAULT '' ); @@ -554,6 +554,32 @@ CREATE TABLE category ( CREATE UNIQUE INDEX category_title ON category(cat_title); CREATE INDEX category_pages ON category(cat_pages); +CREATE TABLE change_tag ( + ct_rc_id INTEGER NULL, + ct_log_id INTEGER NULL, + ct_rev_id INTEGER NULL, + ct_tag TEXT NOT NULL, + ct_params TEXT NULL +); +CREATE UNIQUE INDEX change_tag_rc_tag ON change_tag(ct_rc_id,ct_tag); +CREATE UNIQUE INDEX change_tag_log_tag ON change_tag(ct_log_id,ct_tag); +CREATE UNIQUE INDEX change_tag_rev_tag ON change_tag(ct_rev_id,ct_tag); +CREATE INDEX change_tag_tag_id ON change_tag(ct_tag,ct_rc_id,ct_rev_id,ct_log_id); + +CREATE TABLE tag_summary ( + ts_rc_id INTEGER NULL, + ts_log_id INTEGER NULL, + ts_rev_id INTEGER NULL, + ts_tags TEXT NOT NULL +); +CREATE UNIQUE INDEX tag_summary_rc_id ON tag_summary(ts_rc_id); +CREATE UNIQUE INDEX tag_summary_log_id ON tag_summary(ts_log_id); +CREATE UNIQUE INDEX tag_summary_rev_id ON tag_summary(ts_rev_id); + +CREATE TABLE valid_tag ( + vt_tag TEXT NOT NULL PRIMARY KEY +); + CREATE TABLE mediawiki_version ( type TEXT NOT NULL, mw_version TEXT NOT NULL, @@ -573,5 +599,5 @@ CREATE TABLE mediawiki_version ( ); INSERT INTO mediawiki_version (type,mw_version,sql_version,sql_date) - VALUES ('Creation','??','$LastChangedRevision: 41967 $','$LastChangedDate: 2008-10-11 07:08:10 -0500 (Sat, 11 Oct 2008) $'); + VALUES ('Creation','??','$LastChangedRevision: 48615 $','$LastChangedDate: 2009-03-19 20:15:41 -0500 (Thu, 19 Mar 2009) $'); diff --git a/maintenance/rebuildFileCache.php b/maintenance/rebuildFileCache.php index 125b8842..8c01b90f 100644 --- a/maintenance/rebuildFileCache.php +++ b/maintenance/rebuildFileCache.php @@ -17,6 +17,7 @@ $wgDisableCounters = false; // no real hits here $start = isset($args[0]) ? intval($args[0]) : 0; $overwrite = isset( $args[1] ) && $args[1] === 'overwrite'; echo "Building content page file cache from page {$start}!\n"; +echo "Format: <start> [overwrite]\n"; $dbr = wfGetDB( DB_SLAVE ); $start = $start > 0 ? $start : $dbr->selectField( 'page', 'MIN(page_id)', false, __FUNCTION__ ); @@ -34,6 +35,7 @@ $end += $BATCH_SIZE - 1; $blockStart = $start; $blockEnd = $start + $BATCH_SIZE - 1; +$dbw = wfGetDB( DB_MASTER ); // Go through each page and save the output while( $blockEnd <= $end ) { // Get the pages @@ -60,8 +62,6 @@ while( $blockEnd <= $end ) { echo "Page {$row->page_id} already cached\n"; continue; // done already! } - } else { - echo "Page {$row->page_id} not cached\n"; } ob_start( array(&$cache, 'saveToFileCache' ) ); // save on ob_end_clean() $wgUseFileCache = false; // hack, we don't want $wgArticle fiddling with filecache @@ -77,6 +77,7 @@ while( $blockEnd <= $end ) { } else { echo "Page {$row->page_id} not cacheable\n"; } + $dbw->commit(); // commit any changes } $blockStart += $BATCH_SIZE; $blockEnd += $BATCH_SIZE; diff --git a/maintenance/rebuildInterwiki.php b/maintenance/rebuildInterwiki.php index 9a3cfd98..8a25ce3c 100644 --- a/maintenance/rebuildInterwiki.php +++ b/maintenance/rebuildInterwiki.php @@ -12,8 +12,8 @@ $oldCwd = getcwd(); $optionsWithArgs = array( "d" ); -include_once( "commandLine.inc" ); -include_once( "rebuildInterwiki.inc" ); +require( "commandLine.inc" ); +require( "rebuildInterwiki.inc" ); chdir( $oldCwd ); # Output diff --git a/maintenance/refreshLinks.inc b/maintenance/refreshLinks.inc index 036d4109..b7d531c7 100644 --- a/maintenance/refreshLinks.inc +++ b/maintenance/refreshLinks.inc @@ -136,41 +136,67 @@ function fixLinksFromArticle( $id ) { $dbw->immediateCommit(); } -function deleteLinksFromNonexistent( $maxLag = 0 ) { - $fname = 'deleteLinksFromNonexistent'; - +/* + * Removes non-existing links from pages from pagelinks, imagelinks, + * categorylinks, templatelinks and externallinks tables. + * + * @param $maxLag + * @param $batchSize The size of deletion batches + * + * @author Merlijn van Deen <valhallasw@arctus.nl> + */ +function deleteLinksFromNonexistent( $maxLag = 0, $batchSize = 100 ) { wfWaitForSlaves( $maxLag ); - + $dbw = wfGetDB( DB_MASTER ); - $linksTables = array( + $lb = wfGetLBFactory()->newMainLB(); + $dbr = $lb->getConnection( DB_SLAVE ); + $dbr->bufferResults( false ); + + $linksTables = array( // table name => page_id field 'pagelinks' => 'pl_from', 'imagelinks' => 'il_from', 'categorylinks' => 'cl_from', 'templatelinks' => 'tl_from', 'externallinks' => 'el_from', ); - - $page = $dbw->tableName( 'page' ); - - + foreach ( $linksTables as $table => $field ) { - if ( !$dbw->ping() ) { - print "DB disconnected, reconnecting..."; - while ( !$dbw->ping() ) { - print "."; - sleep(10); + print "Retrieving illegal entries from $table... "; + + // SELECT DISTINCT( $field ) FROM $table LEFT JOIN page ON $field=page_id WHERE page_id IS NULL; + $results = $dbr->select( array( $table, 'page' ), + $field, + array('page_id' => null ), + __METHOD__, + 'DISTINCT', + array( 'page' => array( 'LEFT JOIN', "$field=page_id")) + ); + + $counter = 0; + $list = array(); + print "0.."; + + foreach( $results as $row ) { + $counter++; + $list[] = $row->$field; + if ( ( $counter % $batchSize ) == 0 ) { + wfWaitForSlaves(5); + $dbw->delete( $table, array( $field => $list ), __METHOD__ ); + + print $counter . ".."; + $list = array(); } - print "\n"; } - - $pTable = $dbw->tableName( $table ); - $sql = "DELETE $pTable FROM $pTable LEFT JOIN $page ON page_id=$field WHERE page_id IS NULL"; - - print "Deleting $table from non-existent articles..."; - $dbw->query( $sql, $fname ); - print " fixed " .$dbw->affectedRows() . " row(s)\n"; + + print $counter; + if (count($list) > 0) { + $dbw->delete( $table, array( $field => $list ), __METHOD__ ); + } + + print "\n"; } + + $lb->closeAll(); } - -?> diff --git a/maintenance/refreshLinks.php b/maintenance/refreshLinks.php index 4893d580..c7667520 100644 --- a/maintenance/refreshLinks.php +++ b/maintenance/refreshLinks.php @@ -5,7 +5,7 @@ */ /** */ -$optionsWithArgs = array( 'm', 'e' ); +$optionsWithArgs = array('batch-size', 'm', 'e' ); require_once( "commandLine.inc" ); require_once( "refreshLinks.inc" ); @@ -15,17 +15,19 @@ if( isset( $options['help'] ) ) { Usage: php refreshLinks.php --help php refreshLinks.php [<start>] [-e <end>] [-m <maxlag>] [--dfn-only] - [--new-only] [--redirects-only] + [--batch-size <size>] [--new-only] [--redirects-only] php refreshLinks.php [<start>] [-e <end>] [-m <maxlag>] --old-redirects-only - --help : This help message - --dfn-only : Delete links from nonexistent articles only - --new-only : Only affect articles with just a single edit - --redirects-only : Only fix redirects, not all links - --old-redirects-only : Only fix redirects with no redirect table entry - -m <number> : Maximum replication lag - <start> : First page id to refresh - -e <number> : Last page id to refresh + --help : This help message + --dfn-only : Delete links from nonexistent articles only + --batch-size <number> : The delete batch size when removing links from + nonexistent articles (defaults to 100) + --new-only : Only affect articles with just a single edit + --redirects-only : Only fix redirects, not all links + --old-redirects-only : Only fix redirects with no redirect table entry + -m <number> : Maximum replication lag + <start> : First page id to refresh + -e <number> : Last page id to refresh TEXT; exit(0); @@ -42,12 +44,13 @@ if ( !$options['dfn-only'] ) { refreshLinks( $start, $options['new-only'], $options['m'], $options['e'], $options['redirects-only'], $options['old-redirects-only'] ); } -// this bit's bad for replication: disabling temporarily -// --brion 2005-07-16 -//deleteLinksFromNonexistent(); -if ( $options['globals'] ) { - print_r( $GLOBALS ); +if ( !isset( $options['batch-size'] ) ) { + $options['batch-size'] = 100; } +deleteLinksFromNonexistent($options['m'], $options['batch-size']); +if ( $options['globals'] ) { + print_r( $GLOBALS ); +} diff --git a/maintenance/runJobs.php b/maintenance/runJobs.php index cee9cb1e..1340a857 100644 --- a/maintenance/runJobs.php +++ b/maintenance/runJobs.php @@ -10,11 +10,21 @@ * @ingroup Maintenance */ -$optionsWithArgs = array( 'maxjobs', 'type' ); +$optionsWithArgs = array( 'maxjobs', 'type', 'procs' ); $wgUseNormalUser = true; require_once( 'commandLine.inc' ); -require_once( "$IP/includes/JobQueue.php" ); -require_once( "$IP/includes/FakeTitle.php" ); + +if ( isset( $options['procs'] ) ) { + $procs = intval( $options['procs'] ); + if ( $procs < 1 || $procs > 1000 ) { + echo "Invalid argument to --procs\n"; + exit( 1 ); + } + $fc = new ForkController( $procs ); + if ( $fc->start( $procs ) != 'child' ) { + exit( 0 ); + } +} if ( isset( $options['maxjobs'] ) ) { $maxJobs = $options['maxjobs']; @@ -45,10 +55,15 @@ while ( $dbw->selectField( 'job', 'job_id', $conds, 'runJobs.php' ) ) { break; wfWaitForSlaves( 5 ); - print wfTimestamp( TS_DB ) . " " . $job->id . " " . $job->toString() . "\n"; + $t = microtime( true ); $offset=$job->id; - if ( !$job->run() ) { - print wfTimestamp( TS_DB ) . " Error: {$job->error}\n"; + $status = $job->run(); + $t = microtime( true ) - $t; + $timeMs = intval( $t * 1000 ); + if ( !$status ) { + runJobsLog( $job->toString() . " t=$timeMs error={$job->error}" ); + } else { + runJobsLog( $job->toString() . " t=$timeMs good" ); } if ( $maxJobs && ++$n > $maxJobs ) { break 2; @@ -56,3 +71,10 @@ while ( $dbw->selectField( 'job', 'job_id', $conds, 'runJobs.php' ) ) { } } + +function runJobsLog( $msg ) { + print wfTimestamp( TS_DB ) . " $msg\n"; + wfDebugLog( 'runJobs', $msg ); +} + + diff --git a/maintenance/showJobs.php b/maintenance/showJobs.php index d4f68db7..6e38c854 100644 --- a/maintenance/showJobs.php +++ b/maintenance/showJobs.php @@ -10,11 +10,6 @@ * @author Ashar Voultoiz */ require_once( 'commandLine.inc' ); -require_once( "$IP/includes/JobQueue.php" ); -require_once( "$IP/includes/FakeTitle.php" ); - -// Trigger errors on inappropriate use of $wgTitle -$wgTitle = new FakeTitle; $dbw = wfGetDB( DB_MASTER ); $count = $dbw->selectField( 'job', 'count(*)', '', 'runJobs.php' ); diff --git a/maintenance/sqlite/README b/maintenance/sqlite/README new file mode 100644 index 00000000..b8a45553 --- /dev/null +++ b/maintenance/sqlite/README @@ -0,0 +1,12 @@ +SQLite shares the MySQL schema file at maintenance/tables.sql, with a set of +compatibility regexes to convert MySQL syntax to SQLite syntax: + +* BINARY() and VARBINARY() fields are converted to BLOB +* the UNSIGNED modifier is removed +* "INT" fields are converted to "INTEGER" +* ENUM is converted to BLOB +* the BINARY collation modifier is removed +* AUTO_INCREMENT is converted to AUTOINCREMENT +* Any table options are removed +* Truncated indexes are upgraded to full-width indexes +* FULLTEXT indexes are converted to ordinary indexes diff --git a/maintenance/sqlite/archives/initial-indexes.sql b/maintenance/sqlite/archives/initial-indexes.sql new file mode 100644 index 00000000..a88b7a26 --- /dev/null +++ b/maintenance/sqlite/archives/initial-indexes.sql @@ -0,0 +1,417 @@ +-- Correct for the total lack of indexes in the MW 1.13 SQLite schema +-- +-- Unique indexes need to be handled with INSERT SELECT since just running +-- the CREATE INDEX statement will fail if there are duplicate values. +-- +-- Ignore duplicates, several tables will have them (e.g. bug 16966) but in +-- most cases it's harmless to discard them. We'll keep the old tables with +-- duplicates in so that the user can recover them in case of disaster. + +-------------------------------------------------------------------------------- +-- Drop temporary tables from aborted runs +-------------------------------------------------------------------------------- + +DROP TABLE IF EXISTS /*_*/user_tmp; +DROP TABLE IF EXISTS /*_*/user_groups_tmp; +DROP TABLE IF EXISTS /*_*/page_tmp; +DROP TABLE IF EXISTS /*_*/revision_tmp; +DROP TABLE IF EXISTS /*_*/pagelinks_tmp; +DROP TABLE IF EXISTS /*_*/templatelinks_tmp; +DROP TABLE IF EXISTS /*_*/imagelinks_tmp; +DROP TABLE IF EXISTS /*_*/categorylinks_tmp; +DROP TABLE IF EXISTS /*_*/category_tmp; +DROP TABLE IF EXISTS /*_*/langlinks_tmp; +DROP TABLE IF EXISTS /*_*/site_stats_tmp; +DROP TABLE IF EXISTS /*_*/ipblocks_tmp; +DROP TABLE IF EXISTS /*_*/watchlist_tmp; +DROP TABLE IF EXISTS /*_*/math_tmp; +DROP TABLE IF EXISTS /*_*/interwiki_tmp; +DROP TABLE IF EXISTS /*_*/page_restrictions_tmp; +DROP TABLE IF EXISTS /*_*/protected_titles_tmp; +DROP TABLE IF EXISTS /*_*/page_props_tmp; + +-------------------------------------------------------------------------------- +-- Create new tables +-------------------------------------------------------------------------------- + +CREATE TABLE /*_*/user_tmp ( + user_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT, + user_name varchar(255) binary NOT NULL default '', + user_real_name varchar(255) binary NOT NULL default '', + user_password tinyblob NOT NULL, + user_newpassword tinyblob NOT NULL, + user_newpass_time binary(14), + user_email tinytext NOT NULL, + user_options blob NOT NULL, + user_touched binary(14) NOT NULL default '', + user_token binary(32) NOT NULL default '', + user_email_authenticated binary(14), + user_email_token binary(32), + user_email_token_expires binary(14), + user_registration binary(14), + user_editcount int +); +CREATE UNIQUE INDEX /*i*/user_name ON /*_*/user_tmp (user_name); +CREATE INDEX /*i*/user_email_token ON /*_*/user_tmp (user_email_token); + + +CREATE TABLE /*_*/user_groups_tmp ( + ug_user int unsigned NOT NULL default 0, + ug_group varbinary(16) NOT NULL default '' +); + +CREATE UNIQUE INDEX /*i*/ug_user_group ON /*_*/user_groups_tmp (ug_user,ug_group); +CREATE INDEX /*i*/ug_group ON /*_*/user_groups_tmp (ug_group); + +CREATE TABLE /*_*/page_tmp ( + page_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT, + page_namespace int NOT NULL, + page_title varchar(255) binary NOT NULL, + page_restrictions tinyblob NOT NULL, + page_counter bigint unsigned NOT NULL default 0, + page_is_redirect tinyint unsigned NOT NULL default 0, + page_is_new tinyint unsigned NOT NULL default 0, + page_random real unsigned NOT NULL, + page_touched binary(14) NOT NULL default '', + page_latest int unsigned NOT NULL, + page_len int unsigned NOT NULL +); + +CREATE UNIQUE INDEX /*i*/name_title ON /*_*/page_tmp (page_namespace,page_title); +CREATE INDEX /*i*/page_random ON /*_*/page_tmp (page_random); +CREATE INDEX /*i*/page_len ON /*_*/page_tmp (page_len); + + +CREATE TABLE /*_*/revision_tmp ( + rev_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT, + rev_page int unsigned NOT NULL, + rev_text_id int unsigned NOT NULL, + rev_comment tinyblob NOT NULL, + rev_user int unsigned NOT NULL default 0, + rev_user_text varchar(255) binary NOT NULL default '', + rev_timestamp binary(14) NOT NULL default '', + rev_minor_edit tinyint unsigned NOT NULL default 0, + rev_deleted tinyint unsigned NOT NULL default 0, + rev_len int unsigned, + rev_parent_id int unsigned default NULL +); +CREATE UNIQUE INDEX /*i*/rev_page_id ON /*_*/revision_tmp (rev_page, rev_id); +CREATE INDEX /*i*/rev_timestamp ON /*_*/revision_tmp (rev_timestamp); +CREATE INDEX /*i*/page_timestamp ON /*_*/revision_tmp (rev_page,rev_timestamp); +CREATE INDEX /*i*/user_timestamp ON /*_*/revision_tmp (rev_user,rev_timestamp); +CREATE INDEX /*i*/usertext_timestamp ON /*_*/revision_tmp (rev_user_text,rev_timestamp); + +CREATE TABLE /*_*/pagelinks_tmp ( + pl_from int unsigned NOT NULL default 0, + pl_namespace int NOT NULL default 0, + pl_title varchar(255) binary NOT NULL default '' +); + +CREATE UNIQUE INDEX /*i*/pl_from ON /*_*/pagelinks_tmp (pl_from,pl_namespace,pl_title); +CREATE INDEX /*i*/pl_namespace_title ON /*_*/pagelinks_tmp (pl_namespace,pl_title,pl_from); + + +CREATE TABLE /*_*/templatelinks_tmp ( + tl_from int unsigned NOT NULL default 0, + tl_namespace int NOT NULL default 0, + tl_title varchar(255) binary NOT NULL default '' +); + +CREATE UNIQUE INDEX /*i*/tl_from ON /*_*/templatelinks_tmp (tl_from,tl_namespace,tl_title); +CREATE INDEX /*i*/tl_namespace_title ON /*_*/templatelinks_tmp (tl_namespace,tl_title,tl_from); + + +CREATE TABLE /*_*/imagelinks_tmp ( + il_from int unsigned NOT NULL default 0, + il_to varchar(255) binary NOT NULL default '' +) /*$wgDBTableOptions*/; +CREATE UNIQUE INDEX /*i*/il_from ON /*_*/imagelinks_tmp (il_from,il_to); +CREATE INDEX /*i*/il_to ON /*_*/imagelinks_tmp (il_to,il_from); + + +CREATE TABLE /*_*/categorylinks_tmp ( + cl_from int unsigned NOT NULL default 0, + cl_to varchar(255) binary NOT NULL default '', + cl_sortkey varchar(70) binary NOT NULL default '', + cl_timestamp timestamp NOT NULL +); +CREATE UNIQUE INDEX /*i*/cl_from ON /*_*/categorylinks_tmp (cl_from,cl_to); +CREATE INDEX /*i*/cl_sortkey ON /*_*/categorylinks_tmp (cl_to,cl_sortkey,cl_from); +CREATE INDEX /*i*/cl_timestamp ON /*_*/categorylinks_tmp (cl_to,cl_timestamp); + + +CREATE TABLE /*_*/category_tmp ( + cat_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT, + cat_title varchar(255) binary NOT NULL, + cat_pages int signed NOT NULL default 0, + cat_subcats int signed NOT NULL default 0, + cat_files int signed NOT NULL default 0, + cat_hidden tinyint unsigned NOT NULL default 0 +); +CREATE UNIQUE INDEX /*i*/cat_title ON /*_*/category_tmp (cat_title); +CREATE INDEX /*i*/cat_pages ON /*_*/category_tmp (cat_pages); + +CREATE TABLE /*_*/langlinks_tmp ( + ll_from int unsigned NOT NULL default 0, + ll_lang varbinary(20) NOT NULL default '', + ll_title varchar(255) binary NOT NULL default '' +); + +CREATE UNIQUE INDEX /*i*/ll_from ON /*_*/langlinks_tmp (ll_from, ll_lang); +CREATE INDEX /*i*/ll_lang_title ON /*_*/langlinks_tmp (ll_lang, ll_title); + + +CREATE TABLE /*_*/site_stats_tmp ( + ss_row_id int unsigned NOT NULL, + ss_total_views bigint unsigned default 0, + ss_total_edits bigint unsigned default 0, + ss_good_articles bigint unsigned default 0, + ss_total_pages bigint default '-1', + ss_users bigint default '-1', + ss_active_users bigint default '-1', + ss_admins int default '-1', + ss_images int default 0 +); +CREATE UNIQUE INDEX /*i*/ss_row_id ON /*_*/site_stats_tmp (ss_row_id); + + +CREATE TABLE /*_*/ipblocks_tmp ( + ipb_id int NOT NULL PRIMARY KEY AUTO_INCREMENT, + ipb_address tinyblob NOT NULL, + ipb_user int unsigned NOT NULL default 0, + ipb_by int unsigned NOT NULL default 0, + ipb_by_text varchar(255) binary NOT NULL default '', + ipb_reason tinyblob NOT NULL, + ipb_timestamp binary(14) NOT NULL default '', + ipb_auto bool NOT NULL default 0, + + -- If set to 1, block applies only to logged-out users + ipb_anon_only bool NOT NULL default 0, + ipb_create_account bool NOT NULL default 1, + ipb_enable_autoblock bool NOT NULL default '1', + ipb_expiry varbinary(14) NOT NULL default '', + ipb_range_start tinyblob NOT NULL, + ipb_range_end tinyblob NOT NULL, + ipb_deleted bool NOT NULL default 0, + ipb_block_email bool NOT NULL default 0, + ipb_allow_usertalk bool NOT NULL default 0 +); +CREATE UNIQUE INDEX /*i*/ipb_address ON /*_*/ipblocks_tmp (ipb_address(255), ipb_user, ipb_auto, ipb_anon_only); +CREATE INDEX /*i*/ipb_user ON /*_*/ipblocks_tmp (ipb_user); +CREATE INDEX /*i*/ipb_range ON /*_*/ipblocks_tmp (ipb_range_start(8), ipb_range_end(8)); +CREATE INDEX /*i*/ipb_timestamp ON /*_*/ipblocks_tmp (ipb_timestamp); +CREATE INDEX /*i*/ipb_expiry ON /*_*/ipblocks_tmp (ipb_expiry); + + +CREATE TABLE /*_*/watchlist_tmp ( + wl_user int unsigned NOT NULL, + wl_namespace int NOT NULL default 0, + wl_title varchar(255) binary NOT NULL default '', + wl_notificationtimestamp varbinary(14) +); + +CREATE UNIQUE INDEX /*i*/wl_user_namespace_title ON /*_*/watchlist_tmp (wl_user, wl_namespace, wl_title); +CREATE INDEX /*i*/namespace_title ON /*_*/watchlist_tmp (wl_namespace, wl_title); + + +CREATE TABLE /*_*/math_tmp ( + math_inputhash varbinary(16) NOT NULL, + math_outputhash varbinary(16) NOT NULL, + math_html_conservativeness tinyint NOT NULL, + math_html text, + math_mathml text +); + +CREATE UNIQUE INDEX /*i*/math_inputhash ON /*_*/math_tmp (math_inputhash); + + +CREATE TABLE /*_*/interwiki_tmp ( + iw_prefix varchar(32) NOT NULL, + iw_url blob NOT NULL, + iw_local bool NOT NULL, + iw_trans tinyint NOT NULL default 0 +); + +CREATE UNIQUE INDEX /*i*/iw_prefix ON /*_*/interwiki_tmp (iw_prefix); + + +CREATE TABLE /*_*/page_restrictions_tmp ( + pr_page int NOT NULL, + pr_type varbinary(60) NOT NULL, + pr_level varbinary(60) NOT NULL, + pr_cascade tinyint NOT NULL, + pr_user int NULL, + pr_expiry varbinary(14) NULL, + pr_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT +); + +CREATE UNIQUE INDEX /*i*/pr_pagetype ON /*_*/page_restrictions_tmp (pr_page,pr_type); +CREATE UNIQUE INDEX /*i*/pr_typelevel ON /*_*/page_restrictions_tmp (pr_type,pr_level); +CREATE UNIQUE INDEX /*i*/pr_level ON /*_*/page_restrictions_tmp (pr_level); +CREATE UNIQUE INDEX /*i*/pr_cascade ON /*_*/page_restrictions_tmp (pr_cascade); + +CREATE TABLE /*_*/protected_titles_tmp ( + pt_namespace int NOT NULL, + pt_title varchar(255) binary NOT NULL, + pt_user int unsigned NOT NULL, + pt_reason tinyblob, + pt_timestamp binary(14) NOT NULL, + pt_expiry varbinary(14) NOT NULL default '', + pt_create_perm varbinary(60) NOT NULL +); +CREATE UNIQUE INDEX /*i*/pt_namespace_title ON /*_*/protected_titles_tmp (pt_namespace,pt_title); +CREATE INDEX /*i*/pt_timestamp ON /*_*/protected_titles_tmp (pt_timestamp); + +CREATE TABLE /*_*/page_props_tmp ( + pp_page int NOT NULL, + pp_propname varbinary(60) NOT NULL, + pp_value blob NOT NULL +); +CREATE UNIQUE INDEX /*i*/pp_page_propname ON /*_*/page_props_tmp (pp_page,pp_propname); + +-------------------------------------------------------------------------------- +-- Populate the new tables using INSERT SELECT +-------------------------------------------------------------------------------- + +INSERT OR IGNORE INTO /*_*/user_tmp SELECT * FROM /*_*/user; +INSERT OR IGNORE INTO /*_*/user_groups_tmp SELECT * FROM /*_*/user_groups; +INSERT OR IGNORE INTO /*_*/page_tmp SELECT * FROM /*_*/page; +INSERT OR IGNORE INTO /*_*/revision_tmp SELECT * FROM /*_*/revision; +INSERT OR IGNORE INTO /*_*/pagelinks_tmp SELECT * FROM /*_*/pagelinks; +INSERT OR IGNORE INTO /*_*/templatelinks_tmp SELECT * FROM /*_*/templatelinks; +INSERT OR IGNORE INTO /*_*/imagelinks_tmp SELECT * FROM /*_*/imagelinks; +INSERT OR IGNORE INTO /*_*/categorylinks_tmp SELECT * FROM /*_*/categorylinks; +INSERT OR IGNORE INTO /*_*/category_tmp SELECT * FROM /*_*/category; +INSERT OR IGNORE INTO /*_*/langlinks_tmp SELECT * FROM /*_*/langlinks; +INSERT OR IGNORE INTO /*_*/site_stats_tmp SELECT * FROM /*_*/site_stats; +INSERT OR IGNORE INTO /*_*/ipblocks_tmp SELECT * FROM /*_*/ipblocks; +INSERT OR IGNORE INTO /*_*/watchlist_tmp SELECT * FROM /*_*/watchlist; +INSERT OR IGNORE INTO /*_*/math_tmp SELECT * FROM /*_*/math; +INSERT OR IGNORE INTO /*_*/interwiki_tmp SELECT * FROM /*_*/interwiki; +INSERT OR IGNORE INTO /*_*/page_restrictions_tmp SELECT * FROM /*_*/page_restrictions; +INSERT OR IGNORE INTO /*_*/protected_titles_tmp SELECT * FROM /*_*/protected_titles; +INSERT OR IGNORE INTO /*_*/page_props_tmp SELECT * FROM /*_*/page_props; + +-------------------------------------------------------------------------------- +-- Do the table renames +-------------------------------------------------------------------------------- + +ALTER TABLE /*_*/user RENAME TO /*_*/user_old_13; +ALTER TABLE /*_*/user_tmp RENAME TO /*_*/user; +ALTER TABLE /*_*/user_groups RENAME TO /*_*/user_groups_old_13; +ALTER TABLE /*_*/user_groups_tmp RENAME TO /*_*/user_groups; +ALTER TABLE /*_*/page RENAME TO /*_*/page_old_13; +ALTER TABLE /*_*/page_tmp RENAME TO /*_*/page; +ALTER TABLE /*_*/revision RENAME TO /*_*/revision_old_13; +ALTER TABLE /*_*/revision_tmp RENAME TO /*_*/revision; +ALTER TABLE /*_*/pagelinks RENAME TO /*_*/pagelinks_old_13; +ALTER TABLE /*_*/pagelinks_tmp RENAME TO /*_*/pagelinks; +ALTER TABLE /*_*/templatelinks RENAME TO /*_*/templatelinks_old_13; +ALTER TABLE /*_*/templatelinks_tmp RENAME TO /*_*/templatelinks; +ALTER TABLE /*_*/imagelinks RENAME TO /*_*/imagelinks_old_13; +ALTER TABLE /*_*/imagelinks_tmp RENAME TO /*_*/imagelinks; +ALTER TABLE /*_*/categorylinks RENAME TO /*_*/categorylinks_old_13; +ALTER TABLE /*_*/categorylinks_tmp RENAME TO /*_*/categorylinks; +ALTER TABLE /*_*/category RENAME TO /*_*/category_old_13; +ALTER TABLE /*_*/category_tmp RENAME TO /*_*/category; +ALTER TABLE /*_*/langlinks RENAME TO /*_*/langlinks_old_13; +ALTER TABLE /*_*/langlinks_tmp RENAME TO /*_*/langlinks; +ALTER TABLE /*_*/site_stats RENAME TO /*_*/site_stats_old_13; +ALTER TABLE /*_*/site_stats_tmp RENAME TO /*_*/site_stats; +ALTER TABLE /*_*/ipblocks RENAME TO /*_*/ipblocks_old_13; +ALTER TABLE /*_*/ipblocks_tmp RENAME TO /*_*/ipblocks; +ALTER TABLE /*_*/watchlist RENAME TO /*_*/watchlist_old_13; +ALTER TABLE /*_*/watchlist_tmp RENAME TO /*_*/watchlist; +ALTER TABLE /*_*/math RENAME TO /*_*/math_old_13; +ALTER TABLE /*_*/math_tmp RENAME TO /*_*/math; +ALTER TABLE /*_*/interwiki RENAME TO /*_*/interwiki_old_13; +ALTER TABLE /*_*/interwiki_tmp RENAME TO /*_*/interwiki; +ALTER TABLE /*_*/page_restrictions RENAME TO /*_*/page_restrictions_old_13; +ALTER TABLE /*_*/page_restrictions_tmp RENAME TO /*_*/page_restrictions; +ALTER TABLE /*_*/protected_titles RENAME TO /*_*/protected_titles_old_13; +ALTER TABLE /*_*/protected_titles_tmp RENAME TO /*_*/protected_titles; +ALTER TABLE /*_*/page_props RENAME TO /*_*/page_props_old_13; +ALTER TABLE /*_*/page_props_tmp RENAME TO /*_*/page_props; + +-------------------------------------------------------------------------------- +-- Drop and create tables with unique indexes but no valuable data +-------------------------------------------------------------------------------- + + +DROP TABLE IF EXISTS /*_*/searchindex; +CREATE TABLE /*_*/searchindex ( + si_page int unsigned NOT NULL, + si_title varchar(255) NOT NULL default '', + si_text mediumtext NOT NULL +); +CREATE UNIQUE INDEX /*i*/si_page ON /*_*/searchindex (si_page); +CREATE INDEX /*i*/si_title ON /*_*/searchindex (si_title); +CREATE INDEX /*i*/si_text ON /*_*/searchindex (si_text); + +DROP TABLE IF EXISTS /*_*/transcache; +CREATE TABLE /*_*/transcache ( + tc_url varbinary(255) NOT NULL, + tc_contents text, + tc_time int NOT NULL +) /*$wgDBTableOptions*/; +CREATE UNIQUE INDEX /*i*/tc_url_idx ON /*_*/transcache (tc_url); + +DROP TABLE IF EXISTS /*_*/querycache_info; +CREATE TABLE /*_*/querycache_info ( + qci_type varbinary(32) NOT NULL default '', + qci_timestamp binary(14) NOT NULL default '19700101000000' +) /*$wgDBTableOptions*/; +CREATE UNIQUE INDEX /*i*/qci_type ON /*_*/querycache_info (qci_type); + +-------------------------------------------------------------------------------- +-- Empty some cache tables to make the update faster +-------------------------------------------------------------------------------- + +DELETE FROM /*_*/querycache; +DELETE FROM /*_*/objectcache; +DELETE FROM /*_*/querycachetwo; + +-------------------------------------------------------------------------------- +-- Add indexes to tables with no unique indexes +-------------------------------------------------------------------------------- + +CREATE INDEX /*i*/un_user_id ON /*_*/user_newtalk (user_id); +CREATE INDEX /*i*/un_user_ip ON /*_*/user_newtalk (user_ip); +CREATE INDEX /*i*/name_title_timestamp ON /*_*/archive (ar_namespace,ar_title,ar_timestamp); +CREATE INDEX /*i*/ar_usertext_timestamp ON /*_*/archive (ar_user_text,ar_timestamp); +CREATE INDEX /*i*/el_from ON /*_*/externallinks (el_from, el_to(40)); +CREATE INDEX /*i*/el_to ON /*_*/externallinks (el_to(60), el_from); +CREATE INDEX /*i*/el_index ON /*_*/externallinks (el_index(60)); +CREATE INDEX /*i*/img_usertext_timestamp ON /*_*/image (img_user_text,img_timestamp); +CREATE INDEX /*i*/img_size ON /*_*/image (img_size); +CREATE INDEX /*i*/img_timestamp ON /*_*/image (img_timestamp); +CREATE INDEX /*i*/img_sha1 ON /*_*/image (img_sha1); +CREATE INDEX /*i*/oi_usertext_timestamp ON /*_*/oldimage (oi_user_text,oi_timestamp); +CREATE INDEX /*i*/oi_name_timestamp ON /*_*/oldimage (oi_name,oi_timestamp); +CREATE INDEX /*i*/oi_name_archive_name ON /*_*/oldimage (oi_name,oi_archive_name(14)); +CREATE INDEX /*i*/oi_sha1 ON /*_*/oldimage (oi_sha1); +CREATE INDEX /*i*/fa_name ON /*_*/filearchive (fa_name, fa_timestamp); +CREATE INDEX /*i*/fa_group_key ON /*_*/filearchive (fa_storage_group, fa_storage_key); +CREATE INDEX /*i*/fa_deleted_timestamp ON /*_*/filearchive (fa_deleted_timestamp); +CREATE INDEX /*i*/fa_user_timestamp ON /*_*/filearchive (fa_user_text,fa_timestamp); +CREATE INDEX /*i*/rc_timestamp ON /*_*/recentchanges (rc_timestamp); +CREATE INDEX /*i*/rc_namespace_title ON /*_*/recentchanges (rc_namespace, rc_title); +CREATE INDEX /*i*/rc_cur_id ON /*_*/recentchanges (rc_cur_id); +CREATE INDEX /*i*/new_name_timestamp ON /*_*/recentchanges (rc_new,rc_namespace,rc_timestamp); +CREATE INDEX /*i*/rc_ip ON /*_*/recentchanges (rc_ip); +CREATE INDEX /*i*/rc_ns_usertext ON /*_*/recentchanges (rc_namespace, rc_user_text); +CREATE INDEX /*i*/rc_user_text ON /*_*/recentchanges (rc_user_text, rc_timestamp); +CREATE INDEX /*i*/qc_type_value ON /*_*/querycache (qc_type,qc_value); +CREATE INDEX /*i*/oc_exptime ON /*_*/objectcache (exptime); +CREATE INDEX /*i*/type_time ON /*_*/logging (log_type, log_timestamp); +CREATE INDEX /*i*/user_time ON /*_*/logging (log_user, log_timestamp); +CREATE INDEX /*i*/page_time ON /*_*/logging (log_namespace, log_title, log_timestamp); +CREATE INDEX /*i*/times ON /*_*/logging (log_timestamp); +CREATE INDEX /*i*/tb_page ON /*_*/trackbacks (tb_page); +CREATE INDEX /*i*/job_cmd_namespace_title ON /*_*/job (job_cmd, job_namespace, job_title); +CREATE INDEX /*i*/rd_ns_title ON /*_*/redirect (rd_namespace,rd_title,rd_from); +CREATE INDEX /*i*/qcc_type ON /*_*/querycachetwo (qcc_type,qcc_value); +CREATE INDEX /*i*/qcc_title ON /*_*/querycachetwo (qcc_type,qcc_namespace,qcc_title); +CREATE INDEX /*i*/qcc_titletwo ON /*_*/querycachetwo (qcc_type,qcc_namespacetwo,qcc_titletwo); + +INSERT INTO /*_*/updatelog VALUES ('initial_indexes'); diff --git a/maintenance/sqlite/tables.sql b/maintenance/sqlite/tables.sql deleted file mode 100644 index 13e2a19b..00000000 --- a/maintenance/sqlite/tables.sql +++ /dev/null @@ -1,340 +0,0 @@ -CREATE TABLE /*$wgDBprefix*/user ( - user_id INTEGER PRIMARY KEY AUTOINCREMENT, - user_name varchar(255) default '', - user_real_name varchar(255) default '', - user_password tinyblob , - user_newpassword tinyblob , - user_newpass_time BLOB, - user_email tinytext , - user_options blob , - user_touched BLOB default '', - user_token BLOB default '', - user_email_authenticated BLOB, - user_email_token BLOB, - user_email_token_expires BLOB, - user_registration BLOB, - user_editcount int) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/user_groups ( - ug_user INTEGER default '0', - ug_group varBLOB default '') /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/user_newtalk ( - user_id INTEGER default '0', - user_ip varBLOB default '', - user_last_timestamp BLOB default '') /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/page ( - page_id INTEGER PRIMARY KEY AUTOINCREMENT, - page_namespace INTEGER , - page_title varchar(255) , - page_restrictions tinyblob , - page_counter bigint default '0', - page_is_redirect tinyint default '0', - page_is_new tinyint default '0', - page_random real , - page_touched BLOB default '', - page_latest INTEGER , - page_len INTEGER ) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/revision ( - rev_id INTEGER PRIMARY KEY AUTOINCREMENT, - rev_page INTEGER , - rev_text_id INTEGER , - rev_comment tinyblob , - rev_user INTEGER default '0', - rev_user_text varchar(255) default '', - rev_timestamp BLOB default '', - rev_minor_edit tinyint default '0', - rev_deleted tinyint default '0', - rev_len int, - rev_parent_id INTEGER default NULL) /*$wgDBTableOptions*/ ; - -CREATE TABLE /*$wgDBprefix*/text ( - old_id INTEGER PRIMARY KEY AUTOINCREMENT, - old_text mediumblob , - old_flags tinyblob ) /*$wgDBTableOptions*/ ; - -CREATE TABLE /*$wgDBprefix*/archive ( - ar_namespace INTEGER default '0', - ar_title varchar(255) default '', - ar_text mediumblob , - ar_comment tinyblob , - ar_user INTEGER default '0', - ar_user_text varchar(255) , - ar_timestamp BLOB default '', - ar_minor_edit tinyint default '0', - ar_flags tinyblob , - ar_rev_id int, - ar_text_id int, - ar_deleted tinyint default '0', - ar_len int, - ar_page_id int, - ar_parent_id INTEGER default NULL) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/pagelinks ( - pl_from INTEGER default '0', - pl_namespace INTEGER default '0', - pl_title varchar(255) default '') /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/templatelinks ( - tl_from INTEGER default '0', - tl_namespace INTEGER default '0', - tl_title varchar(255) default '') /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/imagelinks ( - il_from INTEGER default '0', - il_to varchar(255) default '') /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/categorylinks ( - cl_from INTEGER default '0', - cl_to varchar(255) default '', - cl_sortkey varchar(70) default '', - cl_timestamp timestamp ) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/category ( - cat_id INTEGER PRIMARY KEY AUTOINCREMENT, - cat_title varchar(255) , - cat_pages INTEGER signed default 0, - cat_subcats INTEGER signed default 0, - cat_files INTEGER signed default 0, - cat_hidden tinyint default 0) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/externallinks ( - el_from INTEGER default '0', - el_to blob , - el_index blob ) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/langlinks ( - ll_from INTEGER default '0', - ll_lang varBLOB default '', - ll_title varchar(255) default '') /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/site_stats ( - ss_row_id INTEGER , - ss_total_views bigint default '0', - ss_total_edits bigint default '0', - ss_good_articles bigint default '0', - ss_total_pages bigint default '-1', - ss_users bigint default '-1', - ss_admins INTEGER default '-1', - ss_images INTEGER default '0') /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/hitcounter ( - hc_id INTEGER -) ; - -CREATE TABLE /*$wgDBprefix*/ipblocks ( - ipb_id INTEGER PRIMARY KEY AUTOINCREMENT, - ipb_address tinyblob , - ipb_user INTEGER default '0', - ipb_by INTEGER default '0', - ipb_by_text varchar(255) default '', - ipb_reason tinyblob , - ipb_timestamp BLOB default '', - ipb_auto bool default 0, - ipb_anon_only bool default 0, - ipb_create_account bool default 1, - ipb_enable_autoblock bool default '1', - ipb_expiry varBLOB default '', - ipb_range_start tinyblob , - ipb_range_end tinyblob , - ipb_deleted bool default 0, - ipb_block_email bool default 0) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/image ( - img_name varchar(255) default '', - img_size INTEGER default '0', - img_width INTEGER default '0', - img_height INTEGER default '0', - img_metadata mediumblob , - img_bits INTEGER default '0', - img_media_type TEXT default NULL, - img_major_mime TEXT default "unknown", - img_minor_mime varBLOB default "unknown", - img_description tinyblob , - img_user INTEGER default '0', - img_user_text varchar(255) , - img_timestamp varBLOB default '', - img_sha1 varBLOB default '') /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/oldimage ( - oi_name varchar(255) default '', - oi_archive_name varchar(255) default '', - oi_size INTEGER default 0, - oi_width INTEGER default 0, - oi_height INTEGER default 0, - oi_bits INTEGER default 0, - oi_description tinyblob , - oi_user INTEGER default '0', - oi_user_text varchar(255) , - oi_timestamp BLOB default '', - oi_metadata mediumblob , - oi_media_type TEXT default NULL, - oi_major_mime TEXT default "unknown", - oi_minor_mime varBLOB default "unknown", - oi_deleted tinyint default '0', - oi_sha1 varBLOB default '') /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/filearchive ( - fa_id INTEGER PRIMARY KEY AUTOINCREMENT, - fa_name varchar(255) default '', - fa_archive_name varchar(255) default '', - fa_storage_group varBLOB, - fa_storage_key varBLOB default '', - fa_deleted_user int, - fa_deleted_timestamp BLOB default '', - fa_deleted_reason text, - fa_size INTEGER default '0', - fa_width INTEGER default '0', - fa_height INTEGER default '0', - fa_metadata mediumblob, - fa_bits INTEGER default '0', - fa_media_type TEXT default NULL, - fa_major_mime TEXT default "unknown", - fa_minor_mime varBLOB default "unknown", - fa_description tinyblob, - fa_user INTEGER default '0', - fa_user_text varchar(255) , - fa_timestamp BLOB default '', - fa_deleted tinyint default '0') /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/recentchanges ( - rc_id INTEGER PRIMARY KEY AUTOINCREMENT, - rc_timestamp varBLOB default '', - rc_cur_time varBLOB default '', - rc_user INTEGER default '0', - rc_user_text varchar(255) , - rc_namespace INTEGER default '0', - rc_title varchar(255) default '', - rc_comment varchar(255) default '', - rc_minor tinyint default '0', - rc_bot tinyint default '0', - rc_new tinyint default '0', - rc_cur_id INTEGER default '0', - rc_this_oldid INTEGER default '0', - rc_last_oldid INTEGER default '0', - rc_type tinyint default '0', - rc_moved_to_ns tinyint default '0', - rc_moved_to_title varchar(255) default '', - rc_patrolled tinyint default '0', - rc_ip varBLOB default '', - rc_old_len int, - rc_new_len int, - rc_deleted tinyint default '0', - rc_logid INTEGER default '0', - rc_log_type varBLOB NULL default NULL, - rc_log_action varBLOB NULL default NULL, - rc_params blob NULL) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/watchlist ( - wl_user INTEGER , - wl_namespace INTEGER default '0', - wl_title varchar(255) default '', - wl_notificationtimestamp varBLOB) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/math ( - math_inputhash varBLOB , - math_outputhash varBLOB , - math_html_conservativeness tinyint , - math_html text, - math_mathml text) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/searchindex ( - si_page INTEGER , - si_title varchar(255) default '', - si_text mediumtext ) ; - -CREATE TABLE /*$wgDBprefix*/interwiki ( - iw_prefix varchar(32) , - iw_url blob , - iw_local bool , - iw_trans tinyint default 0) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/querycache ( - qc_type varBLOB , - qc_value INTEGER default '0', - qc_namespace INTEGER default '0', - qc_title varchar(255) default '') /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/objectcache ( - keyname varBLOB default '', - value mediumblob, - exptime datetime) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/transcache ( - tc_url varBLOB , - tc_contents text, - tc_time INTEGER ) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/logging ( - log_id INTEGER PRIMARY KEY AUTOINCREMENT, - log_type varBLOB default '', - log_action varBLOB default '', - log_timestamp BLOB default '19700101000000', - log_user INTEGER default 0, - log_namespace INTEGER default 0, - log_title varchar(255) default '', - log_comment varchar(255) default '', - log_params blob , - log_deleted tinyint default '0') /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/trackbacks ( - tb_id INTEGER PRIMARY KEY AUTOINCREMENT, - tb_page INTEGER REFERENCES /*$wgDBprefix*/page(page_id) ON DELETE CASCADE, - tb_title varchar(255) , - tb_url blob , - tb_ex text, - tb_name varchar(255)) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/job ( - job_id INTEGER PRIMARY KEY AUTOINCREMENT, - job_cmd varBLOB default '', - job_namespace INTEGER , - job_title varchar(255) , - job_params blob ) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/querycache_info ( - qci_type varBLOB default '', - qci_timestamp BLOB default '19700101000000') /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/redirect ( - rd_from INTEGER default '0', - rd_namespace INTEGER default '0', - rd_title varchar(255) default '') /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/querycachetwo ( - qcc_type varBLOB , - qcc_value INTEGER default '0', - qcc_namespace INTEGER default '0', - qcc_title varchar(255) default '', - qcc_namespacetwo INTEGER default '0', - qcc_titletwo varchar(255) default '') /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/page_restrictions ( - pr_page INTEGER , - pr_type varBLOB , - pr_level varBLOB , - pr_cascade tinyint , - pr_user INTEGER NULL, - pr_expiry varBLOB NULL, - pr_id INTEGER PRIMARY KEY AUTOINCREMENT) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/protected_titles ( - pt_namespace INTEGER , - pt_title varchar(255) , - pt_user INTEGER , - pt_reason tinyblob, - pt_timestamp BLOB , - pt_expiry varBLOB default '', - pt_create_perm varBLOB ) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/page_props ( - pp_page INTEGER , - pp_propname varBLOB , - pp_value blob ) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/updatelog ( - ul_key varchar(255) ) /*$wgDBTableOptions*/; - - diff --git a/maintenance/storage/blobs.sql b/maintenance/storage/blobs.sql index 0b1b82d8..623dd7bf 100644 --- a/maintenance/storage/blobs.sql +++ b/maintenance/storage/blobs.sql @@ -4,5 +4,5 @@ CREATE TABLE /*$wgDBprefix*/blobs ( blob_id integer UNSIGNED NOT NULL AUTO_INCREMENT, blob_text longblob, PRIMARY KEY (blob_id) -) ENGINE=MyISAM MAX_ROWS=1000000 AVG_ROW_LENGTH=1000000; +) ENGINE=MyISAM MAX_ROWS=100000000 AVG_ROW_LENGTH=100000; diff --git a/maintenance/storage/recompressTracked.php b/maintenance/storage/recompressTracked.php index 7e4ed1b4..d8d2e4ef 100644 --- a/maintenance/storage/recompressTracked.php +++ b/maintenance/storage/recompressTracked.php @@ -333,7 +333,6 @@ class RecompressTracked { } else { $this->info( "Moving orphans..." ); } - $ids = array(); while ( true ) { $res = $dbr->select( 'blob_tracking', @@ -353,6 +352,7 @@ class RecompressTracked { if ( !$res->numRows() ) { break; } + $ids = array(); foreach ( $res as $row ) { $ids[] = $row->bt_text_id; $i++; @@ -366,6 +366,12 @@ class RecompressTracked { array_unshift( $args, 'doOrphanList' ); call_user_func_array( array( $this, 'dispatch' ), $args ); } + if ( count( $ids ) ) { + $args = $ids; + array_unshift( $args, 'doOrphanList' ); + call_user_func_array( array( $this, 'dispatch' ), $args ); + } + $startId = $row->bt_text_id; $this->report( 'orphans', $i, $numOrphans ); } diff --git a/maintenance/storage/trackBlobs.php b/maintenance/storage/trackBlobs.php index b13faa00..0f25fb94 100644 --- a/maintenance/storage/trackBlobs.php +++ b/maintenance/storage/trackBlobs.php @@ -11,7 +11,7 @@ if ( count( $args ) < 1 ) { exit( 1 ); } $tracker = new TrackBlobs( $args ); -$tracker->trackBlobs(); +$tracker->run(); class TrackBlobs { var $clusters, $textClause; @@ -33,7 +33,7 @@ class TrackBlobs { } } - function trackBlobs() { + function run() { $this->initTrackingTable(); $this->trackRevisions(); $this->trackOrphanText(); @@ -259,14 +259,18 @@ class TrackBlobs { } continue; } + $table = $extDB->getLBInfo( 'blobs table' ); + if ( is_null( $table ) ) { + $table = 'blobs'; + } $startId = 0; $batchesDone = 0; $actualBlobs = gmp_init( 0 ); - $endId = $extDB->selectField( 'blobs', 'MAX(blob_id)', false, __METHOD__ ); + $endId = $extDB->selectField( $table, 'MAX(blob_id)', false, __METHOD__ ); // Build a bitmap of actual blob rows while ( true ) { - $res = $extDB->select( 'blobs', + $res = $extDB->select( $table, array( 'blob_id' ), array( 'blob_id > ' . $extDB->addQuotes( $startId ) ), __METHOD__, diff --git a/maintenance/tables.sql b/maintenance/tables.sql index 28f496eb..3b1e8eb7 100644 --- a/maintenance/tables.sql +++ b/maintenance/tables.sql @@ -2,6 +2,8 @@ -- This is read and executed by the install script; you should -- not have to run it by itself unless doing a manual install. +-- This is a shared schema file used for both MySQL and SQLite installs. + -- -- General notes: -- @@ -28,7 +30,7 @@ -- well. -- -- --- The /*$wgDBprefix*/ comments in this and other files are +-- The /*_*/ comments in this and other files are -- replaced with the defined table prefix by the installer -- and updater scripts. If you are installing or running -- updates manually, you will need to manually insert the @@ -48,8 +50,8 @@ -- preferences and to key tracking information in the other -- tables. -- -CREATE TABLE /*$wgDBprefix*/user ( - user_id int unsigned NOT NULL auto_increment, +CREATE TABLE /*_*/user ( + user_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT, -- Usernames must be unique, must not be in the form of -- an IP address. _Shouldn't_ allow slashes or case @@ -124,13 +126,12 @@ CREATE TABLE /*$wgDBprefix*/user ( -- Meant primarily for heuristic checks to give an impression of whether -- the account has been used much. -- - user_editcount int, + user_editcount int +) /*$wgDBTableOptions*/; - PRIMARY KEY user_id (user_id), - UNIQUE INDEX user_name (user_name), - INDEX (user_email_token) +CREATE UNIQUE INDEX /*i*/user_name ON /*_*/user (user_name); +CREATE INDEX /*i*/user_email_token ON /*_*/user (user_email_token); -) /*$wgDBTableOptions*/; -- -- User permissions have been broken out to a separate table; @@ -140,9 +141,9 @@ CREATE TABLE /*$wgDBprefix*/user ( -- This table replaces the old user_rights field which used a -- comma-separated blob. -- -CREATE TABLE /*$wgDBprefix*/user_groups ( +CREATE TABLE /*_*/user_groups ( -- Key to user_id - ug_user int unsigned NOT NULL default '0', + ug_user int unsigned NOT NULL default 0, -- Group names are short symbolic string keys. -- The set of group names is open-ended, though in practice @@ -152,37 +153,39 @@ CREATE TABLE /*$wgDBprefix*/user_groups ( -- with particular permissions. A user will have the combined -- permissions of any group they're explicitly in, plus -- the implicit '*' and 'user' groups. - ug_group varbinary(16) NOT NULL default '', - - PRIMARY KEY (ug_user,ug_group), - KEY (ug_group) + ug_group varbinary(16) NOT NULL default '' ) /*$wgDBTableOptions*/; +CREATE UNIQUE INDEX /*i*/ug_user_group ON /*_*/user_groups (ug_user,ug_group); +CREATE INDEX /*i*/ug_group ON /*_*/user_groups (ug_group); + + -- Stores notifications of user talk page changes, for the display -- of the "you have new messages" box -CREATE TABLE /*$wgDBprefix*/user_newtalk ( +CREATE TABLE /*_*/user_newtalk ( -- Key to user.user_id - user_id int NOT NULL default '0', + user_id int NOT NULL default 0, -- If the user is an anonymous user their IP address is stored here -- since the user_id of 0 is ambiguous user_ip varbinary(40) NOT NULL default '', -- The highest timestamp of revisions of the talk page viewed -- by this user - user_last_timestamp binary(14) NOT NULL default '', - INDEX user_id (user_id), - INDEX user_ip (user_ip) - + user_last_timestamp binary(14) NOT NULL default '' ) /*$wgDBTableOptions*/; +-- Indexes renamed for SQLite in 1.14 +CREATE INDEX /*i*/un_user_id ON /*_*/user_newtalk (user_id); +CREATE INDEX /*i*/un_user_ip ON /*_*/user_newtalk (user_ip); + -- -- Core of the wiki: each page has an entry here which identifies -- it by title and contains some essential metadata. -- -CREATE TABLE /*$wgDBprefix*/page ( +CREATE TABLE /*_*/page ( -- Unique identifier number. The page_id will be preserved across -- edits and rename operations, but not deletions and recreations. - page_id int unsigned NOT NULL auto_increment, + page_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT, -- A page name is broken into a namespace and a title. -- The namespace keys are UI-language-independent constants, @@ -198,14 +201,14 @@ CREATE TABLE /*$wgDBprefix*/page ( page_restrictions tinyblob NOT NULL, -- Number of times this page has been viewed. - page_counter bigint unsigned NOT NULL default '0', + page_counter bigint unsigned NOT NULL default 0, -- 1 indicates the article is a redirect. - page_is_redirect tinyint unsigned NOT NULL default '0', + page_is_redirect tinyint unsigned NOT NULL default 0, -- 1 indicates this is a new entry, with only one edit. -- Not all pages with one edit are new pages. - page_is_new tinyint unsigned NOT NULL default '0', + page_is_new tinyint unsigned NOT NULL default 0, -- Random value between 0 and 1, used for Special:Randompage page_random real unsigned NOT NULL, @@ -223,24 +226,21 @@ CREATE TABLE /*$wgDBprefix*/page ( page_latest int unsigned NOT NULL, -- Uncompressed length in bytes of the page's current source text. - page_len int unsigned NOT NULL, + page_len int unsigned NOT NULL +) /*$wgDBTableOptions*/; - PRIMARY KEY page_id (page_id), - UNIQUE INDEX name_title (page_namespace,page_title), - - -- Special-purpose indexes - INDEX (page_random), - INDEX (page_len) +CREATE UNIQUE INDEX /*i*/name_title ON /*_*/page (page_namespace,page_title); +CREATE INDEX /*i*/page_random ON /*_*/page (page_random); +CREATE INDEX /*i*/page_len ON /*_*/page (page_len); -) /*$wgDBTableOptions*/; -- -- Every edit of a page creates also a revision row. -- This stores metadata about the revision, and a reference -- to the text storage backend. -- -CREATE TABLE /*$wgDBprefix*/revision ( - rev_id int unsigned NOT NULL auto_increment, +CREATE TABLE /*_*/revision ( + rev_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT, -- Key to page_id. This should _never_ be invalid. rev_page int unsigned NOT NULL, @@ -258,7 +258,7 @@ CREATE TABLE /*$wgDBprefix*/revision ( -- Key to user.user_id of the user who made this edit. -- Stores 0 for anonymous edits and for some mass imports. - rev_user int unsigned NOT NULL default '0', + rev_user int unsigned NOT NULL default 0, -- Text username or IP address of the editor. rev_user_text varchar(255) binary NOT NULL default '', @@ -268,28 +268,27 @@ CREATE TABLE /*$wgDBprefix*/revision ( -- Records whether the user marked the 'minor edit' checkbox. -- Many automated edits are marked as minor. - rev_minor_edit tinyint unsigned NOT NULL default '0', + rev_minor_edit tinyint unsigned NOT NULL default 0, -- Not yet used; reserved for future changes to the deletion system. - rev_deleted tinyint unsigned NOT NULL default '0', + rev_deleted tinyint unsigned NOT NULL default 0, -- Length of this revision in bytes rev_len int unsigned, -- Key to revision.rev_id -- This field is used to add support for a tree structure (The Adjacency List Model) - rev_parent_id int unsigned default NULL, - - PRIMARY KEY rev_page_id (rev_page, rev_id), - UNIQUE INDEX rev_id (rev_id), - INDEX rev_timestamp (rev_timestamp), - INDEX page_timestamp (rev_page,rev_timestamp), - INDEX user_timestamp (rev_user,rev_timestamp), - INDEX usertext_timestamp (rev_user_text,rev_timestamp) + rev_parent_id int unsigned default NULL ) /*$wgDBTableOptions*/ MAX_ROWS=10000000 AVG_ROW_LENGTH=1024; -- In case tables are created as MyISAM, use row hints for MySQL <5.0 to avoid 4GB limit +CREATE UNIQUE INDEX /*i*/rev_page_id ON /*_*/revision (rev_page, rev_id); +CREATE INDEX /*i*/rev_timestamp ON /*_*/revision (rev_timestamp); +CREATE INDEX /*i*/page_timestamp ON /*_*/revision (rev_page,rev_timestamp); +CREATE INDEX /*i*/user_timestamp ON /*_*/revision (rev_user,rev_timestamp); +CREATE INDEX /*i*/usertext_timestamp ON /*_*/revision (rev_user_text,rev_timestamp); + -- -- Holds text of individual page revisions. -- @@ -298,13 +297,13 @@ CREATE TABLE /*$wgDBprefix*/revision ( -- table into the 'text' table to minimize unnecessary churning -- and downtime. If upgrading, the other fields will be left unused. -- -CREATE TABLE /*$wgDBprefix*/text ( +CREATE TABLE /*_*/text ( -- Unique text storage key number. -- Note that the 'oldid' parameter used in URLs does *not* -- refer to this number anymore, but to rev_id. -- -- revision.rev_text_id is a key to this column - old_id int unsigned NOT NULL auto_increment, + old_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT, -- Depending on the contents of the old_flags field, the text -- may be convenient plain text, or it may be funkily encoded. @@ -319,21 +318,19 @@ CREATE TABLE /*$wgDBprefix*/text ( -- The object either contains multiple versions compressed -- together to achieve a better compression ratio, or it refers -- to another row where the text can be found. - old_flags tinyblob NOT NULL, - - PRIMARY KEY old_id (old_id) - + old_flags tinyblob NOT NULL ) /*$wgDBTableOptions*/ MAX_ROWS=10000000 AVG_ROW_LENGTH=10240; -- In case tables are created as MyISAM, use row hints for MySQL <5.0 to avoid 4GB limit + -- -- Holding area for deleted articles, which may be viewed -- or restored by admins through the Special:Undelete interface. -- The fields generally correspond to the page, revision, and text -- fields, with several caveats. -- -CREATE TABLE /*$wgDBprefix*/archive ( - ar_namespace int NOT NULL default '0', +CREATE TABLE /*_*/archive ( + ar_namespace int NOT NULL default 0, ar_title varchar(255) binary NOT NULL default '', -- Newly deleted pages will not store text in this table, @@ -346,10 +343,10 @@ CREATE TABLE /*$wgDBprefix*/archive ( -- Basic revision stuff... ar_comment tinyblob NOT NULL, - ar_user int unsigned NOT NULL default '0', + ar_user int unsigned NOT NULL default 0, ar_user_text varchar(255) binary NOT NULL, ar_timestamp binary(14) NOT NULL default '', - ar_minor_edit tinyint NOT NULL default '0', + ar_minor_edit tinyint NOT NULL default 0, -- See ar_text note. ar_flags tinyblob NOT NULL, @@ -375,7 +372,7 @@ CREATE TABLE /*$wgDBprefix*/archive ( ar_text_id int unsigned, -- rev_deleted for archives - ar_deleted tinyint unsigned NOT NULL default '0', + ar_deleted tinyint unsigned NOT NULL default 0, -- Length of this revision in bytes ar_len int unsigned, @@ -388,80 +385,77 @@ CREATE TABLE /*$wgDBprefix*/archive ( ar_page_id int unsigned, -- Original previous revision - ar_parent_id int unsigned default NULL, - - KEY name_title_timestamp (ar_namespace,ar_title,ar_timestamp), - KEY usertext_timestamp (ar_user_text,ar_timestamp) - + ar_parent_id int unsigned default NULL ) /*$wgDBTableOptions*/; +CREATE INDEX /*i*/name_title_timestamp ON /*_*/archive (ar_namespace,ar_title,ar_timestamp); +CREATE INDEX /*i*/ar_usertext_timestamp ON /*_*/archive (ar_user_text,ar_timestamp); + -- -- Track page-to-page hyperlinks within the wiki. -- -CREATE TABLE /*$wgDBprefix*/pagelinks ( +CREATE TABLE /*_*/pagelinks ( -- Key to the page_id of the page containing the link. - pl_from int unsigned NOT NULL default '0', + pl_from int unsigned NOT NULL default 0, -- Key to page_namespace/page_title of the target page. -- The target page may or may not exist, and due to renames -- and deletions may refer to different page records as time -- goes by. - pl_namespace int NOT NULL default '0', - pl_title varchar(255) binary NOT NULL default '', - - UNIQUE KEY pl_from (pl_from,pl_namespace,pl_title), - KEY (pl_namespace,pl_title,pl_from) - + pl_namespace int NOT NULL default 0, + pl_title varchar(255) binary NOT NULL default '' ) /*$wgDBTableOptions*/; +CREATE UNIQUE INDEX /*i*/pl_from ON /*_*/pagelinks (pl_from,pl_namespace,pl_title); +CREATE UNIQUE INDEX /*i*/pl_namespace ON /*_*/pagelinks (pl_namespace,pl_title,pl_from); + -- -- Track template inclusions. -- -CREATE TABLE /*$wgDBprefix*/templatelinks ( +CREATE TABLE /*_*/templatelinks ( -- Key to the page_id of the page containing the link. - tl_from int unsigned NOT NULL default '0', + tl_from int unsigned NOT NULL default 0, -- Key to page_namespace/page_title of the target page. -- The target page may or may not exist, and due to renames -- and deletions may refer to different page records as time -- goes by. - tl_namespace int NOT NULL default '0', - tl_title varchar(255) binary NOT NULL default '', - - UNIQUE KEY tl_from (tl_from,tl_namespace,tl_title), - KEY (tl_namespace,tl_title,tl_from) - + tl_namespace int NOT NULL default 0, + tl_title varchar(255) binary NOT NULL default '' ) /*$wgDBTableOptions*/; +CREATE UNIQUE INDEX /*i*/tl_from ON /*_*/templatelinks (tl_from,tl_namespace,tl_title); +CREATE UNIQUE INDEX /*i*/tl_namespace ON /*_*/templatelinks (tl_namespace,tl_title,tl_from); + + -- -- Track links to images *used inline* -- We don't distinguish live from broken links here, so -- they do not need to be changed on upload/removal. -- -CREATE TABLE /*$wgDBprefix*/imagelinks ( +CREATE TABLE /*_*/imagelinks ( -- Key to page_id of the page containing the image / media link. - il_from int unsigned NOT NULL default '0', + il_from int unsigned NOT NULL default 0, -- Filename of target image. -- This is also the page_title of the file's description page; -- all such pages are in namespace 6 (NS_FILE). - il_to varchar(255) binary NOT NULL default '', - - UNIQUE KEY il_from (il_from,il_to), - KEY (il_to,il_from) - + il_to varchar(255) binary NOT NULL default '' ) /*$wgDBTableOptions*/; +CREATE UNIQUE INDEX /*i*/il_from ON /*_*/imagelinks (il_from,il_to); +CREATE UNIQUE INDEX /*i*/il_to ON /*_*/imagelinks (il_to,il_from); + + -- -- Track category inclusions *used inline* -- This tracks a single level of category membership --- (folksonomic tagging, really). -- -CREATE TABLE /*$wgDBprefix*/categorylinks ( +CREATE TABLE /*_*/categorylinks ( -- Key to page_id of the page defined as a category member. - cl_from int unsigned NOT NULL default '0', + cl_from int unsigned NOT NULL default 0, -- Name of the category. -- This is also the page_title of the category's description page; @@ -480,26 +474,26 @@ CREATE TABLE /*$wgDBprefix*/categorylinks ( -- This isn't really used at present. Provided for an optional -- sorting method by approximate addition time. - cl_timestamp timestamp NOT NULL, - - UNIQUE KEY cl_from (cl_from,cl_to), - - -- We always sort within a given category... - KEY cl_sortkey (cl_to,cl_sortkey,cl_from), - - -- Not really used? - KEY cl_timestamp (cl_to,cl_timestamp) - + cl_timestamp timestamp NOT NULL ) /*$wgDBTableOptions*/; +CREATE UNIQUE INDEX /*i*/cl_from ON /*_*/categorylinks (cl_from,cl_to); + +-- We always sort within a given category... +CREATE INDEX /*i*/cl_sortkey ON /*_*/categorylinks (cl_to,cl_sortkey,cl_from); + +-- Not really used? +CREATE INDEX /*i*/cl_timestamp ON /*_*/categorylinks (cl_to,cl_timestamp); + + -- -- Track all existing categories. Something is a category if 1) it has an en- -- try somewhere in categorylinks, or 2) it once did. Categories might not -- have corresponding pages, so they need to be tracked separately. -- -CREATE TABLE /*$wgDBprefix*/category ( +CREATE TABLE /*_*/category ( -- Primary key - cat_id int unsigned NOT NULL auto_increment, + cat_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT, -- Name of the category, in the same form as page_title (with underscores). -- If there is a category page corresponding to this category, by definition, @@ -516,21 +510,21 @@ CREATE TABLE /*$wgDBprefix*/category ( cat_files int signed NOT NULL default 0, -- Reserved for future use - cat_hidden tinyint unsigned NOT NULL default 0, - - PRIMARY KEY (cat_id), - UNIQUE KEY (cat_title), - - -- For Special:Mostlinkedcategories - KEY (cat_pages) + cat_hidden tinyint unsigned NOT NULL default 0 ) /*$wgDBTableOptions*/; +CREATE UNIQUE INDEX /*i*/cat_title ON /*_*/category (cat_title); + +-- For Special:Mostlinkedcategories +CREATE INDEX /*i*/cat_pages ON /*_*/category (cat_pages); + + -- -- Track links to external URLs -- -CREATE TABLE /*$wgDBprefix*/externallinks ( +CREATE TABLE /*_*/externallinks ( -- page_id of the referring page - el_from int unsigned NOT NULL default '0', + el_from int unsigned NOT NULL default 0, -- The URL el_to blob NOT NULL, @@ -546,50 +540,52 @@ CREATE TABLE /*$wgDBprefix*/externallinks ( -- which allows for fast searching for all pages under example.com with the -- clause: -- WHERE el_index LIKE 'http://com.example.%' - el_index blob NOT NULL, - - KEY (el_from, el_to(40)), - KEY (el_to(60), el_from), - KEY (el_index(60)) + el_index blob NOT NULL ) /*$wgDBTableOptions*/; +CREATE INDEX /*i*/el_from ON /*_*/externallinks (el_from, el_to(40)); +CREATE INDEX /*i*/el_to ON /*_*/externallinks (el_to(60), el_from); +CREATE INDEX /*i*/el_index ON /*_*/externallinks (el_index(60)); + + -- -- Track interlanguage links -- -CREATE TABLE /*$wgDBprefix*/langlinks ( +CREATE TABLE /*_*/langlinks ( -- page_id of the referring page - ll_from int unsigned NOT NULL default '0', + ll_from int unsigned NOT NULL default 0, -- Language code of the target ll_lang varbinary(20) NOT NULL default '', -- Title of the target, including namespace - ll_title varchar(255) binary NOT NULL default '', - - UNIQUE KEY (ll_from, ll_lang), - KEY (ll_lang, ll_title) + ll_title varchar(255) binary NOT NULL default '' ) /*$wgDBTableOptions*/; +CREATE UNIQUE INDEX /*i*/ll_from ON /*_*/langlinks (ll_from, ll_lang); +CREATE INDEX /*i*/ll_lang ON /*_*/langlinks (ll_lang, ll_title); + + -- -- Contains a single row with some aggregate info -- on the state of the site. -- -CREATE TABLE /*$wgDBprefix*/site_stats ( +CREATE TABLE /*_*/site_stats ( -- The single row should contain 1 here. ss_row_id int unsigned NOT NULL, -- Total number of page views, if hit counters are enabled. - ss_total_views bigint unsigned default '0', + ss_total_views bigint unsigned default 0, -- Total number of edits performed. - ss_total_edits bigint unsigned default '0', + ss_total_edits bigint unsigned default 0, -- An approximate count of pages matching the following criteria: -- * in namespace 0 -- * not a redirect -- * contains the text '[[' -- See Article::isCountable() in includes/Article.php - ss_good_articles bigint unsigned default '0', + ss_good_articles bigint unsigned default 0, -- Total pages, theoretically equal to SELECT COUNT(*) FROM page; except faster ss_total_pages bigint default '-1', @@ -604,20 +600,21 @@ CREATE TABLE /*$wgDBprefix*/site_stats ( ss_admins int default '-1', -- Number of images, equivalent to SELECT COUNT(*) FROM image - ss_images int default '0', + ss_images int default 0 +) /*$wgDBTableOptions*/; - UNIQUE KEY ss_row_id (ss_row_id) +-- Pointless index to assuage developer superstitions +CREATE UNIQUE INDEX /*i*/ss_row_id ON /*_*/site_stats (ss_row_id); -) /*$wgDBTableOptions*/; -- -- Stores an ID for every time any article is visited; -- depending on $wgHitcounterUpdateFreq, it is -- periodically cleared and the page_counter column --- in the page table updated for the all articles +-- in the page table updated for all the articles -- that have been visited.) -- -CREATE TABLE /*$wgDBprefix*/hitcounter ( +CREATE TABLE /*_*/hitcounter ( hc_id int unsigned NOT NULL ) ENGINE=HEAP MAX_ROWS=25000; @@ -626,18 +623,18 @@ CREATE TABLE /*$wgDBprefix*/hitcounter ( -- The internet is full of jerks, alas. Sometimes it's handy -- to block a vandal or troll account. -- -CREATE TABLE /*$wgDBprefix*/ipblocks ( +CREATE TABLE /*_*/ipblocks ( -- Primary key, introduced for privacy. - ipb_id int NOT NULL auto_increment, + ipb_id int NOT NULL PRIMARY KEY AUTO_INCREMENT, -- Blocked IP address in dotted-quad form or user name. ipb_address tinyblob NOT NULL, -- Blocked user ID or 0 for IP blocks. - ipb_user int unsigned NOT NULL default '0', + ipb_user int unsigned NOT NULL default 0, -- User ID who made the block. - ipb_by int unsigned NOT NULL default '0', + ipb_by int unsigned NOT NULL default 0, -- User name of blocker ipb_by_text varchar(255) binary NOT NULL default '', @@ -679,43 +676,41 @@ CREATE TABLE /*$wgDBprefix*/ipblocks ( ipb_block_email bool NOT NULL default 0, -- Block allows user to edit their own talk page - ipb_allow_usertalk bool NOT NULL default 0, - - PRIMARY KEY ipb_id (ipb_id), - - -- Unique index to support "user already blocked" messages - -- Any new options which prevent collisions should be included - UNIQUE INDEX ipb_address (ipb_address(255), ipb_user, ipb_auto, ipb_anon_only), - - INDEX ipb_user (ipb_user), - INDEX ipb_range (ipb_range_start(8), ipb_range_end(8)), - INDEX ipb_timestamp (ipb_timestamp), - INDEX ipb_expiry (ipb_expiry) + ipb_allow_usertalk bool NOT NULL default 0 ) /*$wgDBTableOptions*/; + +-- Unique index to support "user already blocked" messages +-- Any new options which prevent collisions should be included +CREATE UNIQUE INDEX /*i*/ipb_address ON /*_*/ipblocks (ipb_address(255), ipb_user, ipb_auto, ipb_anon_only); + +CREATE INDEX /*i*/ipb_user ON /*_*/ipblocks (ipb_user); +CREATE INDEX /*i*/ipb_range ON /*_*/ipblocks (ipb_range_start(8), ipb_range_end(8)); +CREATE INDEX /*i*/ipb_timestamp ON /*_*/ipblocks (ipb_timestamp); +CREATE INDEX /*i*/ipb_expiry ON /*_*/ipblocks (ipb_expiry); -- -- Uploaded images and other files. -- -CREATE TABLE /*$wgDBprefix*/image ( +CREATE TABLE /*_*/image ( -- Filename. -- This is also the title of the associated description page, -- which will be in namespace 6 (NS_FILE). - img_name varchar(255) binary NOT NULL default '', + img_name varchar(255) binary NOT NULL default '' PRIMARY KEY, -- File size in bytes. - img_size int unsigned NOT NULL default '0', + img_size int unsigned NOT NULL default 0, -- For images, size in pixels. - img_width int NOT NULL default '0', - img_height int NOT NULL default '0', + img_width int NOT NULL default 0, + img_height int NOT NULL default 0, -- Extracted EXIF metadata stored as a serialized PHP array. img_metadata mediumblob NOT NULL, -- For images, bits per pixel if known. - img_bits int NOT NULL default '0', + img_bits int NOT NULL default 0, -- Media type as defined by the MEDIATYPE_xxx constants img_media_type ENUM("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE") default NULL, @@ -735,34 +730,31 @@ CREATE TABLE /*$wgDBprefix*/image ( img_description tinyblob NOT NULL, -- user_id and user_name of uploader. - img_user int unsigned NOT NULL default '0', + img_user int unsigned NOT NULL default 0, img_user_text varchar(255) binary NOT NULL, -- Time of the upload. img_timestamp varbinary(14) NOT NULL default '', -- SHA-1 content hash in base-36 - img_sha1 varbinary(32) NOT NULL default '', - - PRIMARY KEY img_name (img_name), - - INDEX img_usertext_timestamp (img_user_text,img_timestamp), - -- Used by Special:Imagelist for sort-by-size - INDEX img_size (img_size), - -- Used by Special:Newimages and Special:Imagelist - INDEX img_timestamp (img_timestamp), - -- Used in API and duplicate search - INDEX img_sha1 (img_sha1) + img_sha1 varbinary(32) NOT NULL default '' +) /*$wgDBTableOptions*/; +CREATE INDEX /*i*/img_usertext_timestamp ON /*_*/image (img_user_text,img_timestamp); +-- Used by Special:Imagelist for sort-by-size +CREATE INDEX /*i*/img_size ON /*_*/image (img_size); +-- Used by Special:Newimages and Special:Imagelist +CREATE INDEX /*i*/img_timestamp ON /*_*/image (img_timestamp); +-- Used in API and duplicate search +CREATE INDEX /*i*/img_sha1 ON /*_*/image (img_sha1); -) /*$wgDBTableOptions*/; -- -- Previous revisions of uploaded files. -- Awkwardly, image rows have to be moved into -- this table at re-upload time. -- -CREATE TABLE /*$wgDBprefix*/oldimage ( +CREATE TABLE /*_*/oldimage ( -- Base filename: key to image.img_name oi_name varchar(255) binary NOT NULL default '', @@ -776,7 +768,7 @@ CREATE TABLE /*$wgDBprefix*/oldimage ( oi_height int NOT NULL default 0, oi_bits int NOT NULL default 0, oi_description tinyblob NOT NULL, - oi_user int unsigned NOT NULL default '0', + oi_user int unsigned NOT NULL default 0, oi_user_text varchar(255) binary NOT NULL, oi_timestamp binary(14) NOT NULL default '', @@ -784,23 +776,23 @@ CREATE TABLE /*$wgDBprefix*/oldimage ( oi_media_type ENUM("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE") default NULL, oi_major_mime ENUM("unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart") NOT NULL default "unknown", oi_minor_mime varbinary(32) NOT NULL default "unknown", - oi_deleted tinyint unsigned NOT NULL default '0', - oi_sha1 varbinary(32) NOT NULL default '', - - INDEX oi_usertext_timestamp (oi_user_text,oi_timestamp), - INDEX oi_name_timestamp (oi_name,oi_timestamp), - -- oi_archive_name truncated to 14 to avoid key length overflow - INDEX oi_name_archive_name (oi_name,oi_archive_name(14)), - INDEX oi_sha1 (oi_sha1) - + oi_deleted tinyint unsigned NOT NULL default 0, + oi_sha1 varbinary(32) NOT NULL default '' ) /*$wgDBTableOptions*/; +CREATE INDEX /*i*/oi_usertext_timestamp ON /*_*/oldimage (oi_user_text,oi_timestamp); +CREATE INDEX /*i*/oi_name_timestamp ON /*_*/oldimage (oi_name,oi_timestamp); +-- oi_archive_name truncated to 14 to avoid key length overflow +CREATE INDEX /*i*/oi_name_archive_name ON /*_*/oldimage (oi_name,oi_archive_name(14)); +CREATE INDEX /*i*/oi_sha1 ON /*_*/oldimage (oi_sha1); + + -- -- Record of deleted file data -- -CREATE TABLE /*$wgDBprefix*/filearchive ( +CREATE TABLE /*_*/filearchive ( -- Unique row id - fa_id int NOT NULL auto_increment, + fa_id int NOT NULL PRIMARY KEY AUTO_INCREMENT, -- Original base filename; key to image.img_name, page.page_title, etc fa_name varchar(255) binary NOT NULL default '', @@ -826,80 +818,83 @@ CREATE TABLE /*$wgDBprefix*/filearchive ( fa_deleted_reason text, -- Duped fields from image - fa_size int unsigned default '0', - fa_width int default '0', - fa_height int default '0', + fa_size int unsigned default 0, + fa_width int default 0, + fa_height int default 0, fa_metadata mediumblob, - fa_bits int default '0', + fa_bits int default 0, fa_media_type ENUM("UNKNOWN", "BITMAP", "DRAWING", "AUDIO", "VIDEO", "MULTIMEDIA", "OFFICE", "TEXT", "EXECUTABLE", "ARCHIVE") default NULL, fa_major_mime ENUM("unknown", "application", "audio", "image", "text", "video", "message", "model", "multipart") default "unknown", fa_minor_mime varbinary(32) default "unknown", fa_description tinyblob, - fa_user int unsigned default '0', + fa_user int unsigned default 0, fa_user_text varchar(255) binary, fa_timestamp binary(14) default '', -- Visibility of deleted revisions, bitfield - fa_deleted tinyint unsigned NOT NULL default '0', - - PRIMARY KEY (fa_id), - INDEX (fa_name, fa_timestamp), -- pick out by image name - INDEX (fa_storage_group, fa_storage_key), -- pick out dupe files - INDEX (fa_deleted_timestamp), -- sort by deletion time - INDEX fa_user_timestamp (fa_user_text,fa_timestamp) -- sort by uploader - + fa_deleted tinyint unsigned NOT NULL default 0 ) /*$wgDBTableOptions*/; +-- pick out by image name +CREATE INDEX /*i*/fa_name ON /*_*/filearchive (fa_name, fa_timestamp); +-- pick out dupe files +CREATE INDEX /*i*/fa_storage_group ON /*_*/filearchive (fa_storage_group, fa_storage_key); +-- sort by deletion time +CREATE INDEX /*i*/fa_deleted_timestamp ON /*_*/filearchive (fa_deleted_timestamp); +-- sort by uploader +CREATE INDEX /*i*/fa_user_timestamp ON /*_*/filearchive (fa_user_text,fa_timestamp); + + -- -- Primarily a summary table for Special:Recentchanges, -- this table contains some additional info on edits from -- the last few days, see Article::editUpdates() -- -CREATE TABLE /*$wgDBprefix*/recentchanges ( - rc_id int NOT NULL auto_increment, +CREATE TABLE /*_*/recentchanges ( + rc_id int NOT NULL PRIMARY KEY AUTO_INCREMENT, rc_timestamp varbinary(14) NOT NULL default '', rc_cur_time varbinary(14) NOT NULL default '', -- As in revision - rc_user int unsigned NOT NULL default '0', + rc_user int unsigned NOT NULL default 0, rc_user_text varchar(255) binary NOT NULL, -- When pages are renamed, their RC entries do _not_ change. - rc_namespace int NOT NULL default '0', + rc_namespace int NOT NULL default 0, rc_title varchar(255) binary NOT NULL default '', -- as in revision... rc_comment varchar(255) binary NOT NULL default '', - rc_minor tinyint unsigned NOT NULL default '0', + rc_minor tinyint unsigned NOT NULL default 0, -- Edits by user accounts with the 'bot' rights key are -- marked with a 1 here, and will be hidden from the -- default view. - rc_bot tinyint unsigned NOT NULL default '0', + rc_bot tinyint unsigned NOT NULL default 0, - rc_new tinyint unsigned NOT NULL default '0', + rc_new tinyint unsigned NOT NULL default 0, -- Key to page_id (was cur_id prior to 1.5). -- This will keep links working after moves while -- retaining the at-the-time name in the changes list. - rc_cur_id int unsigned NOT NULL default '0', + rc_cur_id int unsigned NOT NULL default 0, -- rev_id of the given revision - rc_this_oldid int unsigned NOT NULL default '0', + rc_this_oldid int unsigned NOT NULL default 0, -- rev_id of the prior revision, for generating diff links. - rc_last_oldid int unsigned NOT NULL default '0', + rc_last_oldid int unsigned NOT NULL default 0, -- These may no longer be used, with the new move log. - rc_type tinyint unsigned NOT NULL default '0', - rc_moved_to_ns tinyint unsigned NOT NULL default '0', + rc_type tinyint unsigned NOT NULL default 0, + rc_moved_to_ns tinyint unsigned NOT NULL default 0, rc_moved_to_title varchar(255) binary NOT NULL default '', -- If the Recent Changes Patrol option is enabled, -- users may mark edits as having been reviewed to -- remove a warning flag on the RC list. -- A value of 1 indicates the page has been reviewed. - rc_patrolled tinyint unsigned NOT NULL default '0', + rc_patrolled tinyint unsigned NOT NULL default 0, -- Recorded IP address the edit was made from, if the -- $wgPutIPinRC option is enabled. @@ -911,53 +906,52 @@ CREATE TABLE /*$wgDBprefix*/recentchanges ( rc_new_len int, -- Visibility of recent changes items, bitfield - rc_deleted tinyint unsigned NOT NULL default '0', + rc_deleted tinyint unsigned NOT NULL default 0, -- Value corresonding to log_id, specific log entries - rc_logid int unsigned NOT NULL default '0', + rc_logid int unsigned NOT NULL default 0, -- Store log type info here, or null rc_log_type varbinary(255) NULL default NULL, -- Store log action or null rc_log_action varbinary(255) NULL default NULL, -- Log params - rc_params blob NULL, - - PRIMARY KEY rc_id (rc_id), - INDEX rc_timestamp (rc_timestamp), - INDEX rc_namespace_title (rc_namespace, rc_title), - INDEX rc_cur_id (rc_cur_id), - INDEX new_name_timestamp (rc_new,rc_namespace,rc_timestamp), - INDEX rc_ip (rc_ip), - INDEX rc_ns_usertext (rc_namespace, rc_user_text), - INDEX rc_user_text (rc_user_text, rc_timestamp) - + rc_params blob NULL ) /*$wgDBTableOptions*/; -CREATE TABLE /*$wgDBprefix*/watchlist ( +CREATE INDEX /*i*/rc_timestamp ON /*_*/recentchanges (rc_timestamp); +CREATE INDEX /*i*/rc_namespace_title ON /*_*/recentchanges (rc_namespace, rc_title); +CREATE INDEX /*i*/rc_cur_id ON /*_*/recentchanges (rc_cur_id); +CREATE INDEX /*i*/new_name_timestamp ON /*_*/recentchanges (rc_new,rc_namespace,rc_timestamp); +CREATE INDEX /*i*/rc_ip ON /*_*/recentchanges (rc_ip); +CREATE INDEX /*i*/rc_ns_usertext ON /*_*/recentchanges (rc_namespace, rc_user_text); +CREATE INDEX /*i*/rc_user_text ON /*_*/recentchanges (rc_user_text, rc_timestamp); + + +CREATE TABLE /*_*/watchlist ( -- Key to user.user_id wl_user int unsigned NOT NULL, -- Key to page_namespace/page_title -- Note that users may watch pages which do not exist yet, -- or existed in the past but have been deleted. - wl_namespace int NOT NULL default '0', + wl_namespace int NOT NULL default 0, wl_title varchar(255) binary NOT NULL default '', -- Timestamp when user was last sent a notification e-mail; -- cleared when the user visits the page. - wl_notificationtimestamp varbinary(14), + wl_notificationtimestamp varbinary(14) - UNIQUE KEY (wl_user, wl_namespace, wl_title), - KEY namespace_title (wl_namespace, wl_title) - ) /*$wgDBTableOptions*/; +CREATE UNIQUE INDEX /*i*/wl_user ON /*_*/watchlist (wl_user, wl_namespace, wl_title); +CREATE INDEX /*i*/namespace_title ON /*_*/watchlist (wl_namespace, wl_title); + -- -- Used by the math module to keep track -- of previously-rendered items. -- -CREATE TABLE /*$wgDBprefix*/math ( +CREATE TABLE /*_*/math ( -- Binary MD5 hash of the latex fragment, used as an identifier key. math_inputhash varbinary(16) NOT NULL, @@ -972,12 +966,12 @@ CREATE TABLE /*$wgDBprefix*/math ( math_html text, -- MathML output from texvc, if any - math_mathml text, - - UNIQUE KEY math_inputhash (math_inputhash) - + math_mathml text ) /*$wgDBTableOptions*/; +CREATE UNIQUE INDEX /*i*/math_inputhash ON /*_*/math (math_inputhash); + + -- -- When using the default MySQL search backend, page titles -- and text are munged to strip markup, do Unicode case folding, @@ -986,7 +980,7 @@ CREATE TABLE /*$wgDBprefix*/math ( -- This table must be MyISAM; InnoDB does not support the needed -- fulltext index. -- -CREATE TABLE /*$wgDBprefix*/searchindex ( +CREATE TABLE /*_*/searchindex ( -- Key to page_id si_page int unsigned NOT NULL, @@ -994,18 +988,18 @@ CREATE TABLE /*$wgDBprefix*/searchindex ( si_title varchar(255) NOT NULL default '', -- Munged version of body text - si_text mediumtext NOT NULL, - - UNIQUE KEY (si_page), - FULLTEXT si_title (si_title), - FULLTEXT si_text (si_text) - + si_text mediumtext NOT NULL ) ENGINE=MyISAM; +CREATE UNIQUE INDEX /*i*/si_page ON /*_*/searchindex (si_page); +CREATE FULLTEXT INDEX /*i*/si_title ON /*_*/searchindex (si_title); +CREATE FULLTEXT INDEX /*i*/si_text ON /*_*/searchindex (si_text); + + -- -- Recognized interwiki link prefixes -- -CREATE TABLE /*$wgDBprefix*/interwiki ( +CREATE TABLE /*_*/interwiki ( -- The interwiki prefix, (e.g. "Meatball", or the language prefix "de") iw_prefix varchar(32) NOT NULL, @@ -1019,55 +1013,56 @@ CREATE TABLE /*$wgDBprefix*/interwiki ( iw_local bool NOT NULL, -- Boolean value indicating whether interwiki transclusions are allowed. - iw_trans tinyint NOT NULL default 0, - - UNIQUE KEY iw_prefix (iw_prefix) - + iw_trans tinyint NOT NULL default 0 ) /*$wgDBTableOptions*/; +CREATE UNIQUE INDEX /*i*/iw_prefix ON /*_*/interwiki (iw_prefix); + + -- -- Used for caching expensive grouped queries -- -CREATE TABLE /*$wgDBprefix*/querycache ( +CREATE TABLE /*_*/querycache ( -- A key name, generally the base name of of the special page. qc_type varbinary(32) NOT NULL, -- Some sort of stored value. Sizes, counts... - qc_value int unsigned NOT NULL default '0', + qc_value int unsigned NOT NULL default 0, -- Target namespace+title - qc_namespace int NOT NULL default '0', - qc_title varchar(255) binary NOT NULL default '', - - KEY (qc_type,qc_value) - + qc_namespace int NOT NULL default 0, + qc_title varchar(255) binary NOT NULL default '' ) /*$wgDBTableOptions*/; +CREATE INDEX /*i*/qc_type ON /*_*/querycache (qc_type,qc_value); + + -- -- For a few generic cache operations if not using Memcached -- -CREATE TABLE /*$wgDBprefix*/objectcache ( - keyname varbinary(255) NOT NULL default '', +CREATE TABLE /*_*/objectcache ( + keyname varbinary(255) NOT NULL default '' PRIMARY KEY, value mediumblob, - exptime datetime, - PRIMARY KEY (keyname), - KEY (exptime) - + exptime datetime ) /*$wgDBTableOptions*/; +CREATE INDEX /*i*/exptime ON /*_*/objectcache (exptime); + -- -- Cache of interwiki transclusion -- -CREATE TABLE /*$wgDBprefix*/transcache ( +CREATE TABLE /*_*/transcache ( tc_url varbinary(255) NOT NULL, tc_contents text, - tc_time int NOT NULL, - UNIQUE INDEX tc_url_idx (tc_url) + tc_time int NOT NULL ) /*$wgDBTableOptions*/; -CREATE TABLE /*$wgDBprefix*/logging ( +CREATE UNIQUE INDEX /*i*/tc_url_idx ON /*_*/transcache (tc_url); + + +CREATE TABLE /*_*/logging ( -- Log ID, for referring to this specific log entry, probably for deletion and such. - log_id int unsigned NOT NULL auto_increment, + log_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT, -- Symbolic keys for the general log type and the action type -- within the log. The output format will be controlled by the @@ -1093,32 +1088,29 @@ CREATE TABLE /*$wgDBprefix*/logging ( log_params blob NOT NULL, -- rev_deleted for logs - log_deleted tinyint unsigned NOT NULL default '0', + log_deleted tinyint unsigned NOT NULL default 0 +) /*$wgDBTableOptions*/; - PRIMARY KEY log_id (log_id), - KEY type_time (log_type, log_timestamp), - KEY user_time (log_user, log_timestamp), - KEY page_time (log_namespace, log_title, log_timestamp), - KEY times (log_timestamp) +CREATE INDEX /*i*/type_time ON /*_*/logging (log_type, log_timestamp); +CREATE INDEX /*i*/user_time ON /*_*/logging (log_user, log_timestamp); +CREATE INDEX /*i*/page_time ON /*_*/logging (log_namespace, log_title, log_timestamp); +CREATE INDEX /*i*/times ON /*_*/logging (log_timestamp); -) /*$wgDBTableOptions*/; -CREATE TABLE /*$wgDBprefix*/trackbacks ( - tb_id int auto_increment, - tb_page int REFERENCES /*$wgDBprefix*/page(page_id) ON DELETE CASCADE, +CREATE TABLE /*_*/trackbacks ( + tb_id int PRIMARY KEY AUTO_INCREMENT, + tb_page int REFERENCES /*_*/page(page_id) ON DELETE CASCADE, tb_title varchar(255) NOT NULL, tb_url blob NOT NULL, tb_ex text, - tb_name varchar(255), - - PRIMARY KEY (tb_id), - INDEX (tb_page) + tb_name varchar(255) ) /*$wgDBTableOptions*/; +CREATE INDEX /*i*/tb_page ON /*_*/trackbacks (tb_page); -- Jobs performed by parallel apache threads or a command-line daemon -CREATE TABLE /*$wgDBprefix*/job ( - job_id int unsigned NOT NULL auto_increment, +CREATE TABLE /*_*/job ( + job_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT, -- Command name -- Limited to 60 to prevent key length overflow @@ -1130,68 +1122,66 @@ CREATE TABLE /*$wgDBprefix*/job ( job_title varchar(255) binary NOT NULL, -- Any other parameters to the command - -- Presently unused, format undefined - job_params blob NOT NULL, - - PRIMARY KEY job_id (job_id), - KEY (job_cmd, job_namespace, job_title) + -- Stored as a PHP serialized array, or an empty string if there are no parameters + job_params blob NOT NULL ) /*$wgDBTableOptions*/; +CREATE INDEX /*i*/job_cmd ON /*_*/job (job_cmd, job_namespace, job_title); --- Details of updates to cached special pages -CREATE TABLE /*$wgDBprefix*/querycache_info ( +-- Details of updates to cached special pages +CREATE TABLE /*_*/querycache_info ( -- Special page name -- Corresponds to a qc_type value qci_type varbinary(32) NOT NULL default '', -- Timestamp of last update - qci_timestamp binary(14) NOT NULL default '19700101000000', + qci_timestamp binary(14) NOT NULL default '19700101000000' +) /*$wgDBTableOptions*/; - UNIQUE KEY ( qci_type ) +CREATE UNIQUE INDEX /*i*/qci_type ON /*_*/querycache_info (qci_type); -) /*$wgDBTableOptions*/; -- For each redirect, this table contains exactly one row defining its target -CREATE TABLE /*$wgDBprefix*/redirect ( +CREATE TABLE /*_*/redirect ( -- Key to the page_id of the redirect page - rd_from int unsigned NOT NULL default '0', + rd_from int unsigned NOT NULL default 0 PRIMARY KEY, -- Key to page_namespace/page_title of the target page. -- The target page may or may not exist, and due to renames -- and deletions may refer to different page records as time -- goes by. - rd_namespace int NOT NULL default '0', - rd_title varchar(255) binary NOT NULL default '', - - PRIMARY KEY rd_from (rd_from), - KEY rd_ns_title (rd_namespace,rd_title,rd_from) + rd_namespace int NOT NULL default 0, + rd_title varchar(255) binary NOT NULL default '' ) /*$wgDBTableOptions*/; +CREATE INDEX /*i*/rd_ns_title ON /*_*/redirect (rd_namespace,rd_title,rd_from); + + -- Used for caching expensive grouped queries that need two links (for example double-redirects) -CREATE TABLE /*$wgDBprefix*/querycachetwo ( +CREATE TABLE /*_*/querycachetwo ( -- A key name, generally the base name of of the special page. qcc_type varbinary(32) NOT NULL, -- Some sort of stored value. Sizes, counts... - qcc_value int unsigned NOT NULL default '0', + qcc_value int unsigned NOT NULL default 0, -- Target namespace+title - qcc_namespace int NOT NULL default '0', + qcc_namespace int NOT NULL default 0, qcc_title varchar(255) binary NOT NULL default '', -- Target namespace+title2 - qcc_namespacetwo int NOT NULL default '0', - qcc_titletwo varchar(255) binary NOT NULL default '', + qcc_namespacetwo int NOT NULL default 0, + qcc_titletwo varchar(255) binary NOT NULL default '' +) /*$wgDBTableOptions*/; - KEY qcc_type (qcc_type,qcc_value), - KEY qcc_title (qcc_type,qcc_namespace,qcc_title), - KEY qcc_titletwo (qcc_type,qcc_namespacetwo,qcc_titletwo) +CREATE INDEX /*i*/qcc_type ON /*_*/querycachetwo (qcc_type,qcc_value); +CREATE INDEX /*i*/qcc_title ON /*_*/querycachetwo (qcc_type,qcc_namespace,qcc_title); +CREATE INDEX /*i*/qcc_titletwo ON /*_*/querycachetwo (qcc_type,qcc_namespacetwo,qcc_titletwo); -) /*$wgDBTableOptions*/; -- Used for storing page restrictions (i.e. protection levels) -CREATE TABLE /*$wgDBprefix*/page_restrictions ( +CREATE TABLE /*_*/page_restrictions ( -- Page to apply restrictions to (Foreign Key to page). pr_page int NOT NULL, -- The protection type (edit, move, etc) @@ -1205,42 +1195,78 @@ CREATE TABLE /*$wgDBprefix*/page_restrictions ( -- Field for time-limited protection. pr_expiry varbinary(14) NULL, -- Field for an ID for this restrictions row (sort-key for Special:ProtectedPages) - pr_id int unsigned NOT NULL auto_increment, + pr_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT +) /*$wgDBTableOptions*/; - PRIMARY KEY pr_pagetype (pr_page,pr_type), +CREATE UNIQUE INDEX /*i*/pr_pagetype ON /*_*/page_restrictions (pr_page,pr_type); +CREATE INDEX /*i*/pr_typelevel ON /*_*/page_restrictions (pr_type,pr_level); +CREATE INDEX /*i*/pr_level ON /*_*/page_restrictions (pr_level); +CREATE INDEX /*i*/pr_cascade ON /*_*/page_restrictions (pr_cascade); - UNIQUE KEY pr_id (pr_id), - KEY pr_typelevel (pr_type,pr_level), - KEY pr_level (pr_level), - KEY pr_cascade (pr_cascade) -) /*$wgDBTableOptions*/; -- Protected titles - nonexistent pages that have been protected -CREATE TABLE /*$wgDBprefix*/protected_titles ( +CREATE TABLE /*_*/protected_titles ( pt_namespace int NOT NULL, pt_title varchar(255) binary NOT NULL, pt_user int unsigned NOT NULL, pt_reason tinyblob, pt_timestamp binary(14) NOT NULL, pt_expiry varbinary(14) NOT NULL default '', - pt_create_perm varbinary(60) NOT NULL, - PRIMARY KEY (pt_namespace,pt_title), - KEY pt_timestamp (pt_timestamp) + pt_create_perm varbinary(60) NOT NULL ) /*$wgDBTableOptions*/; +CREATE UNIQUE INDEX /*i*/pt_namespace_title ON /*_*/protected_titles (pt_namespace,pt_title); +CREATE INDEX /*i*/pt_timestamp ON /*_*/protected_titles (pt_timestamp); + + -- Name/value pairs indexed by page_id -CREATE TABLE /*$wgDBprefix*/page_props ( +CREATE TABLE /*_*/page_props ( pp_page int NOT NULL, pp_propname varbinary(60) NOT NULL, - pp_value blob NOT NULL, - - PRIMARY KEY (pp_page,pp_propname) + pp_value blob NOT NULL ) /*$wgDBTableOptions*/; +CREATE UNIQUE INDEX /*i*/pp_page_propname ON /*_*/page_props (pp_page,pp_propname); + + -- A table to log updates, one text key row per update. -CREATE TABLE /*$wgDBprefix*/updatelog ( - ul_key varchar(255) NOT NULL, - PRIMARY KEY (ul_key) +CREATE TABLE /*_*/updatelog ( + ul_key varchar(255) NOT NULL PRIMARY KEY +) /*$wgDBTableOptions*/; + + +-- A table to track tags for revisions, logs and recent changes. +CREATE TABLE /*_*/change_tag ( + ct_rc_id int NULL, + ct_log_id int NULL, + ct_rev_id int NULL, + ct_tag varchar(255) NOT NULL, + ct_params blob NULL ) /*$wgDBTableOptions*/; +CREATE UNIQUE INDEX /*i*/change_tag_rc_tag ON /*_*/change_tag (ct_rc_id,ct_tag); +CREATE UNIQUE INDEX /*i*/change_tag_log_tag ON /*_*/change_tag (ct_log_id,ct_tag); +CREATE UNIQUE INDEX /*i*/change_tag_rev_tag ON /*_*/change_tag (ct_rev_id,ct_tag); +-- Covering index, so we can pull all the info only out of the index. +CREATE INDEX /*i*/change_tag_tag_id ON /*_*/change_tag (ct_tag,ct_rc_id,ct_rev_id,ct_log_id); + + +-- Rollup table to pull a LIST of tags simply without ugly GROUP_CONCAT that only works on MySQL 4.1+ +CREATE TABLE /*_*/tag_summary ( + ts_rc_id int NULL, + ts_log_id int NULL, + ts_rev_id int NULL, + ts_tags blob NOT NULL +) /*$wgDBTableOptions*/; + +CREATE UNIQUE INDEX /*i*/tag_summary_rc_id ON /*_*/tag_summary (ts_rc_id); +CREATE UNIQUE INDEX /*i*/tag_summary_log_id ON /*_*/tag_summary (ts_log_id); +CREATE UNIQUE INDEX /*i*/tag_summary_rev_id ON /*_*/tag_summary (ts_rev_id); + + +CREATE TABLE /*_*/valid_tag ( + vt_tag varchar(255) NOT NULL PRIMARY KEY +) /*$wgDBTableOptions*/; + + -- vim: sw=2 sts=2 et diff --git a/maintenance/updateRestrictions.php b/maintenance/updateRestrictions.php index f0567b5b..59879eaa 100644 --- a/maintenance/updateRestrictions.php +++ b/maintenance/updateRestrictions.php @@ -22,25 +22,23 @@ if ( !$db->tableExists( 'page_restrictions' ) ) { migrate_page_restrictions( $db ); function migrate_page_restrictions( $db ) { - $start = $db->selectField( 'page', 'MIN(page_id)', false, __FUNCTION__ ); - $end = $db->selectField( 'page', 'MAX(page_id)', false, __FUNCTION__ ); - if( !$start ) { die("Nothing to do.\n"); } + $end = $db->selectField( 'page', 'MAX(page_id)', false, __FUNCTION__ ); # Do remaining chunk $end += BATCH_SIZE - 1; $blockStart = $start; $blockEnd = $start + BATCH_SIZE - 1; $encodedExpiry = 'infinity'; - while ( $blockEnd <= $end ) { + while( $blockEnd <= $end ) { echo "...doing page_id from $blockStart to $blockEnd\n"; $cond = "page_id BETWEEN $blockStart AND $blockEnd AND page_restrictions !=''"; - $res = $db->select( 'page', array('page_id', 'page_restrictions'), $cond, __FUNCTION__ ); + $res = $db->select( 'page', array('page_id','page_namespace','page_restrictions'), $cond, __FUNCTION__ ); $batch = array(); - while ( $row = $db->fetchObject( $res ) ) { + while( $row = $db->fetchObject( $res ) ) { $oldRestrictions = array(); foreach( explode( ':', trim( $row->page_restrictions ) ) as $restrict ) { $temp = explode( '=', trim( $restrict ) ); @@ -53,6 +51,12 @@ function migrate_page_restrictions( $db ) { $oldRestrictions[$temp[0]] = trim( $temp[1] ); } } + # Clear invalid columns + if( $row->page_namespace == NS_MEDIAWIKI ) { + $db->update( 'page', array( 'page_restrictions' => '' ), + array( 'page_id' => $row->page_id ), __FUNCTION__ ); + echo "...removed dead page_restrictions column for page {$row->page_id}\n"; + } # Update restrictions table foreach( $oldRestrictions as $action => $restrictions ) { $batch[] = array( @@ -67,9 +71,8 @@ function migrate_page_restrictions( $db ) { # We use insert() and not replace() as Article.php replaces # page_restrictions with '' when protected in the restrictions table if ( count( $batch ) ) { - $ok = $db->deadlockLoop( - array( $db, 'insert' ), - 'page_restrictions', $batch, __FUNCTION__, array( 'IGNORE' ) ); + $ok = $db->deadlockLoop( array( $db, 'insert' ), 'page_restrictions', + $batch, __FUNCTION__, array( 'IGNORE' ) ); if( !$ok ) { throw new MWException( "Deadlock loop failed wtf :(" ); } @@ -81,6 +84,8 @@ function migrate_page_restrictions( $db ) { echo "...removing dead rows from page_restrictions\n"; // Kill any broken rows from previous imports $db->delete( 'page_restrictions', array( 'pr_level' => '' ) ); + // Kill other invalid rows + $db->deleteJoin( 'page_restrictions', 'page', 'pr_page', 'page_id', array('page_namespace' => NS_MEDIAWIKI) ); echo "...Done!\n"; } diff --git a/maintenance/updaters.inc b/maintenance/updaters.inc index e671efe5..71a0fe84 100644 --- a/maintenance/updaters.inc +++ b/maintenance/updaters.inc @@ -16,138 +16,159 @@ require_once 'deleteDefaultMessages.php'; require_once( "$IP/includes/Hooks.php" ); /** - * List of update functions to call on a MySQL-based MediaWiki installation, - * in sequence. First item is function name, rest are parameters to pass. + * List of update functions to call for each DB type, in sequence. First item + * is function name, rest are parameters to pass. */ -$wgMysqlUpdates = array( - // 1.2 - // update_passwords obsolete - array( 'add_field', 'ipblocks', 'ipb_id', 'patch-ipblocks.sql' ), - array( 'add_field', 'ipblocks', 'ipb_expiry', 'patch-ipb_expiry.sql' ), - array( 'do_interwiki_update' ), - array( 'do_index_update' ), - // do_linkscc_update obsolete - array( 'add_table', 'hitcounter', 'patch-hitcounter.sql' ), - array( 'add_field', 'recentchanges', 'rc_type', 'patch-rc_type.sql' ), - - // 1.3 - array( 'add_field', 'user', 'user_real_name', 'patch-user-realname.sql' ), - array( 'add_table', 'querycache', 'patch-querycache.sql' ), - array( 'add_table', 'objectcache', 'patch-objectcache.sql' ), - array( 'add_table', 'categorylinks', 'patch-categorylinks.sql' ), - // do_linkscc_1_3_update obsolete - array( 'do_old_links_update' ), - array( 'add_field', 'recentchanges', 'rc_ip', 'patch-rc_ip.sql' ), - - // 1.4 - array( 'do_image_name_unique_update' ), - array( 'add_field', 'recentchanges', 'rc_id', 'patch-rc_id.sql' ), - array( 'add_field', 'recentchanges', 'rc_patrolled', 'patch-rc-patrol.sql' ), - array( 'add_table', 'logging', 'patch-logging.sql' ), - // do_user_rights_update obsolete - array( 'add_field', 'user', 'user_token', 'patch-user_token.sql' ), - // old, old_articleid, patch-remove-old-title-namespace.sql obsolete - // user_groups, patch-userlevels.sql obsolete - // do_group_update() obsolete - array( 'do_watchlist_update' ), - array( 'do_user_update' ), - // do_copy_newtalk_to_watchlist obsolete - - // 1.5 - array( 'do_schema_restructuring' ), - array( 'add_field', 'logging', 'log_params', 'patch-log_params.sql' ), - array( 'check_bin', 'logging', 'log_title', 'patch-logging-title.sql', ), - array( 'add_field', 'archive', 'ar_rev_id', 'patch-archive-rev_id.sql' ), - array( 'add_field', 'page', 'page_len', 'patch-page_len.sql' ), - array( 'do_inverse_timestamp' ), - array( 'do_text_id' ), - array( 'add_field', 'revision', 'rev_deleted', 'patch-rev_deleted.sql' ), - array( 'add_field', 'image', 'img_width', 'patch-img_width.sql' ), - array( 'add_field', 'image', 'img_metadata', 'patch-img_metadata.sql' ), - array( 'add_field', 'user', 'user_email_token', 'patch-user_email_token.sql' ), - array( 'add_field', 'archive', 'ar_text_id', 'patch-archive-text_id.sql' ), - array( 'do_namespace_size' ), - array( 'add_field', 'image', 'img_media_type', 'patch-img_media_type.sql' ), - array( 'do_pagelinks_update' ), - array( 'do_drop_img_type' ), - array( 'do_user_unique_update' ), - array( 'do_user_groups_update' ), - array( 'add_field', 'site_stats', 'ss_total_pages', 'patch-ss_total_articles.sql' ), - array( 'add_table', 'user_newtalk', 'patch-usernewtalk2.sql' ), - array( 'add_table', 'transcache', 'patch-transcache.sql' ), - array( 'add_field', 'interwiki', 'iw_trans', 'patch-interwiki-trans.sql' ), - array( 'add_table', 'trackbacks', 'patch-trackbacks.sql' ), - - // 1.6 - array( 'do_watchlist_null' ), - // do_image_index_update obsolete - array( 'do_logging_timestamp_index' ), - array( 'add_field', 'ipblocks', 'ipb_range_start', 'patch-ipb_range_start.sql' ), - array( 'do_page_random_update' ), - array( 'add_field', 'user', 'user_registration','patch-user_registration.sql' ), - array( 'do_templatelinks_update' ), - array( 'add_table', 'externallinks', 'patch-externallinks.sql' ), - array( 'add_table', 'job', 'patch-job.sql' ), - array( 'add_field', 'site_stats', 'ss_images', 'patch-ss_images.sql' ), - array( 'add_table', 'langlinks', 'patch-langlinks.sql' ), - array( 'add_table', 'querycache_info', 'patch-querycacheinfo.sql' ), - array( 'add_table', 'filearchive', 'patch-filearchive.sql' ), - array( 'add_field', 'ipblocks', 'ipb_anon_only', 'patch-ipb_anon_only.sql' ), - array( 'do_rc_indices_update' ), - - // 1.9 - array( 'add_field', 'user', 'user_newpass_time', 'patch-user_newpass_time.sql' ), - array( 'add_table', 'redirect', 'patch-redirect.sql' ), - array( 'add_table', 'querycachetwo', 'patch-querycachetwo.sql' ), - array( 'add_field', 'ipblocks', 'ipb_enable_autoblock', 'patch-ipb_optional_autoblock.sql' ), - array( 'do_backlinking_indices_update' ), - array( 'add_field', 'recentchanges', 'rc_old_len', 'patch-rc_len.sql' ), - array( 'add_field', 'user', 'user_editcount', 'patch-user_editcount.sql' ), - - // 1.10 - array( 'do_restrictions_update' ), - array( 'add_field', 'logging', 'log_id', 'patch-log_id.sql' ), - array( 'add_field', 'revision', 'rev_parent_id', 'patch-rev_parent_id.sql' ), - array( 'add_field', 'page_restrictions', 'pr_id', 'patch-page_restrictions_sortkey.sql' ), - array( 'add_field', 'revision', 'rev_len', 'patch-rev_len.sql' ), - array( 'add_field', 'recentchanges', 'rc_deleted', 'patch-rc_deleted.sql' ), - array( 'add_field', 'logging', 'log_deleted', 'patch-log_deleted.sql' ), - array( 'add_field', 'archive', 'ar_deleted', 'patch-ar_deleted.sql' ), - array( 'add_field', 'ipblocks', 'ipb_deleted', 'patch-ipb_deleted.sql' ), - array( 'add_field', 'filearchive', 'fa_deleted', 'patch-fa_deleted.sql' ), - array( 'add_field', 'archive', 'ar_len', 'patch-ar_len.sql' ), - - // 1.11 - array( 'add_field', 'ipblocks', 'ipb_block_email', 'patch-ipb_emailban.sql' ), - array( 'do_categorylinks_indices_update' ), - array( 'add_field', 'oldimage', 'oi_metadata', 'patch-oi_metadata.sql'), - array( 'do_archive_user_index' ), - array( 'do_image_user_index' ), - array( 'do_oldimage_user_index' ), - array( 'add_field', 'archive', 'ar_page_id', 'patch-archive-page_id.sql'), - array( 'add_field', 'image', 'img_sha1', 'patch-img_sha1.sql' ), - - // 1.12 - array( 'add_table', 'protected_titles', 'patch-protected_titles.sql' ), - - // 1.13 - array( 'add_field', 'ipblocks', 'ipb_by_text', 'patch-ipb_by_text.sql' ), - array( 'add_table', 'page_props', 'patch-page_props.sql' ), - array( 'add_table', 'updatelog', 'patch-updatelog.sql' ), - array( 'add_table', 'category', 'patch-category.sql' ), - array( 'do_category_population' ), - array( 'add_field', 'archive', 'ar_parent_id', 'patch-ar_parent_id.sql'), - array( 'add_field', 'user_newtalk', 'user_last_timestamp', 'patch-user_last_timestamp.sql'), - array( 'do_populate_parent_id' ), - array( 'check_bin', 'protected_titles', 'pt_title', 'patch-pt_title-encoding.sql', ), - array( 'maybe_do_profiling_memory_update' ), - array( 'do_filearchive_indices_update' ), - array( 'update_password_format' ), - - // 1.14 - array( 'add_field', 'site_stats', 'ss_active_users', 'patch-ss_active_users.sql' ), - array( 'do_active_users_init' ), - array( 'add_field', 'ipblocks', 'ipb_allow_usertalk', 'patch-ipb_allow_usertalk.sql' ) +$wgUpdates = array( + 'mysql' => array( + // 1.2 + // update_passwords obsolete + array( 'add_field', 'ipblocks', 'ipb_id', 'patch-ipblocks.sql' ), + array( 'add_field', 'ipblocks', 'ipb_expiry', 'patch-ipb_expiry.sql' ), + array( 'do_interwiki_update' ), + array( 'do_index_update' ), + // do_linkscc_update obsolete + array( 'add_table', 'hitcounter', 'patch-hitcounter.sql' ), + array( 'add_field', 'recentchanges', 'rc_type', 'patch-rc_type.sql' ), + + // 1.3 + array( 'add_field', 'user', 'user_real_name', 'patch-user-realname.sql' ), + array( 'add_table', 'querycache', 'patch-querycache.sql' ), + array( 'add_table', 'objectcache', 'patch-objectcache.sql' ), + array( 'add_table', 'categorylinks', 'patch-categorylinks.sql' ), + // do_linkscc_1_3_update obsolete + array( 'do_old_links_update' ), + array( 'fix_ancient_imagelinks' ), + array( 'add_field', 'recentchanges', 'rc_ip', 'patch-rc_ip.sql' ), + + // 1.4 + array( 'do_image_name_unique_update' ), + array( 'add_field', 'recentchanges', 'rc_id', 'patch-rc_id.sql' ), + array( 'add_field', 'recentchanges', 'rc_patrolled', 'patch-rc-patrol.sql' ), + array( 'add_table', 'logging', 'patch-logging.sql' ), + // do_user_rights_update obsolete + array( 'add_field', 'user', 'user_token', 'patch-user_token.sql' ), + // old, old_articleid, patch-remove-old-title-namespace.sql obsolete + // user_groups, patch-userlevels.sql obsolete + // do_group_update() obsolete + array( 'do_watchlist_update' ), + array( 'do_user_update' ), + // do_copy_newtalk_to_watchlist obsolete + + // 1.5 + array( 'do_schema_restructuring' ), + array( 'add_field', 'logging', 'log_params', 'patch-log_params.sql' ), + array( 'check_bin', 'logging', 'log_title', 'patch-logging-title.sql', ), + array( 'add_field', 'archive', 'ar_rev_id', 'patch-archive-rev_id.sql' ), + array( 'add_field', 'page', 'page_len', 'patch-page_len.sql' ), + array( 'do_inverse_timestamp' ), + array( 'do_text_id' ), + array( 'add_field', 'revision', 'rev_deleted', 'patch-rev_deleted.sql' ), + array( 'add_field', 'image', 'img_width', 'patch-img_width.sql' ), + array( 'add_field', 'image', 'img_metadata', 'patch-img_metadata.sql' ), + array( 'add_field', 'user', 'user_email_token', 'patch-user_email_token.sql' ), + array( 'add_field', 'archive', 'ar_text_id', 'patch-archive-text_id.sql' ), + array( 'do_namespace_size' ), + array( 'add_field', 'image', 'img_media_type', 'patch-img_media_type.sql' ), + array( 'do_pagelinks_update' ), + array( 'do_drop_img_type' ), + array( 'do_user_unique_update' ), + array( 'do_user_groups_update' ), + array( 'add_field', 'site_stats', 'ss_total_pages', 'patch-ss_total_articles.sql' ), + array( 'add_table', 'user_newtalk', 'patch-usernewtalk2.sql' ), + array( 'add_table', 'transcache', 'patch-transcache.sql' ), + array( 'add_field', 'interwiki', 'iw_trans', 'patch-interwiki-trans.sql' ), + array( 'add_table', 'trackbacks', 'patch-trackbacks.sql' ), + + // 1.6 + array( 'do_watchlist_null' ), + // do_image_index_update obsolete + array( 'do_logging_timestamp_index' ), + array( 'add_field', 'ipblocks', 'ipb_range_start', 'patch-ipb_range_start.sql' ), + array( 'do_page_random_update' ), + array( 'add_field', 'user', 'user_registration','patch-user_registration.sql' ), + array( 'do_templatelinks_update' ), + array( 'add_table', 'externallinks', 'patch-externallinks.sql' ), + array( 'add_table', 'job', 'patch-job.sql' ), + array( 'add_field', 'site_stats', 'ss_images', 'patch-ss_images.sql' ), + array( 'add_table', 'langlinks', 'patch-langlinks.sql' ), + array( 'add_table', 'querycache_info', 'patch-querycacheinfo.sql' ), + array( 'add_table', 'filearchive', 'patch-filearchive.sql' ), + array( 'add_field', 'ipblocks', 'ipb_anon_only', 'patch-ipb_anon_only.sql' ), + array( 'do_rc_indices_update' ), + + // 1.9 + array( 'add_field', 'user', 'user_newpass_time', 'patch-user_newpass_time.sql' ), + array( 'add_table', 'redirect', 'patch-redirect.sql' ), + array( 'add_table', 'querycachetwo', 'patch-querycachetwo.sql' ), + array( 'add_field', 'ipblocks', 'ipb_enable_autoblock', 'patch-ipb_optional_autoblock.sql' ), + array( 'do_backlinking_indices_update' ), + array( 'add_field', 'recentchanges', 'rc_old_len', 'patch-rc_len.sql' ), + array( 'add_field', 'user', 'user_editcount', 'patch-user_editcount.sql' ), + + // 1.10 + array( 'do_restrictions_update' ), + array( 'add_field', 'logging', 'log_id', 'patch-log_id.sql' ), + array( 'add_field', 'revision', 'rev_parent_id', 'patch-rev_parent_id.sql' ), + array( 'add_field', 'page_restrictions', 'pr_id', 'patch-page_restrictions_sortkey.sql' ), + array( 'add_field', 'revision', 'rev_len', 'patch-rev_len.sql' ), + array( 'add_field', 'recentchanges', 'rc_deleted', 'patch-rc_deleted.sql' ), + array( 'add_field', 'logging', 'log_deleted', 'patch-log_deleted.sql' ), + array( 'add_field', 'archive', 'ar_deleted', 'patch-ar_deleted.sql' ), + array( 'add_field', 'ipblocks', 'ipb_deleted', 'patch-ipb_deleted.sql' ), + array( 'add_field', 'filearchive', 'fa_deleted', 'patch-fa_deleted.sql' ), + array( 'add_field', 'archive', 'ar_len', 'patch-ar_len.sql' ), + + // 1.11 + array( 'add_field', 'ipblocks', 'ipb_block_email', 'patch-ipb_emailban.sql' ), + array( 'do_categorylinks_indices_update' ), + array( 'add_field', 'oldimage', 'oi_metadata', 'patch-oi_metadata.sql'), + array( 'do_archive_user_index' ), + array( 'do_image_user_index' ), + array( 'do_oldimage_user_index' ), + array( 'add_field', 'archive', 'ar_page_id', 'patch-archive-page_id.sql'), + array( 'add_field', 'image', 'img_sha1', 'patch-img_sha1.sql' ), + + // 1.12 + array( 'add_table', 'protected_titles', 'patch-protected_titles.sql' ), + + // 1.13 + array( 'add_field', 'ipblocks', 'ipb_by_text', 'patch-ipb_by_text.sql' ), + array( 'add_table', 'page_props', 'patch-page_props.sql' ), + array( 'add_table', 'updatelog', 'patch-updatelog.sql' ), + array( 'add_table', 'category', 'patch-category.sql' ), + array( 'do_category_population' ), + array( 'add_field', 'archive', 'ar_parent_id', 'patch-ar_parent_id.sql'), + array( 'add_field', 'user_newtalk', 'user_last_timestamp', 'patch-user_last_timestamp.sql'), + array( 'do_populate_parent_id' ), + array( 'check_bin', 'protected_titles', 'pt_title', 'patch-pt_title-encoding.sql', ), + array( 'maybe_do_profiling_memory_update' ), + array( 'do_filearchive_indices_update' ), + + // 1.14 + array( 'add_field', 'site_stats', 'ss_active_users', 'patch-ss_active_users.sql' ), + array( 'do_active_users_init' ), + array( 'add_field', 'ipblocks', 'ipb_allow_usertalk', 'patch-ipb_allow_usertalk.sql' ), + array( 'do_unique_pl_tl_il' ), + + // 1.15 + array( 'add_table', 'change_tag', 'patch-change_tag.sql' ), + array( 'add_table', 'tag_summary', 'patch-change_tag.sql' ), + array( 'add_table', 'valid_tag', 'patch-change_tag.sql' ), + ), + + 'sqlite' => array( + // 1.14 + array( 'add_field', 'site_stats', 'ss_active_users', 'patch-ss_active_users.sql' ), + array( 'do_active_users_init' ), + array( 'add_field', 'ipblocks', 'ipb_allow_usertalk', 'patch-ipb_allow_usertalk.sql' ), + array( 'sqlite_initial_indexes' ), + + // 1.15 + array( 'add_table', 'change_tag', 'patch-change_tag.sql' ), + array( 'add_table', 'tag_summary', 'patch-change_tag.sql' ), + array( 'add_table', 'valid_tag', 'patch-change_tag.sql' ), + ), ); @@ -236,41 +257,6 @@ function add_index( $table, $index, $patch, $fullpath=false ) { } } -function do_revision_updates() { - global $wgSoftwareRevision; - if ( $wgSoftwareRevision < 1001 ) { - update_passwords(); - } -} - -function update_passwords() { - wfDebugDieBacktrace( "This function needs to be updated or removed.\n" ); - - global $wgDatabase; - $fname = "Update script: update_passwords()"; - wfOut( "\nIt appears that you need to update the user passwords in your\n" . - "database. If you have already done this (if you've run this update\n" . - "script once before, for example), doing so again will make all your\n" . - "user accounts inaccessible, so be sure you only do this once.\n" . - "Update user passwords? (yes/no)" ); - - $resp = readconsole(); - if ( ! ( "Y" == $resp{0} || "y" == $resp{0} ) ) { return; } - - $sql = "SELECT user_id,user_password FROM user"; - $source = $wgDatabase->query( $sql, $fname ); - - while ( $row = $wgDatabase->fetchObject( $source ) ) { - $id = $row->user_id; - $oldpass = $row->user_password; - $newpass = md5( "{$id}-{$oldpass}" ); - - $sql = "UPDATE user SET user_password='{$newpass}' " . - "WHERE user_id={$id}"; - $wgDatabase->query( $sql, $fname ); - } -} - function do_interwiki_update() { # Check that interwiki table exists; if it doesn't source it global $wgDatabase, $IP; @@ -759,6 +745,19 @@ function do_old_links_update() { } } +function fix_ancient_imagelinks() { + global $wgDatabase; + $info = $wgDatabase->fieldInfo( 'imagelinks', 'il_from' ); + if ( $info && $info->type() === 'string' ) { + wfOut( "Fixing ancient broken imagelinks table.\n" ); + wfOut( "NOTE: you will have to run maintenance/refreshLinks.php after this.\n" ); + dbsource( archive( 'patch-fix-il_from.sql' ) ); + wfOut( "ok\n" ); + } else { + wfOut( "...il_from OK\n" ); + } +} + function do_user_unique_update() { global $wgDatabase; $duper = new UserDupes( $wgDatabase ); @@ -1070,11 +1069,13 @@ function do_all_updates( $shared = false, $purge = true ) { } # Run core updates in sequence... - global $wgMysqlUpdates; - foreach( $wgMysqlUpdates as $params ) { - $func = array_shift( $params ); - call_user_func_array( $func, $params ); - flush(); + global $wgUpdates; + if ( isset( $wgUpdates[$wgDBtype] ) ) { + foreach( $wgUpdates[$wgDBtype] as $params ) { + $func = array_shift( $params ); + call_user_func_array( $func, $params ); + flush(); + } } /// @fixme clean up this mess too! @@ -1111,10 +1112,9 @@ function do_all_updates( $shared = false, $purge = true ) { function archive($name) { global $wgDBtype, $IP; - switch ($wgDBtype) { - case "postgres": - return "$IP/maintenance/postgres/archives/$name"; - default: + if ( file_exists( "$IP/maintenance/$wgDBtype/archives/$name" ) ) { + return "$IP/maintenance/$wgDBtype/archives/$name"; + } else { return "$IP/maintenance/archives/$name"; } } @@ -1219,29 +1219,34 @@ function do_populate_parent_id() { populate_rev_parent_id( $wgDatabase ); } -function update_password_format() { - if ( update_row_exists( 'password format' ) ) { - wfOut( "...password hash format already changed\n" ); +function sqlite_initial_indexes() { + global $wgDatabase; + if ( update_row_exists( 'initial_indexes' ) ) { + wfOut( "...have initial indexes\n" ); return; } + wfOut( "Adding initial indexes..." ); + $wgDatabase->sourceFile( archive( 'initial-indexes.sql' ) ); + wfOut( "done\n" ); +} - wfOut( "Updating password hash format..." ); - - global $wgDatabase, $wgPasswordSalt; - $user = $wgDatabase->tableName( 'user' ); - if ( $wgPasswordSalt ) { - $sql = "UPDATE $user SET user_password=CONCAT(':B:', user_id, ':', user_password) " . - "WHERE user_password NOT LIKE ':%'"; +function do_unique_pl_tl_il() { + global $wgDatabase; + $info = $wgDatabase->indexInfo( 'pagelinks', 'pl_namespace' ); + if( is_array($info) && !$info[0]->Non_unique ) { + wfOut( "...pl_namespace, tl_namespace, il_to indices are already UNIQUE.\n" ); } else { - $sql = "UPDATE $user SET user_password=CONCAT(':A:', user_password) " . - "WHERE user_password NOT LIKE ':%'"; + wfOut( "Making pl_namespace, tl_namespace and il_to indices UNIQUE... " ); + dbsource( archive( 'patch-pl-tl-il-unique.sql' ), $wgDatabase ); + wfOut( "ok\n" ); } - $wgDatabase->query( $sql, __METHOD__ ); - $wgDatabase->insert( 'updatelog', array( 'ul_key' => 'password format' ), __METHOD__ ); - - wfOut( "done\n" ); } +/*********************************************************************** + * Start PG crap + * TODO: merge with above + ***********************************************************************/ + function pg_describe_table($table) { @@ -1406,6 +1411,7 @@ function do_postgres_updates() { wfOut( "Adding in schema \"$wgDBts2schema\" to search_path for user \"$wgDBuser\"\n" ); $search_path = "$search_path, $wgDBts2schema"; } + $search_path = str_replace( ', ,', ',', $search_path); if( array_key_exists( 'search_path', $conf ) === false || $search_path != $conf['search_path'] ) { $wgDatabase->doQuery( "ALTER USER $wgDBuser SET search_path = $search_path" ); $wgDatabase->doQuery( "SET search_path = $search_path" ); @@ -1448,6 +1454,9 @@ function do_postgres_updates() { array("protected_titles", "patch-protected_titles.sql"), array("redirect", "patch-redirect.sql"), array("updatelog", "patch-updatelog.sql"), + array('change_tag', 'patch-change_tag.sql'), + array('tag_summary', 'patch-change_tag.sql'), + array('valid_tag', 'patch-change_tag.sql'), ); $newcols = array( @@ -1456,23 +1465,24 @@ function do_postgres_updates() { array("archive", "ar_page_id", "INTEGER"), array("archive", "ar_parent_id", "INTEGER"), array("image", "img_sha1", "TEXT NOT NULL DEFAULT ''"), + array("ipblocks", "ipb_allow_usertalk", "SMALLINT NOT NULL DEFAULT 0"), array("ipblocks", "ipb_anon_only", "SMALLINT NOT NULL DEFAULT 0"), array("ipblocks", "ipb_by_text", "TEXT NOT NULL DEFAULT ''"), array("ipblocks", "ipb_block_email", "SMALLINT NOT NULL DEFAULT 0"), array("ipblocks", "ipb_create_account", "SMALLINT NOT NULL DEFAULT 1"), array("ipblocks", "ipb_deleted", "SMALLINT NOT NULL DEFAULT 0"), array("ipblocks", "ipb_enable_autoblock", "SMALLINT NOT NULL DEFAULT 1"), - array("ipblocks", "ipb_allow_usertalk", "SMALLINT NOT NULL DEFAULT 0"), array("filearchive", "fa_deleted", "SMALLINT NOT NULL DEFAULT 0"), array("logging", "log_deleted", "SMALLINT NOT NULL DEFAULT 0"), array("logging", "log_id", "INTEGER NOT NULL PRIMARY KEY DEFAULT nextval('log_log_id_seq')"), array("logging", "log_params", "TEXT"), array("mwuser", "user_editcount", "INTEGER"), + array("mwuser", "user_hidden", "SMALLINT NOT NULL DEFAULT 0"), array("mwuser", "user_newpass_time", "TIMESTAMPTZ"), array("oldimage", "oi_deleted", "SMALLINT NOT NULL DEFAULT 0"), - array("oldimage", "oi_metadata", "BYTEA NOT NULL DEFAULT ''"), - array("oldimage", "oi_media_type", "TEXT"), array("oldimage", "oi_major_mime", "TEXT NOT NULL DEFAULT 'unknown'"), + array("oldimage", "oi_media_type", "TEXT"), + array("oldimage", "oi_metadata", "BYTEA NOT NULL DEFAULT ''"), array("oldimage", "oi_minor_mime", "TEXT NOT NULL DEFAULT 'unknown'"), array("oldimage", "oi_sha1", "TEXT NOT NULL DEFAULT ''"), array("page_restrictions", "pr_id", "INTEGER NOT NULL UNIQUE DEFAULT nextval('pr_id_val')"), @@ -1484,11 +1494,11 @@ function do_postgres_updates() { array("recentchanges", "rc_new_len", "INTEGER"), array("recentchanges", "rc_old_len", "INTEGER"), array("recentchanges", "rc_params", "TEXT"), - array("revision", "rev_len", "INTEGER"), array("revision", "rev_deleted", "SMALLINT NOT NULL DEFAULT 0"), - array("user_newtalk", "user_last_timestamp", "TIMESTAMPTZ"), - array("site_stats", "ss_active_users", "INTEGER DEFAULT '-1'"), + array("revision", "rev_len", "INTEGER"), array("revision", "rev_parent_id", "INTEGER DEFAULT NULL"), + array("site_stats", "ss_active_users", "INTEGER DEFAULT '-1'"), + array("user_newtalk", "user_last_timestamp", "TIMESTAMPTZ"), ); @@ -1515,7 +1525,7 @@ function do_postgres_updates() { array("ipblocks", "ipb_enable_autoblock", "smallint", "CASE WHEN ipb_enable_autoblock=' ' THEN 0 ELSE ipb_enable_autoblock::smallint END DEFAULT 1"), array("ipblocks", "ipb_block_email", "smallint", "CASE WHEN ipb_block_email=' ' THEN 0 ELSE ipb_block_email::smallint END DEFAULT 0"), array("ipblocks", "ipb_address", "text", "ipb_address::text"), - array("ipblocks", "ipb_deleted", "smallint", "ipb_deleted::smallint"), + array("ipblocks", "ipb_deleted", "smallint", "ipb_deleted::smallint DEFAULT 0"), array("math", "math_inputhash", "bytea", "decode(math_inputhash,'escape')"), array("math", "math_outputhash", "bytea", "decode(math_outputhash,'escape')"), array("mwuser", "user_token", "text", ""), @@ -1541,12 +1551,20 @@ function do_postgres_updates() { array("user_newtalk", "user_ip", "text", "host(user_ip)"), ); + # table, column, nullability + $nullchanges = array( + array("oldimage", "oi_bits", "NULL"), + array("oldimage", "oi_timestamp", "NULL"), + array("oldimage", "oi_major_mime", "NULL"), + array("oldimage", "oi_minor_mime", "NULL"), + ); + $newindexes = array( array("archive", "archive_user_text", "(ar_user_text)"), array("image", "img_sha1", "(img_sha1)"), array("oldimage", "oi_sha1", "(oi_sha1)"), array("revision", "rev_text_id_idx", "(rev_text_id)"), - array("recentchanges", "rc_timestamp_nobot", "(rc_timestamp) WHERE rc_bot = 0"), + array("recentchanges", "rc_timestamp_bot", "(rc_timestamp) WHERE rc_bot = 0"), array("templatelinks", "templatelinks_from", "(tl_from)"), array("watchlist", "wl_user", "(wl_user)"), ); @@ -1627,6 +1645,34 @@ function do_postgres_updates() { } } + foreach ($nullchanges as $nc) { + $fi = $wgDatabase->fieldInfo($nc[0], $nc[1]); + if (is_null($fi)) { + wfOut( "... error: expected column $nc[0].$nc[1] to exist\n" ); + exit(1); + } + if ($fi->nullable()) { + ## It's NULL - does it need to be NOT NULL? + if ('NOT NULL' === $nc[2]) { + wfOut( "Changing \"$nc[0].$nc[1]\" to not allow NULLs\n" ); + $wgDatabase->query( "ALTER TABLE $nc[0] ALTER $nc[1] SET NOT NULL" ); + } + else { + wfOut( "... column \"$nc[0].$nc[1]\" is already set as NULL\n" ); + } + } + else { + ## It's NOT NULL - does it need to be NULL? + if ('NULL' === $nc[2]) { + wfOut( "Changing \"$nc[0].$nc[1]\" to allow NULLs\n" ); + $wgDatabase->query( "ALTER TABLE $nc[0] ALTER $nc[1] DROP NOT NULL" ); + } + else { + wfOut( "... column \"$nc[0].$nc[1]\" is already set as NOT NULL\n" ); + } + } + } + if ($wgDatabase->fieldInfo('oldimage','oi_deleted')->type() !== 'smallint') { wfOut( "Changing \"oldimage.oi_deleted\" to type \"smallint\"\n" ); $wgDatabase->query( "ALTER TABLE oldimage ALTER oi_deleted DROP DEFAULT" ); @@ -1656,7 +1702,7 @@ function do_postgres_updates() { } if ($wgDatabase->hasConstraint("oldimage_oi_name_fkey")) { - wfOut( "Making foriegn key on table \"oldimage\" (to image) a cascade delete\n" ); + wfOut( "Making foreign key on table \"oldimage\" (to image) a cascade delete\n" ); $wgDatabase->query( "ALTER TABLE oldimage DROP CONSTRAINT oldimage_oi_name_fkey" ); $wgDatabase->query( "ALTER TABLE oldimage ADD CONSTRAINT oldimage_oi_name_fkey_cascade ". "FOREIGN KEY (oi_name) REFERENCES image(img_name) ON DELETE CASCADE" ); @@ -1743,7 +1789,12 @@ function do_postgres_updates() { continue; } wfOut( "Creating index \"$ni[1]\" on table \"$ni[0]\"\n" ); - dbsource($ni[2]); + if ( preg_match( '/^\(/', $ni[2] ) ) { + $wgDatabase->query( "CREATE INDEX $ni[1] ON $ni[0] $ni[2]" ); + } + else { + dbsource($ni[2]); + } } # Tweak the page_title tsearch2 trigger to filter out slashes @@ -1762,8 +1813,8 @@ function do_postgres_updates() { 'ctype' => 'U', 'mw_version' => $wgVersion, 'pg_version' => $version, - 'sql_version' => '$LastChangedRevision: 46891 $', - 'sql_date' => '$LastChangedDate: 2009-02-05 22:54:47 -0600 (Thu, 05 Feb 2009) $', + 'sql_version' => '$LastChangedRevision: 51640 $', + 'sql_date' => '$LastChangedDate: 2009-06-09 07:58:05 -0500 (Tue, 09 Jun 2009) $', ) ); return; } -- cgit v1.2.2