For backport to 1.14.
authorTim Starling <tstarling@users.mediawiki.org>
Thu, 15 Jan 2009 06:56:58 +0000 (06:56 +0000)
committerTim Starling <tstarling@users.mediawiki.org>
Thu, 15 Jan 2009 06:56:58 +0000 (06:56 +0000)
* Made the upgrader work with SQLite
* Implemented missing schema info functionality in DatabaseSqlite
* Merged the SQLite and MySQL schemas into the one file with the help of some replaceVars() hacks.
* Moved all primary key definitions to the field definition, moved all indexes to CREATE INDEX statements, for best SQLite compatibility.
* Made all autoincrement fields primary keys, as required by SQLite.
* Removed meaningless buzzword from the category table comment
* tables.sql: s/'0'/0/
* In SQLite the index names have DB scope. Renamed archive.usertext_timestamp, user_newtalk.user_id, user_newtalk.user_ip
* SQLite does not support UPDATE with LIMIT by default. Removed all instances I could find.
* Made query errors work in the installer.
* Fixed DatabaseSqlite::lastErrno(), made SQLITE_SCHEMA errors automatically reissue the query as suggested on sqlite-users. Otherwise upgrade breaks.
* Removed miscellaneous status information from getServerVersion(), that's not the place to put it

config/index.php
includes/Exception.php
includes/SiteStats.php
includes/db/Database.php
includes/db/DatabaseSqlite.php
maintenance/sqlite/README [new file with mode: 0644]
maintenance/sqlite/archives/initial-indexes.sql [new file with mode: 0644]
maintenance/sqlite/tables.sql [deleted file]
maintenance/tables.sql
maintenance/updaters.inc

index 915b8a3..bec5b66 100644 (file)
@@ -47,11 +47,13 @@ require_once( "$IP/includes/Namespace.php" );
 require_once( "$IP/includes/ProfilerStub.php" );
 require_once( "$IP/includes/GlobalFunctions.php" );
 require_once( "$IP/includes/Hooks.php" );
+require_once( "$IP/includes/Exception.php" );
 
 # If we get an exception, the user needs to know
 # all the details
 $wgShowExceptionDetails = true;
-
+$wgShowSQLErrors = true;
+wfInstallExceptionHandler();
 ## Databases we support:
 
 $ourdb = array();
