From 4124558d7b40df818337f1d7eeae10c9ee9688e2 Mon Sep 17 00:00:00 2001 From: Tim Starling Date: Thu, 15 Jan 2009 06:56:58 +0000 Subject: [PATCH] For backport to 1.14. * 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 | 4 +- includes/Exception.php | 26 +- includes/SiteStats.php | 4 +- includes/db/Database.php | 10 +- includes/db/DatabaseSqlite.php | 211 ++++-- maintenance/sqlite/README | 12 + .../sqlite/archives/initial-indexes.sql | 417 ++++++++++++ maintenance/sqlite/tables.sql | 340 ---------- maintenance/tables.sql | 625 +++++++++--------- maintenance/updaters.inc | 308 +++++---- 10 files changed, 1092 insertions(+), 865 deletions(-) create mode 100644 maintenance/sqlite/README create mode 100644 maintenance/sqlite/archives/initial-indexes.sql delete mode 100644 maintenance/sqlite/tables.sql diff --git a/config/index.php b/config/index.php index 915b8a3589..bec5b66908 100644 --- a/config/index.php +++ b/config/index.php @@ -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(); diff --git a/includes/Exception.php b/includes/Exception.php index eb7159861c..b71a07b87a 100644 --- a/includes/Exception.php +++ b/includes/Exception.php @@ -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 ""; } + + 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). diff --git a/includes/SiteStats.php b/includes/SiteStats.php index ab0caa7e04..9427536f7e 100644 --- a/includes/SiteStats.php +++ b/includes/SiteStats.php @@ -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__ ); } } diff --git a/includes/db/Database.php b/includes/db/Database.php index 84b886435a..b1442e7d55 100644 --- a/includes/db/Database.php +++ b/includes/db/Database.php @@ -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. * diff --git a/includes/db/DatabaseSqlite.php b/includes/db/DatabaseSqlite.php index dfc506ccd1..f22f25c2c3 100644 --- a/includes/db/DatabaseSqlite.php +++ b/includes/db/DatabaseSqlite.php @@ -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("
  • 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 index 0000000000..b8a4555380 --- /dev/null +++ b/maintenance/sqlite/README @@ -0,0 +1,12 @@ +SQLite shares the MySQL schema file at maintenance/tables.sql, with a set of +compatibility regexes to convert MySQL syntax to SQLite syntax: + +* BINARY() and VARBINARY() fields are converted to BLOB +* the UNSIGNED modifier is removed +* "INT" fields are converted to "INTEGER" +* ENUM is converted to BLOB +* the BINARY collation modifier is removed +* AUTO_INCREMENT is converted to AUTOINCREMENT +* Any table options are removed +* Truncated indexes are upgraded to full-width indexes +* FULLTEXT indexes are converted to ordinary indexes diff --git a/maintenance/sqlite/archives/initial-indexes.sql b/maintenance/sqlite/archives/initial-indexes.sql new file mode 100644 index 0000000000..5c0305d4b6 --- /dev/null +++ b/maintenance/sqlite/archives/initial-indexes.sql @@ -0,0 +1,417 @@ +-- Correct for the total lack of indexes in the MW 1.13 SQLite schema +-- +-- Unique indexes need to be handled with INSERT SELECT since just running +-- the CREATE INDEX statement will fail if there are duplicate values. +-- +-- Ignore duplicates, several tables will have them (e.g. bug 16966) but in +-- most cases it's harmless to discard them. We'll keep the old tables with +-- duplicates in so that the user can recover them in case of disaster. + +-------------------------------------------------------------------------------- +-- Drop temporary tables from aborted runs +-------------------------------------------------------------------------------- + +DROP TABLE IF EXISTS /*_*/user_tmp; +DROP TABLE IF EXISTS /*_*/user_groups_tmp; +DROP TABLE IF EXISTS /*_*/page_tmp; +DROP TABLE IF EXISTS /*_*/revision_tmp; +DROP TABLE IF EXISTS /*_*/pagelinks_tmp; +DROP TABLE IF EXISTS /*_*/templatelinks_tmp; +DROP TABLE IF EXISTS /*_*/imagelinks_tmp; +DROP TABLE IF EXISTS /*_*/categorylinks_tmp; +DROP TABLE IF EXISTS /*_*/category_tmp; +DROP TABLE IF EXISTS /*_*/langlinks_tmp; +DROP TABLE IF EXISTS /*_*/site_stats_tmp; +DROP TABLE IF EXISTS /*_*/ipblocks_tmp; +DROP TABLE IF EXISTS /*_*/watchlist_tmp; +DROP TABLE IF EXISTS /*_*/math_tmp; +DROP TABLE IF EXISTS /*_*/interwiki_tmp; +DROP TABLE IF EXISTS /*_*/page_restrictions_tmp; +DROP TABLE IF EXISTS /*_*/protected_titles_tmp; +DROP TABLE IF EXISTS /*_*/page_props_tmp; + +-------------------------------------------------------------------------------- +-- Create new tables +-------------------------------------------------------------------------------- + +CREATE TABLE /*_*/user_tmp ( + user_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT, + user_name varchar(255) binary NOT NULL default '', + user_real_name varchar(255) binary NOT NULL default '', + user_password tinyblob NOT NULL, + user_newpassword tinyblob NOT NULL, + user_newpass_time binary(14), + user_email tinytext NOT NULL, + user_options blob NOT NULL, + user_touched binary(14) NOT NULL default '', + user_token binary(32) NOT NULL default '', + user_email_authenticated binary(14), + user_email_token binary(32), + user_email_token_expires binary(14), + user_registration binary(14), + user_editcount int +); +CREATE UNIQUE INDEX 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 index 13e2a19b8a..0000000000 --- a/maintenance/sqlite/tables.sql +++ /dev/null @@ -1,340 +0,0 @@ -CREATE TABLE /*$wgDBprefix*/user ( - user_id INTEGER PRIMARY KEY AUTOINCREMENT, - user_name varchar(255) default '', - user_real_name varchar(255) default '', - user_password tinyblob , - user_newpassword tinyblob , - user_newpass_time BLOB, - user_email tinytext , - user_options blob , - user_touched BLOB default '', - user_token BLOB default '', - user_email_authenticated BLOB, - user_email_token BLOB, - user_email_token_expires BLOB, - user_registration BLOB, - user_editcount int) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/user_groups ( - ug_user INTEGER default '0', - ug_group varBLOB default '') /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/user_newtalk ( - user_id INTEGER default '0', - user_ip varBLOB default '', - user_last_timestamp BLOB default '') /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/page ( - page_id INTEGER PRIMARY KEY AUTOINCREMENT, - page_namespace INTEGER , - page_title varchar(255) , - page_restrictions tinyblob , - page_counter bigint default '0', - page_is_redirect tinyint default '0', - page_is_new tinyint default '0', - page_random real , - page_touched BLOB default '', - page_latest INTEGER , - page_len INTEGER ) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/revision ( - rev_id INTEGER PRIMARY KEY AUTOINCREMENT, - rev_page INTEGER , - rev_text_id INTEGER , - rev_comment tinyblob , - rev_user INTEGER default '0', - rev_user_text varchar(255) default '', - rev_timestamp BLOB default '', - rev_minor_edit tinyint default '0', - rev_deleted tinyint default '0', - rev_len int, - rev_parent_id INTEGER default NULL) /*$wgDBTableOptions*/ ; - -CREATE TABLE /*$wgDBprefix*/text ( - old_id INTEGER PRIMARY KEY AUTOINCREMENT, - old_text mediumblob , - old_flags tinyblob ) /*$wgDBTableOptions*/ ; - -CREATE TABLE /*$wgDBprefix*/archive ( - ar_namespace INTEGER default '0', - ar_title varchar(255) default '', - ar_text mediumblob , - ar_comment tinyblob , - ar_user INTEGER default '0', - ar_user_text varchar(255) , - ar_timestamp BLOB default '', - ar_minor_edit tinyint default '0', - ar_flags tinyblob , - ar_rev_id int, - ar_text_id int, - ar_deleted tinyint default '0', - ar_len int, - ar_page_id int, - ar_parent_id INTEGER default NULL) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/pagelinks ( - pl_from INTEGER default '0', - pl_namespace INTEGER default '0', - pl_title varchar(255) default '') /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/templatelinks ( - tl_from INTEGER default '0', - tl_namespace INTEGER default '0', - tl_title varchar(255) default '') /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/imagelinks ( - il_from INTEGER default '0', - il_to varchar(255) default '') /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/categorylinks ( - cl_from INTEGER default '0', - cl_to varchar(255) default '', - cl_sortkey varchar(70) default '', - cl_timestamp timestamp ) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/category ( - cat_id INTEGER PRIMARY KEY AUTOINCREMENT, - cat_title varchar(255) , - cat_pages INTEGER signed default 0, - cat_subcats INTEGER signed default 0, - cat_files INTEGER signed default 0, - cat_hidden tinyint default 0) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/externallinks ( - el_from INTEGER default '0', - el_to blob , - el_index blob ) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/langlinks ( - ll_from INTEGER default '0', - ll_lang varBLOB default '', - ll_title varchar(255) default '') /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/site_stats ( - ss_row_id INTEGER , - ss_total_views bigint default '0', - ss_total_edits bigint default '0', - ss_good_articles bigint default '0', - ss_total_pages bigint default '-1', - ss_users bigint default '-1', - ss_admins INTEGER default '-1', - ss_images INTEGER default '0') /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/hitcounter ( - hc_id INTEGER -) ; - -CREATE TABLE /*$wgDBprefix*/ipblocks ( - ipb_id INTEGER PRIMARY KEY AUTOINCREMENT, - ipb_address tinyblob , - ipb_user INTEGER default '0', - ipb_by INTEGER default '0', - ipb_by_text varchar(255) default '', - ipb_reason tinyblob , - ipb_timestamp BLOB default '', - ipb_auto bool default 0, - ipb_anon_only bool default 0, - ipb_create_account bool default 1, - ipb_enable_autoblock bool default '1', - ipb_expiry varBLOB default '', - ipb_range_start tinyblob , - ipb_range_end tinyblob , - ipb_deleted bool default 0, - ipb_block_email bool default 0) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/image ( - img_name varchar(255) default '', - img_size INTEGER default '0', - img_width INTEGER default '0', - img_height INTEGER default '0', - img_metadata mediumblob , - img_bits INTEGER default '0', - img_media_type TEXT default NULL, - img_major_mime TEXT default "unknown", - img_minor_mime varBLOB default "unknown", - img_description tinyblob , - img_user INTEGER default '0', - img_user_text varchar(255) , - img_timestamp varBLOB default '', - img_sha1 varBLOB default '') /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/oldimage ( - oi_name varchar(255) default '', - oi_archive_name varchar(255) default '', - oi_size INTEGER default 0, - oi_width INTEGER default 0, - oi_height INTEGER default 0, - oi_bits INTEGER default 0, - oi_description tinyblob , - oi_user INTEGER default '0', - oi_user_text varchar(255) , - oi_timestamp BLOB default '', - oi_metadata mediumblob , - oi_media_type TEXT default NULL, - oi_major_mime TEXT default "unknown", - oi_minor_mime varBLOB default "unknown", - oi_deleted tinyint default '0', - oi_sha1 varBLOB default '') /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/filearchive ( - fa_id INTEGER PRIMARY KEY AUTOINCREMENT, - fa_name varchar(255) default '', - fa_archive_name varchar(255) default '', - fa_storage_group varBLOB, - fa_storage_key varBLOB default '', - fa_deleted_user int, - fa_deleted_timestamp BLOB default '', - fa_deleted_reason text, - fa_size INTEGER default '0', - fa_width INTEGER default '0', - fa_height INTEGER default '0', - fa_metadata mediumblob, - fa_bits INTEGER default '0', - fa_media_type TEXT default NULL, - fa_major_mime TEXT default "unknown", - fa_minor_mime varBLOB default "unknown", - fa_description tinyblob, - fa_user INTEGER default '0', - fa_user_text varchar(255) , - fa_timestamp BLOB default '', - fa_deleted tinyint default '0') /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/recentchanges ( - rc_id INTEGER PRIMARY KEY AUTOINCREMENT, - rc_timestamp varBLOB default '', - rc_cur_time varBLOB default '', - rc_user INTEGER default '0', - rc_user_text varchar(255) , - rc_namespace INTEGER default '0', - rc_title varchar(255) default '', - rc_comment varchar(255) default '', - rc_minor tinyint default '0', - rc_bot tinyint default '0', - rc_new tinyint default '0', - rc_cur_id INTEGER default '0', - rc_this_oldid INTEGER default '0', - rc_last_oldid INTEGER default '0', - rc_type tinyint default '0', - rc_moved_to_ns tinyint default '0', - rc_moved_to_title varchar(255) default '', - rc_patrolled tinyint default '0', - rc_ip varBLOB default '', - rc_old_len int, - rc_new_len int, - rc_deleted tinyint default '0', - rc_logid INTEGER default '0', - rc_log_type varBLOB NULL default NULL, - rc_log_action varBLOB NULL default NULL, - rc_params blob NULL) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/watchlist ( - wl_user INTEGER , - wl_namespace INTEGER default '0', - wl_title varchar(255) default '', - wl_notificationtimestamp varBLOB) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/math ( - math_inputhash varBLOB , - math_outputhash varBLOB , - math_html_conservativeness tinyint , - math_html text, - math_mathml text) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/searchindex ( - si_page INTEGER , - si_title varchar(255) default '', - si_text mediumtext ) ; - -CREATE TABLE /*$wgDBprefix*/interwiki ( - iw_prefix varchar(32) , - iw_url blob , - iw_local bool , - iw_trans tinyint default 0) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/querycache ( - qc_type varBLOB , - qc_value INTEGER default '0', - qc_namespace INTEGER default '0', - qc_title varchar(255) default '') /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/objectcache ( - keyname varBLOB default '', - value mediumblob, - exptime datetime) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/transcache ( - tc_url varBLOB , - tc_contents text, - tc_time INTEGER ) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/logging ( - log_id INTEGER PRIMARY KEY AUTOINCREMENT, - log_type varBLOB default '', - log_action varBLOB default '', - log_timestamp BLOB default '19700101000000', - log_user INTEGER default 0, - log_namespace INTEGER default 0, - log_title varchar(255) default '', - log_comment varchar(255) default '', - log_params blob , - log_deleted tinyint default '0') /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/trackbacks ( - tb_id INTEGER PRIMARY KEY AUTOINCREMENT, - tb_page INTEGER REFERENCES /*$wgDBprefix*/page(page_id) ON DELETE CASCADE, - tb_title varchar(255) , - tb_url blob , - tb_ex text, - tb_name varchar(255)) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/job ( - job_id INTEGER PRIMARY KEY AUTOINCREMENT, - job_cmd varBLOB default '', - job_namespace INTEGER , - job_title varchar(255) , - job_params blob ) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/querycache_info ( - qci_type varBLOB default '', - qci_timestamp BLOB default '19700101000000') /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/redirect ( - rd_from INTEGER default '0', - rd_namespace INTEGER default '0', - rd_title varchar(255) default '') /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/querycachetwo ( - qcc_type varBLOB , - qcc_value INTEGER default '0', - qcc_namespace INTEGER default '0', - qcc_title varchar(255) default '', - qcc_namespacetwo INTEGER default '0', - qcc_titletwo varchar(255) default '') /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/page_restrictions ( - pr_page INTEGER , - pr_type varBLOB , - pr_level varBLOB , - pr_cascade tinyint , - pr_user INTEGER NULL, - pr_expiry varBLOB NULL, - pr_id INTEGER PRIMARY KEY AUTOINCREMENT) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/protected_titles ( - pt_namespace INTEGER , - pt_title varchar(255) , - pt_user INTEGER , - pt_reason tinyblob, - pt_timestamp BLOB , - pt_expiry varBLOB default '', - pt_create_perm varBLOB ) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/page_props ( - pp_page INTEGER , - pp_propname varBLOB , - pp_value blob ) /*$wgDBTableOptions*/; - -CREATE TABLE /*$wgDBprefix*/updatelog ( - ul_key varchar(255) ) /*$wgDBTableOptions*/; - - diff --git a/maintenance/tables.sql b/maintenance/tables.sql index 28f496ebc4..d5559f7a85 100644 --- a/maintenance/tables.sql +++ b/maintenance/tables.sql @@ -2,6 +2,8 @@ -- This is read and executed by the install script; you should -- not have to run it by itself unless doing a manual install. +-- This is a shared schema file used for both MySQL and SQLite installs. + -- -- General notes: -- @@ -28,7 +30,7 @@ -- well. -- -- --- The /*$wgDBprefix*/ comments in this and other files are +-- The /*_*/ comments in this and other files are -- replaced with the defined table prefix by the installer -- and updater scripts. If you are installing or running -- updates manually, you will need to manually insert the @@ -48,8 +50,8 @@ -- preferences and to key tracking information in the other -- tables. -- -CREATE TABLE /*$wgDBprefix*/user ( - user_id int unsigned NOT NULL auto_increment, +CREATE TABLE /*_*/user ( + user_id int unsigned NOT NULL PRIMARY KEY AUTO_INCREMENT, -- Usernames must be unique, must not be in the form of -- an IP address. _Shouldn't_ allow slashes or case @@ -124,13 +126,12 @@ CREATE TABLE /*$wgDBprefix*/user ( -- Meant primarily for heuristic checks to give an impression of whether -- the account has been used much. -- - user_editcount int, + user_editcount int +) /*$wgDBTableOptions*/; - PRIMARY KEY user_id (user_id), - UNIQUE INDEX user_name (user_name), - INDEX (user_email_token) +CREATE UNIQUE INDEX 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 diff --git a/maintenance/updaters.inc b/maintenance/updaters.inc index a49c875797..dade790b4e 100644 --- a/maintenance/updaters.inc +++ b/maintenance/updaters.inc @@ -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) { -- 2.20.1