index eb71598..b71a07b 100644 (file)
@@ -161,23 +161,26 @@ class MWException extends Exception {
                        if( $hookResult = $this->runHooks( get_class( $this ) . "Raw" ) ) {
                                die( $hookResult );
                        }
-                       echo $this->htmlHeader();
-                       echo $this->getHTML();
-                       echo $this->htmlFooter();
+                       if ( defined( 'MEDIAWIKI_INSTALL' ) ) {
+                               echo $this->getHTML();
+                       } else {
+                               echo $this->htmlHeader();
+                               echo $this->getHTML();
+                               echo $this->htmlFooter();
+                       }
                }
        }
 
        /**
         * Output a report about the exception and takes care of formatting.
-        * It will be either HTML or plain text based on $wgCommandLineMode.
+        * It will be either HTML or plain text based on isCommandLine().
         */
        function report() {
-               global $wgCommandLineMode;
                $log = $this->getLogMessage();
                if ( $log ) {
                        wfDebugLog( 'exception', $log );
                }
-               if ( $wgCommandLineMode ) {
+               if ( self::isCommandLine() ) {
                        wfPrintError( $this->getText() );
                } else {
                        $this->reportHTML();
@@ -214,6 +217,10 @@ class MWException extends Exception {
        function htmlFooter() {
                echo "</body></html>";
        }
+
+       static function isCommandLine() {
+               return !empty( $GLOBALS['wgCommandLineMode'] ) && !defined( 'MEDIAWIKI_INSTALL' );
+       }
 }
 
 /**
@@ -264,6 +271,7 @@ function wfInstallExceptionHandler() {
  * Report an exception to the user
  */
 function wfReportException( Exception $e ) {
+       $cmdLine = MWException::isCommandLine();
         if ( $e instanceof MWException ) {
                 try {
                         $e->report();
@@ -276,7 +284,7 @@ function wfReportException( Exception $e ) {
                         "\n\nException caught inside exception handler: " .
                         $e2->__toString() . "\n";
 
-                        if ( !empty( $GLOBALS['wgCommandLineMode'] ) ) {
+                        if ( $cmdLine ) {
                                 wfPrintError( $message );
                         } else {
                                 echo nl2br( htmlspecialchars( $message ) ). "\n";
@@ -288,7 +296,7 @@ function wfReportException( Exception $e ) {
                 if ( $GLOBALS['wgShowExceptionDetails'] ) {
                         $message .= "\n" . $e->getTraceAsString() ."\n";
                 }
-                if ( !empty( $GLOBALS['wgCommandLineMode'] ) ) {
+                if ( $cmdLine ) {
                         wfPrintError( $message );
                 } else {
                         echo nl2br( htmlspecialchars( $message ) ). "\n";
@@ -298,7 +306,7 @@ function wfReportException( Exception $e ) {
 
 /**
  * Print a message, if possible to STDERR.
- * Use this in command line mode only (see wgCommandLineMode)
+ * Use this in command line mode only (see isCommandLine)
  */
 function wfPrintError( $message ) {
        #NOTE: STDERR may not be available, especially if php-cgi is used from the command line (bug #15602).
index ab0caa7..9427536 100644 (file)
@@ -222,7 +222,7 @@ class SiteStatsUpdate {
 
                if ( $updates ) {
                        $site_stats = $dbw->tableName( 'site_stats' );
-                       $sql = $dbw->limitResultForUpdate("UPDATE $site_stats SET $updates", 1);
+                       $sql = "UPDATE $site_stats SET $updates";
 
                        # Need a separate transaction because this a global lock
                        $dbw->begin();
@@ -240,7 +240,7 @@ class SiteStatsUpdate {
                        __METHOD__ );
                $dbw->update( 'site_stats', 
                        array( 'ss_active_users' => intval($activeUsers) ),
-                       array( 'ss_row_id' => 1 ), __METHOD__, array( 'LIMIT' => 1 )
+                       array( 'ss_row_id' => 1 ), __METHOD__
                );
        }
 }
index 84b8864..b1442e7 100644 (file)
@@ -570,7 +570,7 @@ class Database {
                $ret = $this->doQuery( $commentedSql );
 
                # Try reconnecting if the connection was lost
-               if ( false === $ret && ( $this->lastErrno() == 2013 || $this->lastErrno() == 2006 ) ) {
+               if ( false === $ret && $this->wasErrorReissuable() ) {
                        # Transaction is gone, like it or not
                        $this->mTrxLevel = 0;
                        wfDebug( "Connection lost, reconnecting...\n" );
@@ -1816,6 +1816,14 @@ class Database {
                return $this->lastErrno() == 1213;
        }
 
+       /**
+        * Determines if the last query error was something that should be dealt 
+        * with by pinging the connection and reissuing the query
+        */
+       function wasErrorReissuable() {
+               return $this->lastErrno() == 2013 || $this->lastErrno() == 2006;
+       }
+
        /**
         * Perform a deadlock-prone transaction.
         *
index dfc506c..f22f25c 100644 (file)
@@ -15,6 +15,7 @@ class DatabaseSqlite extends Database {
        var $mAffectedRows;
        var $mLastResult;
        var $mDatabaseFile;
+       var $mName;
 
        /**
         * Constructor
@@ -26,6 +27,7 @@ class DatabaseSqlite extends Database {
                $this->mFailFunction = $failFunction;
                $this->mFlags = $flags;
                $this->mDatabaseFile = "$wgSQLiteDataDir/$dbName.sqlite";
+               $this->mName = $dbName;
                $this->open($server, $user, $password, $dbName);
        }
 
@@ -89,8 +91,9 @@ class DatabaseSqlite extends Database {
         */
        function doQuery($sql) {
                $res = $this->mConn->query($sql);
-               if ($res === false) $this->reportQueryError($this->lastError(),$this->lastErrno(),$sql,__FUNCTION__);
-               else {
+               if ($res === false) {
+                       return false;
+               } else {
                        $r = $res instanceof ResultWrapper ? $res->result : $res;
                        $this->mAffectedRows = $r->rowCount();
                        $res = new ResultWrapper($this,$r->fetchAll());
@@ -173,8 +176,12 @@ class DatabaseSqlite extends Database {
        }
 
        function lastErrno() {
-               if (!is_object($this->mConn)) return "Cannot return last error, no db connection";
-               return $this->mConn->errorCode();
+               if (!is_object($this->mConn)) {
+                       return "Cannot return last error, no db connection";
+               } else {
+                       $info = $this->mConn->errorInfo();
+                       return $info[1];
+               }
        }
 
        function affectedRows() {
@@ -183,14 +190,43 @@ class DatabaseSqlite extends Database {
 
        /**
         * Returns information about an index
+        * Returns false if the index does not exist
         * - if errors are explicitly ignored, returns NULL on failure
         */
        function indexInfo($table, $index, $fname = 'Database::indexExists') {
-               return false;
+               $sql = 'PRAGMA index_info(' . $this->addQuotes( $index ) . ')';
+               $res = $this->query( $sql, $fname );
+               if ( !$res ) {
+                       return null;
+               }
+               if ( $res->numRows() == 0 ) {
+                       return false;
+               }
+               $info = array();
+               foreach ( $res as $row ) {
+                       $info[] = $row->name;
+               }
+               return $info;
        }
 
        function indexUnique($table, $index, $fname = 'Database::indexUnique') {
-               return false;
+               $row = $this->selectRow( 'sqlite_master', '*', 
+                       array(
+                               'type' => 'index',
+                               'name' => $index,
+                       ), $fname );
+               if ( !$row || !isset( $row->sql ) ) {
+                       return null;
+               }
+
+               // $row->sql will be of the form CREATE [UNIQUE] INDEX ...
+               $indexPos = strpos( $row->sql, 'INDEX' );
+               if ( $indexPos === false ) {
+                       return null;
+               }
+               $firstPart = substr( $row->sql, 0, $indexPos );
+               $options = explode( ' ', $firstPart );
+               return in_array( 'UNIQUE', $options );
        }
 
        /**
@@ -228,7 +264,10 @@ class DatabaseSqlite extends Database {
                return '';
        }
 
-       # Returns the size of a text field, or -1 for "unlimited"
+       /**
+        * Returns the size of a text field, or -1 for "unlimited"
+        * In SQLite this is SQLITE_MAX_LENGTH, by default 1GB. No way to query it though.
+        */
        function textFieldSize($table, $field) {
                return -1;
        }
@@ -252,6 +291,10 @@ class DatabaseSqlite extends Database {
                return $this->lastErrno() == SQLITE_BUSY;
        }
 
+       function wasErrorReissuable() {
+               return $this->lastErrno() ==  SQLITE_SCHEMA;
+       }
+
        /**
         * @return string wikitext of a link to the server software's web site
         */
@@ -265,17 +308,32 @@ class DatabaseSqlite extends Database {
        function getServerVersion() {
                global $wgContLang;
                $ver = $this->mConn->getAttribute(PDO::ATTR_SERVER_VERSION);
-               $size = $wgContLang->formatSize(filesize($this->mDatabaseFile));
-               $file = basename($this->mDatabaseFile);
-               return $ver." ($file: $size)";
+               return $ver;
        }
 
        /**
         * Query whether a given column exists in the mediawiki schema
         */
-       function fieldExists($table, $field) { return true; }
+       function fieldExists($table, $field) {
+               $info = $this->fieldInfo( $table, $field );
+               return (bool)$info;
+       }
 
-       function fieldInfo($table, $field) { return SQLiteField::fromText($this, $table, $field); }
+       /**
+        * Get information about a given field
+        * Returns false if the field does not exist.
+        */
+       function fieldInfo($table, $field) {
+               $tableName = $this->tableName( $table );
+               $sql = 'PRAGMA table_info(' . $this->addQuotes( $tableName ) . ')';
+               $res = $this->query( $sql, __METHOD__ );
+               foreach ( $res as $row ) {
+                       if ( $row->name == $field ) {
+                               return new SQLiteField( $row, $tableName );
+                       }
+               }
+               return false;
+       }
 
        function begin() {
                if ($this->mTrxLevel == 1) $this->commit();
@@ -296,7 +354,7 @@ class DatabaseSqlite extends Database {
        }
 
        function limitResultForUpdate($sql, $num) {
-               return $sql;
+               return $this->limitResult( $sql, $num );
        }
 
        function strencode($s) {
@@ -325,17 +383,25 @@ class DatabaseSqlite extends Database {
        function quote_ident($s) { return $s; }
 
        /**
-        * For now, does nothing
+        * Not possible in SQLite
+        * We have ATTACH_DATABASE but that requires database selectors before the 
+        * table names and in any case is really a different concept to MySQL's USE
         */
-       function selectDB($db) { return true; }
+       function selectDB($db) {
+               if ( $db != $this->mName ) {
+                       throw new MWException( 'selectDB is not implemented in SQLite' );
+               }
+       }
 
        /**
         * not done
         */
        public function setTimeout($timeout) { return; }
 
+       /**
+        * No-op for a non-networked database
+        */
        function ping() {
-               wfDebug("Function ping() not written for SQLite yet");
                return true;
        }
 
@@ -353,39 +419,16 @@ class DatabaseSqlite extends Database {
        public function setup_database() {
                global $IP,$wgSQLiteDataDir,$wgDBTableOptions;
                $wgDBTableOptions = '';
-               $mysql_tmpl  = "$IP/maintenance/tables.sql";
-               $mysql_iw    = "$IP/maintenance/interwiki.sql";
-               $sqlite_tmpl = "$IP/maintenance/sqlite/tables.sql";
-
-               # Make an SQLite template file if it doesn't exist (based on the same one MySQL uses to create a new wiki db)
-               if (!file_exists($sqlite_tmpl)) {
-                       $sql = file_get_contents($mysql_tmpl);
-                       $sql = preg_replace('/^\s*--.*?$/m','',$sql); # strip comments
-                       $sql = preg_replace('/^\s*(UNIQUE)?\s*(PRIMARY)?\s*KEY.+?$/m','',$sql);
-                       $sql = preg_replace('/^\s*(UNIQUE )?INDEX.+?$/m','',$sql); # These indexes should be created with a CREATE INDEX query
-                       $sql = preg_replace('/^\s*FULLTEXT.+?$/m','',$sql);        # Full text indexes
-                       $sql = preg_replace('/ENUM\(.+?\)/','TEXT',$sql); # Make ENUM's into TEXT's
-                       $sql = preg_replace('/binary\(\d+\)/','BLOB',$sql);
-                       $sql = preg_replace('/(TYPE|MAX_ROWS|AVG_ROW_LENGTH)=\w+/','',$sql);
-                       $sql = preg_replace('/,\s*\)/s',')',$sql); # removing previous items may leave a trailing comma
-                       $sql = str_replace('binary','',$sql);
-                       $sql = str_replace('auto_increment','PRIMARY KEY AUTOINCREMENT',$sql);
-                       $sql = str_replace(' unsigned','',$sql);
-                       $sql = str_replace(' int ',' INTEGER ',$sql);
-                       $sql = str_replace('NOT NULL','',$sql);
-
-                       # Tidy up and write file
-                       $sql = preg_replace('/^\s*^/m','',$sql); # Remove empty lines
-                       $sql = preg_replace('/;$/m',";\n",$sql); # Separate each statement with an empty line
-                       file_put_contents($sqlite_tmpl,$sql);
-               }
 
-               # Parse the SQLite template replacing inline variables such as /*$wgDBprefix*/
-               $err = $this->sourceFile($sqlite_tmpl);
-               if ($err !== true) $this->reportQueryError($err,0,$sql,__FUNCTION__);
+               # Process common MySQL/SQLite table definitions
+               $err = $this->sourceFile( "$IP/maintenance/tables.sql" );
+               if ($err !== true) {
+                       $this->reportQueryError($err,0,$sql,__FUNCTION__);
+                       exit( 1 );
+               }
 
                # Use DatabasePostgres's code to populate interwiki from MySQL template
-               $f = fopen($mysql_iw,'r');
+               $f = fopen("$IP/maintenance/interwiki.sql",'r');
                if ($f == false) dieout("<li>Could not find the interwiki.sql file");
                $sql = "INSERT INTO interwiki(iw_prefix,iw_url,iw_local) VALUES ";
                while (!feof($f)) {
@@ -418,22 +461,80 @@ class DatabaseSqlite extends Database {
                $function = array_shift( $args );
                return call_user_func_array( $function, $args );
        }
-}
+
+       protected function replaceVars( $s ) {
+               $s = parent::replaceVars( $s );
+               if ( preg_match( '/^\s*CREATE TABLE/i', $s ) ) {
+                       // CREATE TABLE hacks to allow schema file sharing with MySQL
+                       
+                       // binary/varbinary column type -> blob
+                       $s = preg_replace( '/\b(var)?binary(\(\d+\))/i', 'blob\1', $s );
+                       // no such thing as unsigned
+                       $s = preg_replace( '/\bunsigned\b/i', '', $s );
+                       // INT -> INTEGER for primary keys
+                       $s = preg_replacE( '/\bint\b/i', 'integer', $s );
+                       // No ENUM type
+                       $s = preg_replace( '/enum\([^)]*\)/i', 'blob', $s );
+                       // binary collation type -> nothing
+                       $s = preg_replace( '/\bbinary\b/i', '', $s );
+                       // auto_increment -> autoincrement
+                       $s = preg_replace( '/\bauto_increment\b/i', 'autoincrement', $s );
+                       // No explicit options
+                       $s = preg_replace( '/\)[^)]*$/', ')', $s );
+               } elseif ( preg_match( '/^\s*CREATE (\s*(?:UNIQUE|FULLTEXT)\s+)?INDEX/i', $s ) ) {
+                       // No truncated indexes
+                       $s = preg_replace( '/\(\d+\)/', '', $s );
+                       // No FULLTEXT
+                       $s = preg_replace( '/\bfulltext\b/i', '', $s );
+               }
+               return $s;
+       }
+
+} // end DatabaseSqlite class
 
 /**
  * @ingroup Database
  */
-class SQLiteField extends MySQLField {
+class SQLiteField {
+       private $info, $tableName;
+       function __construct( $info, $tableName ) {
+               $this->info = $info;
+               $this->tableName = $tableName;
+       }
 
-       function __construct() {
+       function name() {
+               return $this->info->name;
        }
 
-       static function fromText($db, $table, $field) {
-               $n = new SQLiteField;
-               $n->name = $field;
-               $n->tablename = $table;
-               return $n;
+       function tableName() {
+               return $this->tableName;
        }
 
-} // end DatabaseSqlite class
+       function defaultValue() {
+               if ( is_string( $this->info->dflt_value ) ) {
+                       // Typically quoted
+                       if ( preg_match( '/^\'(.*)\'$', $this->info->dflt_value ) ) {
+                               return str_replace( "''", "'", $this->info->dflt_value );
+                       }
+               }
+               return $this->info->dflt_value;
+       }
+
+       function maxLength() {
+               return -1;
+       }
+
+       function nullable() {
+               // SQLite dynamic types are always nullable
+               return true;
+       }
+
+       # isKey(),  isMultipleKey() not implemented, MySQL-specific concept. 
+       # Suggest removal from base class [TS]
+       
+       function type() {
+               return $this->info->type;
+       }
+
+} // end SQLiteField
 
diff --git a/maintenance/sqlite/README b/maintenance/sqlite/README
new file mode 100644 (file)
index 0000000..b8a4555
--- /dev/null
@@ -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 (file)
index 0000000..5c0305d
--- /dev/null
@@ -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 user_name ON /*_*/user_tmp (user_name);
+CREATE INDEX 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 ug_user_group ON /*_*/user_groups_tmp (ug_user,ug_group);
+CREATE INDEX 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 name_title ON /*_*/page_tmp (page_namespace,page_title);
+CREATE INDEX page_random ON /*_*/page_tmp (page_random);
+CREATE INDEX 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 rev_page_id ON /*_*/revision_tmp (rev_page, rev_id);
+CREATE INDEX rev_timestamp ON /*_*/revision_tmp (rev_timestamp);
+CREATE INDEX page_timestamp ON /*_*/revision_tmp (rev_page,rev_timestamp);
+CREATE INDEX user_timestamp ON /*_*/revision_tmp (rev_user,rev_timestamp);
+CREATE INDEX 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 pl_from ON /*_*/pagelinks_tmp (pl_from,pl_namespace,pl_title);
+CREATE INDEX 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 tl_from ON /*_*/templatelinks_tmp (tl_from,tl_namespace,tl_title);
+CREATE INDEX 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 il_from ON /*_*/imagelinks_tmp (il_from,il_to);
+CREATE INDEX 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 cl_from ON /*_*/categorylinks_tmp (cl_from,cl_to);
+CREATE INDEX cl_sortkey ON /*_*/categorylinks_tmp (cl_to,cl_sortkey,cl_from);
+CREATE INDEX 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 cat_title ON /*_*/category_tmp (cat_title);
+CREATE INDEX 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 ll_from ON /*_*/langlinks_tmp (ll_from, ll_lang);
+CREATE INDEX 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 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 ipb_address ON /*_*/ipblocks_tmp (ipb_address(255), ipb_user, ipb_auto, ipb_anon_only);
+CREATE INDEX ipb_user ON /*_*/ipblocks_tmp (ipb_user);
+CREATE INDEX ipb_range ON /*_*/ipblocks_tmp (ipb_range_start(8), ipb_range_end(8));
+CREATE INDEX ipb_timestamp ON /*_*/ipblocks_tmp (ipb_timestamp);
+CREATE INDEX 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 wl_user_namespace_title ON /*_*/watchlist_tmp (wl_user, wl_namespace, wl_title);
+CREATE INDEX 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 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 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 pr_pagetype ON /*_*/page_restrictions_tmp (pr_page,pr_type);
+CREATE UNIQUE INDEX pr_typelevel ON /*_*/page_restrictions_tmp (pr_type,pr_level);
+CREATE UNIQUE INDEX pr_level ON /*_*/page_restrictions_tmp (pr_level);
+CREATE UNIQUE INDEX 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 pt_namespace_title ON /*_*/protected_titles_tmp (pt_namespace,pt_title);
+CREATE INDEX 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 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 si_page ON /*_*/searchindex (si_page);
+CREATE INDEX si_title ON /*_*/searchindex (si_title);
+CREATE INDEX 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 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 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 un_user_id ON /*_*/user_newtalk (user_id);
+CREATE INDEX un_user_ip ON /*_*/user_newtalk (user_ip);
+CREATE INDEX name_title_timestamp ON /*_*/archive (ar_namespace,ar_title,ar_timestamp);
+CREATE INDEX ar_usertext_timestamp ON /*_*/archive (ar_user_text,ar_timestamp);
+CREATE INDEX el_from ON /*_*/externallinks (el_from, el_to(40));
+CREATE INDEX el_to ON /*_*/externallinks (el_to(60), el_from);
+CREATE INDEX el_index ON /*_*/externallinks (el_index(60));
+CREATE INDEX img_usertext_timestamp ON /*_*/image (img_user_text,img_timestamp);
+CREATE INDEX img_size ON /*_*/image (img_size);
+CREATE INDEX img_timestamp ON /*_*/image (img_timestamp);
+CREATE INDEX img_sha1 ON /*_*/image (img_sha1);
+CREATE INDEX oi_usertext_timestamp ON /*_*/oldimage (oi_user_text,oi_timestamp);
+CREATE INDEX oi_name_timestamp ON /*_*/oldimage (oi_name,oi_timestamp);
+CREATE INDEX oi_name_archive_name ON /*_*/oldimage (oi_name,oi_archive_name(14));
+CREATE INDEX oi_sha1 ON /*_*/oldimage (oi_sha1);
+CREATE INDEX fa_name ON /*_*/filearchive (fa_name, fa_timestamp);
+CREATE INDEX fa_group_key ON /*_*/filearchive (fa_storage_group, fa_storage_key);
+CREATE INDEX fa_deleted_timestamp ON /*_*/filearchive (fa_deleted_timestamp);
+CREATE INDEX fa_user_timestamp ON /*_*/filearchive (fa_user_text,fa_timestamp);
+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 INDEX rc_ns_usertext ON /*_*/recentchanges (rc_namespace, rc_user_text);
+CREATE INDEX rc_user_text ON /*_*/recentchanges (rc_user_text, rc_timestamp);
+CREATE INDEX qc_type_value ON /*_*/querycache (qc_type,qc_value);
+CREATE INDEX oc_exptime ON /*_*/objectcache (exptime);
+CREATE INDEX type_time ON /*_*/logging (log_type, log_timestamp);
+CREATE INDEX user_time ON /*_*/logging (log_user, log_timestamp);
+CREATE INDEX page_time ON /*_*/logging (log_namespace, log_title, log_timestamp);
+CREATE INDEX times ON /*_*/logging (log_timestamp);
+CREATE INDEX tb_page ON /*_*/trackbacks (tb_page);
+CREATE INDEX job_cmd_namespace_title ON /*_*/job (job_cmd, job_namespace, job_title);
+CREATE INDEX rd_ns_title ON /*_*/redirect (rd_namespace,rd_title,rd_from);
+CREATE INDEX qcc_type ON /*_*/querycachetwo (qcc_type,qcc_value);
+CREATE INDEX qcc_title ON /*_*/querycachetwo (qcc_type,qcc_namespace,qcc_title);
+CREATE INDEX 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 (file)
index 13e2a19..0000000
+++ /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*/;
-
-
index 28f496e..d5559f7 100644 (file)
@@ -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 user_name ON /*_*/user (user_name);
+CREATE INDEX 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 ug_user_group ON /*_*/user_groups (ug_user,ug_group);
+CREATE INDEX 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 un_user_id ON /*_*/user_newtalk (user_id);
+CREATE INDEX 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 name_title ON /*_*/page (page_namespace,page_title);
+CREATE INDEX page_random ON /*_*/page (page_random);
+CREATE INDEX 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 rev_page_id ON /*_*/revision (rev_page, rev_id);
+CREATE INDEX rev_timestamp ON /*_*/revision (rev_timestamp);
+CREATE INDEX page_timestamp ON /*_*/revision (rev_page,rev_timestamp);
+CREATE INDEX user_timestamp ON /*_*/revision (rev_user,rev_timestamp);
+CREATE INDEX 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 name_title_timestamp ON /*_*/archive (ar_namespace,ar_title,ar_timestamp);
+CREATE INDEX 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 pl_from ON /*_*/pagelinks (pl_from,pl_namespace,pl_title);
+CREATE INDEX pl_namespace_title 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 tl_from ON /*_*/templatelinks (tl_from,tl_namespace,tl_title);
+CREATE INDEX tl_namespace_title 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 il_from ON /*_*/imagelinks (il_from,il_to);
+CREATE INDEX 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 cl_from ON /*_*/categorylinks (cl_from,cl_to);
+
+-- We always sort within a given category...
+CREATE INDEX cl_sortkey ON /*_*/categorylinks (cl_to,cl_sortkey,cl_from);
+
+-- Not really used?
+CREATE INDEX 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 cat_title ON /*_*/category (cat_title);
+
+-- For Special:Mostlinkedcategories
+CREATE INDEX 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 el_from ON /*_*/externallinks (el_from, el_to(40));
+CREATE INDEX el_to ON /*_*/externallinks (el_to(60), el_from);
+CREATE INDEX 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 ll_from ON /*_*/langlinks (ll_from, ll_lang);
+CREATE INDEX ll_lang_title 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,11 +600,12 @@ 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 ss_row_id ON /*_*/site_stats (ss_row_id);
 
-) /*$wgDBTableOptions*/;
 
 --
 -- Stores an ID for every time any article is visited;
@@ -617,7 +614,7 @@ CREATE TABLE /*$wgDBprefix*/site_stats (
 -- in the page table updated for the all 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 ipb_address ON /*_*/ipblocks (ipb_address(255), ipb_user, ipb_auto, ipb_anon_only);
+
+CREATE INDEX ipb_user ON /*_*/ipblocks (ipb_user);
+CREATE INDEX ipb_range ON /*_*/ipblocks (ipb_range_start(8), ipb_range_end(8));
+CREATE INDEX ipb_timestamp ON /*_*/ipblocks (ipb_timestamp);
+CREATE INDEX 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 img_usertext_timestamp ON /*_*/image (img_user_text,img_timestamp);
+-- Used by Special:Imagelist for sort-by-size
+CREATE INDEX img_size ON /*_*/image (img_size);
+-- Used by Special:Newimages and Special:Imagelist
+CREATE INDEX img_timestamp ON /*_*/image (img_timestamp);
+-- Used in API and duplicate search
+CREATE INDEX 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 oi_usertext_timestamp ON /*_*/oldimage (oi_user_text,oi_timestamp);
+CREATE INDEX oi_name_timestamp ON /*_*/oldimage (oi_name,oi_timestamp);
+-- oi_archive_name truncated to 14 to avoid key length overflow
+CREATE INDEX oi_name_archive_name ON /*_*/oldimage (oi_name,oi_archive_name(14));
+CREATE INDEX 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 fa_name ON /*_*/filearchive (fa_name, fa_timestamp);
+-- pick out dupe files
+CREATE INDEX fa_group_key ON /*_*/filearchive (fa_storage_group, fa_storage_key);
+-- sort by deletion time
+CREATE INDEX fa_deleted_timestamp ON /*_*/filearchive (fa_deleted_timestamp);
+-- sort by uploader
+CREATE INDEX 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 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 INDEX rc_ns_usertext ON /*_*/recentchanges (rc_namespace, rc_user_text);
+CREATE INDEX 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 wl_user_namespace_title ON /*_*/watchlist (wl_user, wl_namespace, wl_title);
+CREATE INDEX 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 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 si_page ON /*_*/searchindex (si_page);
+CREATE FULLTEXT INDEX si_title ON /*_*/searchindex (si_title);
+CREATE FULLTEXT INDEX 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 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 qc_type_value 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 oc_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 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 type_time ON /*_*/logging (log_type, log_timestamp);
+CREATE INDEX user_time ON /*_*/logging (log_user, log_timestamp);
+CREATE INDEX page_time ON /*_*/logging (log_namespace, log_title, log_timestamp);
+CREATE INDEX 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 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 job_cmd_namespace_title 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 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 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 qcc_type ON /*_*/querycachetwo (qcc_type,qcc_value);
+CREATE INDEX qcc_title ON /*_*/querycachetwo (qcc_type,qcc_namespace,qcc_title);
+CREATE INDEX 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,43 @@ 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 pr_pagetype ON /*_*/page_restrictions (pr_page,pr_type);
+CREATE UNIQUE INDEX pr_typelevel ON /*_*/page_restrictions (pr_type,pr_level);
+CREATE UNIQUE INDEX pr_level ON /*_*/page_restrictions (pr_level);
+CREATE UNIQUE INDEX 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 pt_namespace_title ON /*_*/protected_titles (pt_namespace,pt_title);
+CREATE INDEX 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 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*/;
 
 -- vim: sw=2 sts=2 et
index a49c875..dade790 100644 (file)
@@ -16,138 +16,148 @@ 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( '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' ),
+       ),
+
+       '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' ),
+       ),
 );
 
 
@@ -1070,11 +1080,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!
@@ -1112,10 +1124,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";
        }
 }
@@ -1243,6 +1254,23 @@ function update_password_format() {
        echo "done\n";
 }
 
+function sqlite_initial_indexes() {
+       global $wgDatabase;
+       if ( update_row_exists( 'initial_indexes' ) ) {
+               echo "...have initial indexes\n";
+               return;
+       }
+       echo "Adding initial indexes...";
+       $wgDatabase->sourceFile( archive( 'initial-indexes.sql' ) );
+       echo "done\n";
+}
+
+
+/***********************************************************************
+ * Start PG crap
+ * TODO: merge with above
+ ***********************************************************************/
+
 function
 pg_describe_table($table)
 {