From: Tim Starling Date: Sun, 18 Jul 2004 08:48:43 +0000 (+0000) Subject: * Support for table name prefixes throughout the code. No support yet for converting... X-Git-Tag: 1.5.0alpha1~2649 X-Git-Url: https://git.cyclocoop.org/%7B%24www_url%7Dadmin/compta/banques/%7B%7B%20url_for%28%27admin_users%27%29%20%7D%7D?a=commitdiff_plain;h=ac549401d4ddaf655ec47cd1e66092fdc83ab30b;p=lhc%2Fweb%2Fwiklou.git * Support for table name prefixes throughout the code. No support yet for converting static SQL, which also means no installation. But it has been tested by creating the tables in the ordinary way and then renaming them * DB_WRITE now called DB_MASTER, DB_READ now called DB_SLAVE * Converted to use SQL wrapper functions instead of direct SQL in various places * Experimental method for preserving the chronological order of events when slave servers are used. Untested. * Fixes to the new post-parse existence test feature * Some.. other stuff --- diff --git a/config/index.php b/config/index.php index c97d78bede..0682cd2a4d 100644 --- a/config/index.php +++ b/config/index.php @@ -184,6 +184,7 @@ class ConfigData { posted && ( 0 == count( $errs ) ) ) { do_querycache_update(); flush(); do_objectcache_update(); flush(); do_categorylinks_update(); flush(); + do_image_name_unique_update(); flush(); if ( isTemplateInitialised() ) { print "Template namespace already initialised\n"; @@ -744,7 +746,7 @@ function writeLocalSettings( $conf ) { for ( $i=0; $i<8; $i++ ) { $proxyKey .= dechex(mt_rand(0, 0x7fffffff)); } - print "Warning: \$wgProxyKey is insecure\n"; + print "
  • Warning: \$wgProxyKey is insecure
  • \n"; } # Add slashes to strings for double quoting @@ -768,7 +770,7 @@ if ( \$wgCommandLineMode ) { if ( isset( \$_SERVER ) && array_key_exists( 'REQUEST_METHOD', \$_SERVER ) ) { die( \"This script must be run from the command line\\n\" ); } -} else { +} elseif ( !\$wgConfiguring ) { ## Compress output if the browser supports it {$zlib}if( !ini_get( 'zlib.output_compression' ) ) ob_start( 'ob_gzhandler' ); } diff --git a/includes/Article.php b/includes/Article.php index 1638141b5a..21fd21bac5 100644 --- a/includes/Article.php +++ b/includes/Article.php @@ -143,7 +143,7 @@ class Article { $index = $matches[4]; if ( $machineID == 0 ) { # Current connection - $db =& wfGetDB( DB_READ ); + $db =& wfGetDB( DB_SLAVE ); } else { # Alternate connection $db =& $wgLoadBalancer->getConnection( $machineID ); @@ -337,7 +337,7 @@ class Article { { global $wgOut, $wgMwRedir, $wgRequest; - $dbr =& wfGetDB( DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); # Query variables :P $oldid = $wgRequest->getVal( 'oldid' ); $redirect = $wgRequest->getVal( 'redirect' ); @@ -445,7 +445,7 @@ class Article { $this->mContent = false; $fname = 'Article::getContentWithout'; - $dbr =& wfGetDB( DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); if ( ! $oldid ) { # Retrieve current version $id = $this->getID(); @@ -516,7 +516,7 @@ class Article { { if ( -1 == $this->mCounter ) { $id = $this->getID(); - $dbr =& wfGetDB( DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); $this->mCounter = $dbr->getField( 'cur', 'cur_counter', "cur_id={$id}" ); } return $this->mCounter; @@ -546,7 +546,7 @@ class Article { $fname = 'Article::loadLastEdit'; - $dbr =& wfGetDB( DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); $s = $dbr->getArray( 'cur', array( 'cur_user','cur_user_text','cur_timestamp', 'cur_comment','cur_minor_edit' ), array( 'cur_id' => $this->getID() ), $fname ); @@ -598,7 +598,7 @@ class Article { $title = $this->mTitle; $contribs = array(); - $dbr = wfGetDB( DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); $oldTable = $dbr->tableName( 'old' ); $userTable = $dbr->tableName( 'user' ); $encDBkey = $dbr->strencode( $title->getDBkey() ); @@ -759,7 +759,7 @@ class Article { $won = wfInvertTimestamp( $now ); wfSeedRandom(); $rand = number_format( mt_rand() / mt_getrandmax(), 12, '.', '' ); - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); $cur_id = $dbw->nextSequenceValue( 'cur_cur_id_seq' ); @@ -903,7 +903,7 @@ class Article { else { $redir = 0; } $text = $this->preSaveTransform( $text ); - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); # Update article, but only if changed. @@ -1029,7 +1029,9 @@ class Article { global $wgMwRedir; $wgLinkCache = new LinkCache(); - + # Select for update + $wgLinkCache->forUpdate( true ); + # Get old version of link table to allow incremental link updates $wgLinkCache->preFill( $this->mTitle ); $wgLinkCache->clear(); @@ -1110,7 +1112,7 @@ class Article { $reason = $wgRequest->getText( 'wpReasonProtect' ); if ( $confirm ) { - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); $dbw->updateArray( 'cur', array( /* SET */ 'cur_touched' => wfTimestampNow(), @@ -1240,7 +1242,7 @@ class Article { # determine whether this page has earlier revisions # and insert a warning if it does # we select the text because it might be useful below - $dbr =& wfGetDB( DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); $ns = $this->mTitle->getNamespace(); $title = $this->mTitle->getDBkey(); $old = $dbr->getArray( 'old', @@ -1402,7 +1404,7 @@ class Article { $fname = 'Article::doDeleteArticle'; wfDebug( $fname."\n" ); - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); $ns = $this->mTitle->getNamespace(); $t = $this->mTitle->getDBkey(); $id = $this->mTitle->getArticleID(); @@ -1527,7 +1529,7 @@ class Article { $wgOut->readOnlyPage( $this->getContent( true ) ); return; } - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); # Enhanced rollback, marks edits rc_bot=1 $bot = $wgRequest->getBool( 'bot' ); @@ -1633,7 +1635,7 @@ class Article { wfSeedRandom(); if ( 0 == mt_rand( 0, 999 ) ) { - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); $cutoff = wfUnix2Timestamp( time() - ( 7 * 86400 ) ); $sql = "DELETE FROM recentchanges WHERE rc_timestamp < '{$cutoff}'"; $dbw->query( $sql ); @@ -1733,8 +1735,10 @@ class Article { # Loads cur_touched and returns a value indicating if it should be used function checkTouched() { + $fname = 'Article::checkTouched'; + $id = $this->getID(); - $dbr =& wfGetDB( DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); $s = $dbr->getArray( 'cur', array( 'cur_touched', 'cur_is_redirect' ), array( 'cur_id' => $id ), $fname ); if( $s !== false ) { @@ -1751,7 +1755,7 @@ class Article { $fname = 'Article::quickEdit'; wfProfileIn( $fname ); - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); $ns = $this->mTitle->getNamespace(); $dbkey = $this->mTitle->getDBkey(); $encDbKey = $dbw->strencode( $dbkey ); @@ -1810,7 +1814,7 @@ class Article { $id = intval( $id ); global $wgHitcounterUpdateFreq; - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); $curTable = $dbw->tableName( 'cur' ); $hitcounterTable = $dbw->tableName( 'hitcounter' ); $acchitsTable = $dbw->tableName( 'acchits' ); @@ -1894,31 +1898,32 @@ class Article { function info() { global $wgUser, $wgTitle, $wgOut, $wgLang, $wgAllowPageInfo; - + $fname = 'Article::info'; + if ( !$wgAllowPageInfo ) { $wgOut->errorpage( "nosuchaction", "nosuchactiontext" ); return; } + + $dbr =& wfGetDB( DB_SLAVE ); $basenamespace = $wgTitle->getNamespace() & (~1); - $cur_clause = "cur_title='".$wgTitle->getDBkey()."' AND cur_namespace=".$basenamespace; - $old_clause = "old_title='".$wgTitle->getDBkey()."' AND old_namespace=".$basenamespace; - $wl_clause = "wl_title='".$wgTitle->getDBkey()."' AND wl_namespace=".$basenamespace; + $cur_clause = array( 'cur_title' => $wgTitle->getDBkey(), 'cur_namespace' => $basenamespace ); + $old_clause = array( 'old_title' => $wgTitle->getDBkey(), 'old_namespace' => $basenamespace ); + $wl_clause = array( 'wl_title' => $wgTitle->getDBkey(), 'wl_namespace' => $basenamespace ); $fullTitle = $wgTitle->makeName($basenamespace, $wgTitle->getDBKey()); $wgOut->setPagetitle( $fullTitle ); $wgOut->setSubtitle( wfMsg( "infosubtitle" )); # first, see if the page exists at all. - $sql = "SELECT COUNT(*) FROM cur WHERE ".$cur_clause; - $exists = wfSingleQuery( $sql , DB_READ ); + $exists = $dbr->selectField( 'cur', 'COUNT(*)', $cur_clause, $fname ); if ($exists < 1) { $wgOut->addHTML( wfMsg("noarticletext") ); } else { - $sql = "SELECT COUNT(*) FROM watchlist WHERE ".$wl_clause; - $wgOut->addHTML( "" ); } } } diff --git a/includes/Block.php b/includes/Block.php index 80b102a712..427fda22ee 100644 --- a/includes/Block.php +++ b/includes/Block.php @@ -49,7 +49,7 @@ class Block $ret = false; $killed = false; - $dbr =& wfGetDB( DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); $ipblocks = $dbr->tableName( 'ipblocks' ); if ( 0 == $user && $address=="" ) { @@ -132,14 +132,14 @@ class Block # Callback with a Block object for every block /*static*/ function enumBlocks( $callback, $tag, $killExpired = true ) { - $dbr =& wfGetDB( DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); $ipblocks = $dbr->tableName( 'ipblocks' ); $sql = "SELECT * FROM $ipblocks ORDER BY ipb_timestamp DESC"; $res = $dbr->query( $sql, 'Block::enumBans' ); $block = new Block(); - while ( $row = wfFetchObject( $res ) ) { + while ( $row = $dbr->fetchObject( $res ) ) { $block->initFromRow( $row ); if ( $killExpired ) { if ( !$block->deleteIfExpired() ) { @@ -155,7 +155,7 @@ class Block function delete() { $fname = 'Block::delete'; - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); if ( $this->mAddress == "" ) { $condition = array( 'ipb_id' => $this->mId ); @@ -168,7 +168,7 @@ class Block function insert() { - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); $dbw->insertArray( 'ipblocks', array( 'ipb_address' => $this->mAddress, @@ -214,7 +214,7 @@ class Block $this->mTimestamp = wfTimestampNow(); $this->mExpiry = Block::getAutoblockExpiry( $this->mTimestamp ); - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); $dbw->updateArray( 'ipblocks', array( /* SET */ 'ipb_timestamp' => $this->mTimestamp, diff --git a/includes/Database.php b/includes/Database.php index d101ccce69..3ba89985fd 100644 --- a/includes/Database.php +++ b/includes/Database.php @@ -9,6 +9,13 @@ define( "LIST_COMMA", 0 ); define( "LIST_AND", 1 ); define( "LIST_SET", 2 ); +# Number of times to re-try an operation in case of deadlock +define( "DEADLOCK_TRIES", 4 ); +# Minimum time to wait before retry, in microseconds +define( "DEADLOCK_DELAY_MIN", 500000 ); +# Maximum time to wait before retry +define( "DEADLOCK_DELAY_MAX", 1500000 ); + class Database { #------------------------------------------------------------------------------ @@ -22,6 +29,7 @@ class Database { /* private */ var $mOut, $mDebug, $mOpened = false; /* private */ var $mFailFunction; + /* private */ var $mTablePrefix; #------------------------------------------------------------------------------ # Accessors @@ -61,9 +69,10 @@ class Database { #------------------------------------------------------------------------------ function Database( $server = false, $user = false, $password = false, $dbName = false, - $failFunction = false, $debug = false, $bufferResults = true, $ignoreErrors = false ) + $failFunction = false, $debug = false, $bufferResults = true, $ignoreErrors = false, + $tablePrefix = 'get from global' ) { - global $wgOut; + global $wgOut, $wgDBprefix; # Can't get a reference if it hasn't been set yet if ( !isset( $wgOut ) ) { $wgOut = NULL; @@ -74,6 +83,12 @@ class Database { $this->mIgnoreErrors = $ignoreErrors; $this->mDebug = $debug; $this->mBufferResults = $bufferResults; + if ( $tablePrefix == 'get from global' ) { + $this->mTablePrefix = $wgDBprefix; + } else { + $this->mTablePrefix = $tablePrefix; + } + if ( $server ) { $this->open( $server, $user, $password, $dbName ); } @@ -188,29 +203,7 @@ class Database { } if ( false === $ret ) { - # Ignore errors during error handling to avoid infinite recursion - $ignore = $this->setIgnoreErrors( true ); - - $error = mysql_error( $this->mConn ); - $errno = mysql_errno( $this->mConn ); - if( $ignore || $tempIgnore ) { - wfDebug("SQL ERROR (ignored): " . $error . "\n"); - } else { - $sql1line = str_replace( "\n", "\\n", $sql ); - wfLogDBError("$fname\t$errno\t$error\t$sql1line\n"); - wfDebug("SQL ERROR: " . $error . "\n"); - if ( $wgCommandLineMode ) { - wfDebugDieBacktrace( "A database error has occurred\n" . - "Query: $sql\n" . - "Function: $fname\n" . - "Error: $errno $error\n" - ); - } elseif ( $this->mOut ) { - // this calls wfAbruptExit() - $this->mOut->databaseError( $fname, $sql, $error, $errno ); - } - } - $this->setIgnoreErrors( $ignore ); + $this->reportQueryError( mysql_error(), mysql_errno(), $sql, $fname, $tempIgnore ); } if ( $wgProfiling ) { @@ -219,6 +212,34 @@ class Database { return $ret; } + function reportQueryError( $error, $errno, $sql, $fname, $tempIgnore = false ) { + global $wgCommandLineMode, $wgFullyInitialised; + # Ignore errors during error handling to avoid infinite recursion + $ignore = $this->setIgnoreErrors( true ); + + if( $ignore || $tempIgnore ) { + wfDebug("SQL ERROR (ignored): " . $error . "\n"); + } else { + $sql1line = str_replace( "\n", "\\n", $sql ); + wfLogDBError("$fname\t$errno\t$error\t$sql1line\n"); + wfDebug("SQL ERROR: " . $error . "\n"); + if ( $wgCommandLineMode || !$this->mOut || empty( $wgFullyInitialised ) ) { + $message = "A database error has occurred\n" . + "Query: $sql\n" . + "Function: $fname\n" . + "Error: $errno $error\n"; + if ( !$wgCommandLineMode ) { + $message = nl2br( $message ); + } + wfDebugDieBacktrace( $message ); + } else { + // this calls wfAbruptExit() + $this->mOut->databaseError( $fname, $sql, $error, $errno ); + } + } + $this->setIgnoreErrors( $ignore ); + } + function freeResult( $res ) { if ( !@mysql_free_result( $res ) ) { wfDebugDieBacktrace( "Unable to free MySQL result\n" ); @@ -263,41 +284,39 @@ class Database { { $table = $this->tableName( $table ); $sql = "UPDATE $table SET $var = '" . - wfStrencode( $value ) . "' WHERE ($cond)"; - return !!$this->query( $sql, DB_WRITE, $fname ); + $this->strencode( $value ) . "' WHERE ($cond)"; + return !!$this->query( $sql, DB_MASTER, $fname ); } + function getField( $table, $var, $cond, $fname = "Database::get", $options = array() ) { + return $this->selectField( $table, $var, $cond, $fname = "Database::get", $options = array() ); + } + # Simple SELECT wrapper, returns a single field, input must be encoded # Usually aborts on failure # If errors are explicitly ignored, returns FALSE on failure - function getField( $table, $var, $cond, $fname = "Database::get" ) + function selectField( $table, $var, $cond, $fname = "Database::selectField", $options = array() ) { - $table = $this->tableName( $table ); - $from = $table?" FROM $table ":""; - if ( is_array( $cond ) ) { - $where = ' WHERE ' . $this->makeList( $cond, LIST_AND ); - } elseif ( $cond ) { - $where = " WHERE ($cond)"; - } else { - $where = ''; + if ( !is_array( $options ) ) { + $options = array( $options ); } - $sql = "SELECT $var $from $where LIMIT 1"; - $result = $this->query( $sql, $fname ); - - $ret = false; - if ( $this->numRows( $result ) > 0 ) { - $s = $this->fetchRow( $result ); - $ret = $s[0]; - $this->freeResult( $result ); + $options['LIMIT'] = 1; + + $res = $this->select( $table, $var, $cond, $fname, $options ); + if ( $res === false || !$this->numRows( $res ) ) { + return false; + } + $row = $this->fetchRow( $res ); + if ( $row !== false ) { + $this->freeResult( $res ); + return $row[0]; + } else { + return false; } - return $ret; } - # SELECT wrapper - function select( $table, $vars, $conds, $fname = "Database::select", $options = array() ) - { - $vars = implode( ",", $vars ); - $table = $this->tableName( $table ); + # Returns an optional USE INDEX clause to go after the table, and a string to go at the end of the query + function makeSelectOptions( $options ) { if ( !is_array( $options ) ) { $options = array( $options ); } @@ -324,16 +343,33 @@ class Database { } else { $useIndex = ''; } + return array( $useIndex, $tailOpts ); + } + # SELECT wrapper + function select( $table, $vars, $conds, $fname = "Database::select", $options = array() ) + { + if ( is_array( $vars ) ) { + $vars = implode( ",", $vars ); + } + $table = $this->tableName( $table ); + list( $useIndex, $tailOpts ) = $this->makeSelectOptions( $options ); + if ( $conds !== false ) { - $where = $this->makeList( $conds, LIST_AND ); - $sql = "SELECT $vars FROM $table $useIndex WHERE $where $tailOpts"; + if ( is_array( $conds ) ) { + $conds = $this->makeList( $conds, LIST_AND ); + } + $sql = "SELECT $vars FROM $table $useIndex WHERE $conds $tailOpts"; } else { $sql = "SELECT $vars FROM $table $useIndex $tailOpts"; } return $this->query( $sql, $fname ); } + function getArray( $table, $vars, $conds, $fname = "Database::getArray", $options = array() ) { + return $this->selectRow( $table, $vars, $conds, $fname, $options ); + } + # Single row SELECT wrapper # Aborts or returns FALSE on error # @@ -341,9 +377,9 @@ class Database { # $conds: a condition map, terms are ANDed together. # Items with numeric keys are taken to be literal conditions # Takes an array of selected variables, and a condition map, which is ANDed - # e.g. getArray( "cur", array( "cur_id" ), array( "cur_namespace" => 0, "cur_title" => "Astronomy" ) ) + # e.g. selectRow( "cur", array( "cur_id" ), array( "cur_namespace" => 0, "cur_title" => "Astronomy" ) ) # would return an object where $obj->cur_id is the ID of the Astronomy article - function getArray( $table, $vars, $conds, $fname = "Database::getArray", $options = array() ) { + function selectRow( $table, $vars, $conds, $fname = "Database::selectRow", $options = array() ) { $options['LIMIT'] = 1; $res = $this->select( $table, $vars, $conds, $fname, $options ); if ( $res === false || !$this->numRows( $res ) ) { @@ -384,7 +420,7 @@ class Database { function fieldExists( $table, $field, $fname = "Database::fieldExists" ) { $table = $this->tableName( $table ); - $res = $this->query( "DESCRIBE $table", DB_READ, $fname ); + $res = $this->query( "DESCRIBE $table", DB_SLAVE, $fname ); if ( !$res ) { return NULL; } @@ -459,6 +495,22 @@ class Database { } return false; } + + function fieldType( $res, $index ) { + return mysql_field_type( $res, $index ); + } + + function indexUnique( $table, $index ) { + $indexInfo = $this->indexInfo( $table, $index ); + if ( !$indexInfo ) { + return NULL; + } + return !$indexInfo->Non_unique; + } + + function insertArray( $table, $a, $fname = "Database::insertArray", $options = array() ) { + return $this->insert( $table, $a, $fname = "Database::insertArray", $options = array() ); + } # INSERT wrapper, inserts an array into a table # @@ -467,9 +519,12 @@ class Database { # # Usually aborts on failure # If errors are explicitly ignored, returns success - function insertArray( $table, $a, $fname = "Database::insertArray", $options = array() ) + function insert( $table, $a, $fname = "Database::insert", $options = array() ) { $table = $this->tableName( $table ); + if ( !is_array( $options ) ) { + $options = array( $options ); + } if ( isset( $a[0] ) && is_array( $a[0] ) ) { $multi = true; $keys = array_keys( $a[0] ); @@ -496,9 +551,13 @@ class Database { } return !!$this->query( $sql, $fname ); } + + function updateArray( $table, $values, $conds, $fname = "Database::updateArray" ) { + return $this->update( $table, $values, $conds, $fname ); + } # UPDATE wrapper, takes a condition array and a SET array - function updateArray( $table, $values, $conds, $fname = "Database::updateArray" ) + function update( $table, $values, $conds, $fname = "Database::update" ) { $table = $this->tableName( $table ); $sql = "UPDATE $table SET " . $this->makeList( $values, LIST_SET ); @@ -559,9 +618,23 @@ class Database { } function tableName( $name ) { + if ( $this->mTablePrefix !== '' ) { + if ( strpos( '.', $name ) === false ) { + $name = $this->mTablePrefix . $name; + } + } return $name; } + function tableNames() { + $inArray = func_get_args(); + $retVal = array(); + foreach ( $inArray as $name ) { + $retVal[$name] = $this->tableName( $name ); + } + return $retVal; + } + function strencode( $s ) { return addslashes( $s ); } @@ -653,7 +726,7 @@ class Database { $table = $this->tableName( $table ); $sql = "SHOW COLUMNS FROM $table LIKE \"$field\";"; $res = $this->query( $sql, "Database::textFieldSize" ); - $row = wfFetchObject( $res ); + $row = $this->fetchObject( $res ); $this->freeResult( $res ); if ( preg_match( "/\((.*)\)/", $row->Type, $m ) ) { @@ -700,6 +773,84 @@ class Database { function limitResult($limit,$offset) { return " LIMIT ".(is_numeric($offset)?"{$offset},":"")."{$limit} "; } + + function wasDeadlock() { + return $this->lastErrno() == 1213; + } + + function deadlockLoop() { + $myFname = 'Database::deadlockLoop'; + + $this->query( "BEGIN", $myFname ); + $args = func_get_args(); + $function = array_shift( $args ); + $oldIgnore = $dbw->setIgnoreErrors( true ); + $tries = DEADLOCK_TRIES; + if ( is_array( $function ) ) { + $fname = $function[0]; + } else { + $fname = $function; + } + do { + $retVal = call_user_func_array( $function, $args ); + $error = $this->lastError(); + $errno = $this->lastErrno(); + $sql = $this->lastQuery(); + + if ( $errno ) { + if ( $dbw->wasDeadlock() ) { + # Retry + usleep( mt_rand( DEADLOCK_DELAY_MIN, DEADLOCK_DELAY_MAX ) ); + } else { + $dbw->reportQueryError( $error, $errno, $sql, $fname ); + } + } + } while( $dbw->wasDeadlock && --$tries > 0 ); + $this->setIgnoreErrors( $oldIgnore ); + if ( $tries <= 0 ) { + $this->query( "ROLLBACK", $myFname ); + $this->reportQueryError( $error, $errno, $sql, $fname ); + return false; + } else { + $this->query( "COMMIT", $myFname ); + return $retVal; + } + } + + # Do a SELECT MASTER_POS_WAIT() + function masterPosWait( $file, $pos ) { + $encFile = $this->strencode( $file ); + $sql = "SELECT MASTER_POS_WAIT('$encFile', $pos)"; + $res = $this->query( $sql, "Database::masterPosWait" ); + if ( $res && $row = $this->fetchRow( $res ) ) { + $this->freeResult( $res ); + return $row[0]; + } else { + return false; + } + } + + # Get the position of the master from SHOW SLAVE STATUS + function getSlavePos() { + $res = $this->query( 'SHOW SLAVE STATUS', 'Database::getSlavePos' ); + $row = $this->fetchObject( $res ); + if ( $row ) { + return array( $row->Master_Log_File, $row->Read_Master_Log_Pos ); + } else { + return array( false, false ); + } + } + + # Get the position of the master from SHOW MASTER STATUS + function getMasterPos() { + $res = $this->query( 'SHOW MASTER STATUS', 'Database::getMasterPos' ); + $row = $this->fetchObject( $res ); + if ( $row ) { + return array( $row->File, $row->Position ); + } else { + return array( false, false ); + } + } } class DatabaseMysql extends Database { diff --git a/includes/DatabaseFunctions.php b/includes/DatabaseFunctions.php index c5f1b6dbe6..43594a3a5c 100644 --- a/includes/DatabaseFunctions.php +++ b/includes/DatabaseFunctions.php @@ -3,11 +3,6 @@ # Backwards compatibility wrapper for Database.php -# I imagine this file will eventually become a backwards -# compatibility wrapper around a load balancer object, and -# the load balancer will finally call Database, which will -# represent a single connection - # Note: $wgDatabase has ceased to exist. Destroy all references. # Usually aborts on failure @@ -27,12 +22,13 @@ function wfQuery( $sql, $db, $fname = "" ) } } -function wfSingleQuery( $sql, $db, $fname = "" ) +function wfSingleQuery( $sql, $dbi, $fname = "" ) { - $res = wfQuery($sql, $db, $fname ); - $row = wfFetchRow( $res ); + $db =& wfGetDB( $dbi ); + $res = $db->query($sql, $fname ); + $row = $db->fetchRow( $res ); $ret = $row[0]; - wfFreeResult( $res ); + $db->freeResult( $res ); return $ret; } @@ -194,7 +190,7 @@ function wfLastDBquery( $dbi = DB_LAST ) } } -function wfSetSQL( $table, $var, $value, $cond, $dbi = DB_WRITE ) +function wfSetSQL( $table, $var, $value, $cond, $dbi = DB_MASTER ) { $db =& wfGetDB( $dbi ); if ( $db !== false ) { @@ -234,7 +230,7 @@ function wfIndexExists( $table, $index, $dbi = DB_LAST ) } } -function wfInsertArray( $table, $array, $fname = "wfInsertArray", $dbi = DB_WRITE ) +function wfInsertArray( $table, $array, $fname = "wfInsertArray", $dbi = DB_MASTER ) { $db =& wfGetDB( $dbi ); if ( $db !== false ) { @@ -254,7 +250,7 @@ function wfGetArray( $table, $vars, $conds, $fname = "wfGetArray", $dbi = DB_LAS } } -function wfUpdateArray( $table, $values, $conds, $fname = "wfUpdateArray", $dbi = DB_WRITE ) +function wfUpdateArray( $table, $values, $conds, $fname = "wfUpdateArray", $dbi = DB_MASTER ) { $db =& wfGetDB( $dbi ); if ( $db !== false ) { @@ -284,7 +280,7 @@ function wfStrencode( $s, $dbi = DB_LAST ) } } -function wfNextSequenceValue( $seqName, $dbi = DB_WRITE ) { +function wfNextSequenceValue( $seqName, $dbi = DB_MASTER ) { $db =& wfGetDB( $dbi ); if ( $db !== false ) { return $db->nextSequenceValue( $seqName ); @@ -293,7 +289,7 @@ function wfNextSequenceValue( $seqName, $dbi = DB_WRITE ) { } } -function wfUseIndexClause( $index, $dbi = DB_READ ) { +function wfUseIndexClause( $index, $dbi = DB_SLAVE ) { $db =& wfGetDB( $dbi ); if ( $db !== false ) { return $db->useIndexClause( $index ); diff --git a/includes/DatabasePostgreSQL.php b/includes/DatabasePostgreSQL.php index 5edaa8c4e6..06a79aa47f 100644 --- a/includes/DatabasePostgreSQL.php +++ b/includes/DatabasePostgreSQL.php @@ -209,14 +209,23 @@ class DatabasePgsql extends Database { function insertArray( $table, $a, $fname = "Database::insertArray", $options = array() ) { # PostgreSQL doesn't support options - # We have a go at faking some of them + # We have a go at faking one of them + # TODO: DELAYED, LOW_PRIORITY + + # IGNORE is performed using single-row inserts, ignoring errors in each if ( in_array( 'IGNORE', $options ) ) { - $ignore = true; + # FIXME: need some way to distiguish between key collision and other types of error $oldIgnore = $this->setIgnoreErrors( true ); - } - $retVal = parent::insertArray( $table, $a, $fname, array() ); - if ( $ignore ) { + if ( !is_array( reset( $a ) ) ) { + $a = array( $a ); + } + foreach ( $a as $row ) { + parent::insertArray( $table, $row, $fname, array() ); + } $this->setIgnoreErrors( $oldIgnore ); + $retVal = true; + } else { + $retVal = parent::insertArray( $table, $a, $fname, array() ); } return $retVal; } @@ -273,56 +282,46 @@ class DatabasePgsql extends Database { function replace( $table, $uniqueIndexes, $rows, $fname = "Database::replace" ) { $table = $this->tableName( $table ); - # Delete rows which collide - if ( $uniqueIndexes ) { - $sql = "DELETE FROM $table WHERE ("; - $first = true; - foreach ( $uniqueIndexes as $index ) { - if ( $first ) { - $first = false; - } else { - $sql .= ") OR ("; - } - if ( is_array( $col ) ) { - $first2 = true; - $sql .= "("; - foreach ( $index as $col ) { - if ( $first2 ) { - $first2 = false; - } else { - $sql .= " AND "; - } - //midom: atleast unbreak the class (remove syntax errors) - //$sql .= "$col = " $this->strencode; + # Single row case + if ( !is_array( reset( $rows ) ) ) { + $rows = array( $rows ); + } + + foreach( $rows as $row ) { + # Delete rows which collide + if ( $uniqueIndexes ) { + $sql = "DELETE FROM $table WHERE ("; + $first = true; + foreach ( $uniqueIndexes as $index ) { + if ( $first ) { + $first = false; + } else { + $sql .= ") OR ("; } - } - if ( $first ) { - $first = false; + if ( is_array( $index ) ) { + $first2 = true; + $sql .= "("; + foreach ( $index as $col ) { + if ( $first2 ) { + $first2 = false; + } else { + $sql .= " AND "; + } + $sql .= "$col=" . $this->addQuotes( $row[$col] ) + } } else { - $sql .= "OR "; + $sql .= "$index=" . $this->addQuotes( $row[$index] ); } - $sql .= "$col IN ("; - $indexValues = array(); - foreach ( $rows as $row ) { - $indexValues[] = $row[$col]; } - $sql .= $this->makeList( $indexValues, LIST_COMMA ) . ") "; + $sql .= ")"; + $this->query( $sql, $fname ); } - $this->query( $sql, $fname ); - } - # Now insert the rows - $sql = "INSERT INTO $table (" . $this->makeList( array_flip( $rows[0] ) ) .") VALUES "; - $first = true; - foreach ( $rows as $row ) { - if ( $first ) { - $first = false; - } else { - $sql .= ","; - } - $sql .= "(" . $this->makeList( $row, LIST_COMMA ) . ")"; + # Now insert the row + $sql = "INSERT INTO $table (" . $this->makeList( array_flip( $row ) ) .') VALUES (' . + $this->makeList( $row, LIST_COMMA ) . ')'; + $this->query( $sql, $fname ); } - $this->query( $sql, $fname ); } # DELETE where the condition is a join @@ -358,6 +357,11 @@ class DatabasePgsql extends Database { function limitResult($limit,$offset) { return " LIMIT $limit ".(is_numeric($offset)?" OFFSET {$offset} ":""); } + + # FIXME: actually detecting deadlocks might be nice + function wasDeadlock() { + return false; + } } # Just an alias. diff --git a/includes/DefaultSettings.php b/includes/DefaultSettings.php index aa7f853980..eb9c1d19f6 100644 --- a/includes/DefaultSettings.php +++ b/includes/DefaultSettings.php @@ -59,6 +59,7 @@ $wgDBname = 'wikidb'; $wgDBconnection = ''; $wgDBuser = 'wikiuser'; $wgDBtype = "mysql"; # "mysql" for working code and "PostgreSQL" for development/broken code +$wgDBprefix = ''; # Table name prefix # Database load balancer # This is a two-dimensional array, an array of server info structures @@ -68,7 +69,7 @@ $wgDBtype = "mysql"; # "mysql" for working code and "PostgreSQL" for d # user: DB user # password: DB password # type: "mysql" or "pgsql" -# load: ratio of DB_READ load, must be >=0, the sum of all loads must be >0 +# load: ratio of DB_SLAVE load, must be >=0, the sum of all loads must be >0 # Leave at false to use the single-server variables above $wgDBservers = false; diff --git a/includes/DifferenceEngine.php b/includes/DifferenceEngine.php index 30d369e6a7..df688228a4 100644 --- a/includes/DifferenceEngine.php +++ b/includes/DifferenceEngine.php @@ -121,7 +121,7 @@ cellpadding='0' cellspacing='4px' class='diff'> global $wgTitle, $wgOut, $wgLang; $fname = "DifferenceEngine::loadText"; - $dbr =& wfGetDB( DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); if ( 0 == $this->mNewid || 0 == $this->mOldid ) { $wgOut->setArticleFlag( true ); $this->mNewtitle = wfMsg( "currentrev" ); diff --git a/includes/EditPage.php b/includes/EditPage.php index cb2be1bc79..8ec9c1739c 100644 --- a/includes/EditPage.php +++ b/includes/EditPage.php @@ -543,7 +543,7 @@ htmlspecialchars( $wgLang->recodeForEdit( $this->textbox1 ) ) . /* private */ function mergeChangesInto( &$text ){ $fname = 'EditPage::mergeChangesInto'; $oldDate = $this->edittime; - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); $obj = $dbr->getArray( 'cur', array( 'cur_text' ), array( 'cur_id' => $this->mTitle->getArticleID() ), $fname, 'FOR UPDATE' ); diff --git a/includes/GlobalFunctions.php b/includes/GlobalFunctions.php index a72e84909b..a00ba73a95 100644 --- a/includes/GlobalFunctions.php +++ b/includes/GlobalFunctions.php @@ -63,11 +63,13 @@ function do_html_entity_decode( $string, $quote_style=ENT_COMPAT, $charset='ISO- $wgRandomSeeded = false; +# Seed Mersenne Twister +# Only necessary in PHP < 4.2.0 function wfSeedRandom() { global $wgRandomSeeded; - if ( ! $wgRandomSeeded ) { + if ( ! $wgRandomSeeded && version_compare( phpversion(), '4.2.0' ) < 0 ) { $seed = hexdec(substr(md5(microtime()),-8)) & 0x7fffffff; mt_srand( $seed ); $wgRandomSeeded = true; @@ -423,7 +425,7 @@ function wfNumberOfArticles() $fname = 'wfLoadSiteStats'; if ( -1 != $wgNumberOfArticles ) return; - $dbr =& wfGetDB( DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); $s = $dbr->getArray( 'site_stats', array( 'ss_total_views', 'ss_total_edits', 'ss_good_articles' ), array( 'ss_row_id' => 1 ), $fname @@ -508,11 +510,10 @@ function wfRecordUpload( $name, $oldver, $size, $desc, $copyStatus = "", $source global $wgUseCopyrightUpload; $fname = 'wfRecordUpload'; - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); # img_name must be unique - $indexInfo = $dbw->indexInfo( 'image', 'img_name' ); - if ( $indexInfo && $indexInfo->Non_unique ) { + if ( !$dbw->indexUnique( 'image', 'img_name' ) ) { wfDebugDieBacktrace( 'Database schema not up to date, please run maintenance/archives/patch-img_name_unique.sql' ); } @@ -535,7 +536,7 @@ function wfRecordUpload( $name, $oldver, $size, $desc, $copyStatus = "", $source # Test to see if the row exists using INSERT IGNORE # This avoids race conditions by locking the row until the commit, and also # doesn't deadlock. SELECT FOR UPDATE causes a deadlock for every race condition. - $dbw->insertArray( 'image', + $dbw->insert( 'image', array( 'img_name' => $name, 'img_size'=> $size, @@ -545,63 +546,70 @@ function wfRecordUpload( $name, $oldver, $size, $desc, $copyStatus = "", $source 'img_user_text' => $wgUser->getName(), ), $fname, 'IGNORE' ); + $descTitle = Title::makeTitle( NS_IMAGE, $name ); if ( $dbw->affectedRows() ) { # Successfully inserted, this is a new image + $id = $descTitle->getArticleID(); - $sql = 'SELECT cur_id,cur_text FROM cur WHERE cur_namespace=' . - Namespace::getImage() . " AND cur_title='" . - wfStrencode( $name ) . "'"; - $res = wfQuery( $sql, DB_READ, $fname ); - if ( 0 == wfNumRows( $res ) ) { - $common = - Namespace::getImage() . ",'" . - wfStrencode( $name ) . "','" . - wfStrencode( $desc ) . "','" . $wgUser->getID() . "','" . - wfStrencode( $wgUser->getName() ) . "','" . $now . - "',1"; - $sql = 'INSERT INTO cur (cur_namespace,cur_title,' . - 'cur_comment,cur_user,cur_user_text,cur_timestamp,cur_is_new,' . - 'cur_text,inverse_timestamp,cur_touched) VALUES (' . - $common . - ",'" . wfStrencode( $textdesc ) . "','{$won}','{$now}')"; - wfQuery( $sql, DB_WRITE, $fname ); - $id = wfInsertId() or 0; # We should throw an error instead + if ( $id == 0 ) { + $seqVal = $dbw->nextSequenceValue( 'cur_cur_id_seq' ); + $dbw->insertArray( 'cur', + array( + 'cur_id' => $seqVal, + 'cur_namespace' => NS_IMAGE, + 'cur_title' => $name, + 'cur_comment' => $desc, + 'cur_user' => $wgUser->getID(), + 'cur_user_text' => $wgUser->getName(), + 'cur_timestamp' => $now, + 'cur_is_new' => 1, + 'cur_text' => $textdesc, + 'inverse_timestamp' => $won, + 'cur_touched' => $now + ), $fname + ); + $id = $dbw->insertId() or 0; # We should throw an error instead - $titleObj = Title::makeTitle( NS_IMAGE, $name ); - RecentChange::notifyNew( $now, $titleObj, 0, $wgUser, $desc ); + RecentChange::notifyNew( $now, $descTitle, 0, $wgUser, $desc ); $u = new SearchUpdate( $id, $name, $desc ); $u->doUpdate(); } } else { # Collision, this is an update of an image + # Get current image row for update $s = $dbw->getArray( 'image', array( 'img_name','img_size','img_timestamp','img_description', 'img_user','img_user_text' ), array( 'img_name' => $name ), $fname, 'FOR UPDATE' ); - $s = wfFetchObject( $res ); - - $sql = 'INSERT INTO oldimage (oi_name,oi_archive_name,oi_size,' . - "oi_timestamp,oi_description,oi_user,oi_user_text) VALUES ('" . - wfStrencode( $s->img_name ) . "','" . - wfStrencode( $oldver ) . - "',{$s->img_size},'{$s->img_timestamp}','" . - wfStrencode( $s->img_description ) . "','" . - wfStrencode( $s->img_user ) . "','" . - wfStrencode( $s->img_user_text) . "')"; - wfQuery( $sql, DB_WRITE, $fname ); - - $sql = "UPDATE image SET img_size={$size}," . - "img_timestamp='" . wfTimestampNow() . "',img_user='" . - $wgUser->getID() . "',img_user_text='" . - wfStrencode( $wgUser->getName() ) . "', img_description='" . - wfStrencode( $desc ) . "' WHERE img_name='" . - wfStrencode( $name ) . "'"; - wfQuery( $sql, DB_WRITE, $fname ); + + # Insert it into oldimage + $dbw->insertArray( 'oldimage', + array( + 'oi_name' => $s->img_name, + 'oi_archive_name' => $oldver, + 'oi_size' => $s->img_size, + 'oi_timestamp' => $s->img_timestamp, + 'oi_description' => $s->img_description, + 'oi_user' => $s->img_user, + 'oi_user_text' => $s->img_user_text + ), $fname + ); + + # Update the current image row + $dbw->updateArray( 'image', + array( /* SET */ + 'img_size' => $size, + 'img_timestamp' => wfTimestampNow(), + 'img_user' => $wgUser->getID(), + 'img_user_text' => $wgUser->getName(), + 'img_description' => $desc, + ), array( /* WHERE */ + 'img_name' => $name + ), $fname + ); - $sql = "UPDATE cur SET cur_touched='{$now}' WHERE cur_namespace=" . - Namespace::getImage() . " AND cur_title='" . - wfStrencode( $name ) . "'"; - wfQuery( $sql, DB_WRITE, $fname ); + # Invalidate the cache for the description page + $descTitle->invalidateCache(); } $log = new LogPage( wfMsg( 'uploadlogpage' ), wfMsg( 'uploadlogpagetext' ) ); @@ -755,10 +763,13 @@ function wfHtmlEscapeFirst( $text ) { } # Sets dest to source and returns the original value of dest +# If source is NULL, it just returns the value, it doesn't set the variable function wfSetVar( &$dest, $source ) { $temp = $dest; - $dest = $source; + if ( !is_null( $source ) ) { + $dest = $source; + } return $temp; } diff --git a/includes/Image.php b/includes/Image.php index eb9dd8ee7f..b35f0db9e3 100644 --- a/includes/Image.php +++ b/includes/Image.php @@ -261,8 +261,8 @@ class Image function nextHistoryLine() { $fname = "Image::nextHistoryLine()"; + $dbr =& wfGetDB( DB_SLAVE ); if ( $this->historyLine == 0 ) {// called for the first time, return line from cur - $dbr =& wfGetDB( DB_READ ); $this->historyRes = $dbr->select( 'image', array( 'img_size','img_description','img_user','img_user_text','img_timestamp', "'' AS oi_archive_name" ), array( 'img_name' => $this->title->getDBkey() ), @@ -272,7 +272,6 @@ class Image return FALSE; } } else if ( $this->historyLine == 1 ) { - $dbr =& wfGetDB( DB_READ ); $this->historyRes = $dbr->select( 'oldimage', array( 'oi_size AS img_size', 'oi_description AS img_description', 'oi_user AS img_user', 'oi_user_text AS img_user_text', 'oi_timestamp AS img_timestamp', 'oi_archive_name' @@ -281,7 +280,7 @@ class Image } $this->historyLine ++; - return wfFetchObject( $this->historyRes ); + return $dbr->fetchObject( $this->historyRes ); } function resetHistory() diff --git a/includes/ImagePage.php b/includes/ImagePage.php index 8073cdd5d6..d06f06a8f8 100644 --- a/includes/ImagePage.php +++ b/includes/ImagePage.php @@ -85,13 +85,13 @@ class ImagePage extends Article { $wgOut->addHTML( "

    " . wfMsg( "imagelinks" ) . "

    \n" ); - $dbr =& wfGetDB( DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); $cur = $dbr->tableName( 'cur' ); $imagelinks = $dbr->tableName( 'imagelinks' ); $sql = "SELECT cur_namespace,cur_title FROM $imagelinks,$cur WHERE il_to=" . $dbr->addQuotes( $this->mTitle->getDBkey() ) . " AND il_from=cur_id"; - $res = $dbr->query( $sql, DB_READ, "Article::imageLinks" ); + $res = $dbr->query( $sql, DB_SLAVE, "Article::imageLinks" ); if ( 0 == $dbr->numRows( $res ) ) { $wgOut->addHtml( "

    " . wfMsg( "nolinkstoimage" ) . "

    \n" ); @@ -162,7 +162,7 @@ class ImagePage extends Article { $image = $wgRequest->getVal( 'image' ); $oldimage = $wgRequest->getVal( 'oldimage' ); - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); if ( !is_null( $image ) ) { $dest = wfImageDir( $image ); @@ -273,7 +273,7 @@ class ImagePage extends Article { } $oldver = wfTimestampNow() . "!{$name}"; - $dbr =& wfGetDB( DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); $size = $dbr->getField( "oldimage", "oi_size", "oi_archive_name='" . $dbr->strencode( $oldimage ) . "'" ); diff --git a/includes/LinkCache.php b/includes/LinkCache.php index 8dcba6f55c..4bb1dfea01 100644 --- a/includes/LinkCache.php +++ b/includes/LinkCache.php @@ -14,7 +14,8 @@ class LinkCache { /* private */ var $mGoodLinks, $mBadLinks, $mActive; /* private */ var $mImageLinks, $mCategoryLinks; /* private */ var $mPreFilled, $mOldGoodLinks, $mOldBadLinks; - + /* private */ var $mForUpdate; + /* private */ function getKey( $title ) { global $wgDBname; return "$wgDBname:lc:title:$title"; @@ -24,6 +25,7 @@ class LinkCache { { $this->mActive = true; $this->mPreFilled = false; + $this->mForUpdate = false; $this->mGoodLinks = array(); $this->mBadLinks = array(); $this->mImageLinks = array(); @@ -32,6 +34,11 @@ class LinkCache { $this->mOldBadLinks = array(); } + # General accessor to get/set whether SELECT FOR UPDATE should be used + function forUpdate( $update = NULL ) { + return wfSetVar( $this->mForUpdate, $update ); + } + function getGoodLinkID( $title ) { if ( array_key_exists( $title, $this->mGoodLinks ) ) { @@ -131,8 +138,15 @@ class LinkCache { if( $wgLinkCacheMemcached ) $id = $wgMemc->get( $key = $this->getKey( $title ) ); if( ! is_integer( $id ) ) { - $dbr =& wfGetDB( DB_READ ); - $id = $dbr->getField( 'cur', 'cur_id', array( 'cur_namespace' => $ns, 'cur_title' => $t ), $fname ); + if ( $this->mForUpdate ) { + $db =& wfGetDB( DB_MASTER ); + $options = array( 'FOR UPDATE' ); + } else { + $db =& wfGetDB( DB_SLAVE ); + $options = array(); + } + + $id = $db->getField( 'cur', 'cur_id', array( 'cur_namespace' => $ns, 'cur_title' => $t ), $fname, $options ); if ( !$id ) { $id = 0; } @@ -170,23 +184,29 @@ class LinkCache { return; } } + if ( $this->mForUpdate ) { + $db =& wfGetDB( DB_MASTER ); + $options = 'FOR UPDATE'; + } else { + $db =& wfGetDB( DB_SLAVE ); + $options = ''; + } - $dbr =& wfGetDB( DB_READ ); - $cur = $dbr->tableName( 'cur' ); - $links = $dbr->tableName( 'links' ); + $cur = $db->tableName( 'cur' ); + $links = $db->tableName( 'links' ); $sql = "SELECT cur_id,cur_namespace,cur_title FROM $cur,$links - WHERE cur_id=l_to AND l_from=$id"; - $res = $dbr->query( $sql, $fname ); - while( $s = $dbr->fetchObject( $res ) ) { + WHERE cur_id=l_to AND l_from=$id $options"; + $res = $db->query( $sql, $fname ); + while( $s = $db->fetchObject( $res ) ) { $this->addGoodLink( $s->cur_id, Title::makeName( $s->cur_namespace, $s->cur_title ) ); } - $res = $dbr->select( 'brokenlinks', array( 'bl_to' ), array( 'bl_from' => $id ), $fname ); - while( $s = wfFetchObject( $res ) ) { + $res = $db->select( 'brokenlinks', array( 'bl_to' ), array( 'bl_from' => $id ), $fname, array( $options ) ); + while( $s = $db->fetchObject( $res ) ) { $this->addBadLink( $s->bl_to ); } @@ -271,9 +291,17 @@ class LinkCache { } /* private */ function fillFromLinkscc( $id ){ + $fname = 'LinkCache::fillFromLinkscc'; + $id = IntVal( $id ); - $dbr =& wfGetDB( DB_READ ); - $raw = $dbr->getField( 'linkscc', 'lcc_cacheobj', array( 'lcc_pageid' => $id ) ); + if ( $this->mForUpdate ) { + $db =& wfGetDB( DB_MASTER ); + $options = 'FOR UPDATE'; + } else { + $db =& wfGetDB( DB_SLAVE ); + $options = ''; + } + $raw = $db->getField( 'linkscc', 'lcc_cacheobj', array( 'lcc_pageid' => $id ), $fname, $options ); if ( $raw === false ) { return false; } @@ -304,7 +332,7 @@ class LinkCache { } else { $ser = serialize( $this ); } - $db =& wfGetDB( DB_WRITE ); + $db =& wfGetDB( DB_MASTER ); $db->replace( 'linkscc', array( 'lcc_pageid' ), array( 'lcc_pageid' => $pid, 'lcc_cacheobj' => $ser ) ); } @@ -315,7 +343,7 @@ class LinkCache { if ( $wgEnablePersistentLC ) { $fname = "LinkCache::linksccClearLinksTo"; $pid = intval( $pid ); - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); # Delete linkscc rows which link to here $dbw->deleteJoin( 'linkscc', 'links', 'lcc_pageid', 'l_from', array( 'l_to' => $pid ), $fname ); # Delete linkscc row representing this page @@ -331,7 +359,7 @@ class LinkCache { $fname = 'LinkCache::linksccClearBrokenLinksTo'; if ( $wgEnablePersistentLC ) { - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); $dbw->deleteJoin( 'linkscc', 'brokenlinks', 'lcc_pageid', 'bl_from', array( 'bl_to' => $title ), $fname ); } } @@ -341,7 +369,7 @@ class LinkCache { global $wgEnablePersistentLC; if ( $wgEnablePersistentLC ) { $pid = intval( $pid ); - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); $dbw->delete( 'linkscc', array( 'lcc_pageid' => $pid ) ); } } diff --git a/includes/LinksUpdate.php b/includes/LinksUpdate.php index 64b9aafced..31a1f486bf 100644 --- a/includes/LinksUpdate.php +++ b/includes/LinksUpdate.php @@ -26,7 +26,7 @@ class LinksUpdate { $del = array(); $add = array(); - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); $links = $dbw->tableName( 'links' ); $brokenlinks = $dbw->tableName( 'brokenlinks' ); $imagelinks = $dbw->tableName( 'imagelinks' ); @@ -189,7 +189,7 @@ class LinksUpdate { wfProfileIn( $fname ); - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); $links = $dbw->tableName( 'links' ); $brokenlinks = $dbw->tableName( 'brokenlinks' ); $imagelinks = $dbw->tableName( 'imagelinks' ); @@ -292,7 +292,7 @@ class LinksUpdate { /* Call for a newly created page, or just to make sure state is consistent */ $fname = "LinksUpdate::fixBrokenLinks"; - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); $cur = $dbw->tableName( 'cur' ); $links = $dbw->tableName( 'links' ); diff --git a/includes/LoadBalancer.php b/includes/LoadBalancer.php index cfc389475b..00d2c1d483 100644 --- a/includes/LoadBalancer.php +++ b/includes/LoadBalancer.php @@ -5,10 +5,14 @@ require_once( "Database.php" ); # Valid database indexes # Operation-based indexes -define( "DB_READ", -1 ); # Read from the slave (or only server) -define( "DB_WRITE", -2 ); # Write to master (or only server) +define( "DB_SLAVE", -1 ); # Read from the slave (or only server) +define( "DB_MASTER", -2 ); # Write to master (or only server) define( "DB_LAST", -3 ); # Whatever database was used last +# Obsolete aliases +define( "DB_READ", -1 ); +define( "DB_WRITE", -2 ); + # Task-based indexes # ***NOT USED YET, EXPERIMENTAL*** # These may be defined in $wgDBservers. If they aren't, the default reader or writer will be used @@ -20,10 +24,13 @@ define( "DB_ASKSQL_R", 1002 ); # Special:Asksql read define( "DB_WATCHLIST_R", 1004 ); # Watchlist read define( "DB_TASK_LAST", 1004) ; # Last in list +define( "MASTER_WAIT_TIMEOUT", 15 ); # Time to wait for a slave to synchronise + class LoadBalancer { /* private */ var $mServers, $mConnections, $mLoads; /* private */ var $mFailFunction; /* private */ var $mForce, $mReadIndex, $mLastConn; + /* private */ var $mWaitForFile, $mWaitForPos; function LoadBalancer() { @@ -52,12 +59,12 @@ class LoadBalancer { $this->mConnections = array(); $this->mLastConn = false; $this->mLoads = array(); + $this->mWaitForFile = false; + $this->mWaitForPos = false; foreach( $servers as $i => $server ) { $this->mLoads[$i] = $server['load']; } - - wfSeedRandom(); } # Given an array of non-normalised probabilities, this function will select @@ -119,6 +126,50 @@ class LoadBalancer { return $conn; } + # Set the master wait position + # If a DB_SLAVE connection has been opened already, waits + # Otherwise sets a variable telling it to wait if such a connection is opened + function waitFor( $file, $pos ) { + $this->mWaitForFile = false; + $this->mWaitForPos = false; + + if ( count( $this->mServers ) == 1 ) { + return; + } + + $this->mWaitForFile = $file; + $this->mWaitForPos = $pos; + + if ( $this->mReadIndex > 0 ) { + $this->doWait( $this->mReadIndex ); + } + } + + # Wait for a given slave to catch up to the master pos stored in $this + function doWait( $index ) { + global $wgMemc; + + $key = "masterpos:" . $index; + $memcPos = $wgMemc->get( $key ); + if ( $memcPos ) { + list( $file, $pos ) = explode( ' ', $memcPos ); + # If the saved position is later than the requested position, return now + if ( $file == $this->mWaitForFile && $this->mWaitForPos <= $pos ) { + return; + } + } + + $conn =& $this->getConnection( $index ); + $result = $conn->masterPosWait( $this->mWaitForFile, $this->mWaitForPos, MASTER_WAIT_TIMEOUT ); + if ( $result == -1 ) { + # Timed out waiting for slave, use master instead + # This is not the ideal solution. If there are a large number of slaves, a slow + # replicated write query will cause the master to be swamped with reads. However + # that's a relatively graceful failure mode, so it will do for now. + $this->mReadIndex = 0; + } + } + function &getConnection( $i, $fail = false ) { /* @@ -126,18 +177,18 @@ class LoadBalancer { if ( $i >= DB_TASK_FIRST && $i < DB_TASK_LAST ) { if ( $i % 2 ) { # Odd index use writer - $i = DB_WRITE; + $i = DB_MASTER; } else { # Even index use reader - $i = DB_READ; + $i = DB_SLAVE; } }*/ # Operation-based index # Note, getReader() and getWriter() will re-enter this function - if ( $i == DB_READ ) { + if ( $i == DB_SLAVE ) { $this->mLastConn =& $this->getReader(); - } elseif ( $i == DB_WRITE ) { + } elseif ( $i == DB_MASTER ) { $this->mLastConn =& $this->getWriter(); } elseif ( $i == DB_LAST ) { # Just use $this->mLastConn, which should already be set @@ -147,8 +198,11 @@ class LoadBalancer { } } else { # Explicit index - if ( !array_key_exists( $i, $this->mConnections) || !$this->mConnections[$i]->isOpen() ) { + if ( !array_key_exists( $i, $this->mConnections ) || !$this->mConnections[$i]->isOpen() ) { $this->mConnections[$i] = $this->makeConnection( $this->mServers[$i] ); + if ( $i != 0 && $this->mWaitForFile ) { + $this->doWait( $i ); + } } if ( !$this->mConnections[$i]->isOpen() ) { wfDebug( "Failed to connect to database $i at {$this->mServers[$i]['host']}\n" ); @@ -206,4 +260,36 @@ class LoadBalancer { { return array_key_exists( $i, $this->mServers ); } + + # Get the number of defined servers (not the number of open connections) + function getServerCount() { + return count( $this->mServers ); + } + + # Save master pos to the session and to memcached, if the session exists + function saveMasterPos() { + global $wgSessionStarted; + if ( $wgSessionStarted && count( $this->mServers ) > 1 ) { + # If this entire request was served from a slave without opening a connection to the + # master (however unlikely that may be), then we can fetch the position from the slave. + if ( empty( $this->mConnections[0] ) ) { + $conn =& $this->getConnection( DB_SLAVE ); + list( $file, $pos ) = $conn->getSlavePos(); + } else { + $conn =& $this->getConnection( 0 ); + list( $file, $pos ) = $conn->getMasterPos(); + } + if ( $file !== false ) { + $_SESSION['master_log_file'] = $file; + $_SESSION['master_pos'] = $pos; + } + } + } + + # Loads the master pos from the session, waits for it if necessary + function loadMasterPos() { + if ( isset( $_SESSION['master_log_file'] ) && isset( $_SESSION['master_pos'] ) ) { + $this->waitFor( $_SESSION['master_log_file'], $_SESSION['master_pos'] ); + } + } } diff --git a/includes/LogPage.php b/includes/LogPage.php index 31f598c7a5..1c2aa206a9 100644 --- a/includes/LogPage.php +++ b/includes/LogPage.php @@ -20,7 +20,7 @@ class LogPage { { $fname = 'LogPage::getContent'; - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); $s = $dbw->getArray( 'cur', array( 'cur_id','cur_text','cur_timestamp' ), array( 'cur_namespace' => Namespace::getWikipedia(), 'cur_title' => $this->mTitle ), @@ -56,7 +56,7 @@ class LogPage { global $wgUser; $fname = "LogPage::saveContent"; - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); $uid = $wgUser->getID(); if( !$this->mContentLoaded ) return false; diff --git a/includes/MagicWord.php b/includes/MagicWord.php index 33b8f09332..697fe87d27 100644 --- a/includes/MagicWord.php +++ b/includes/MagicWord.php @@ -84,6 +84,9 @@ class MagicWord { { global $wgMagicWords; + if ( !is_array( $wgMagicWords ) ) { + wfDebugDieBacktrace( "Incorrect initialisation order, \$wgMagicWords does not exist\n" ); + } if (!array_key_exists( $id, $wgMagicWords ) ) { $mw = new MagicWord(); $mw->load( $id ); diff --git a/includes/Math.php b/includes/Math.php index 10ae193248..8dce2b8945 100644 --- a/includes/Math.php +++ b/includes/Math.php @@ -120,7 +120,7 @@ class MathRenderer { $md5_sql = pack("H32", $this->md5); # Binary packed, not hex - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); $dbw->replace( 'math', array( 'math_inputhash' ), array( 'math_inputhash' => $md5_sql, @@ -149,7 +149,7 @@ class MathRenderer { $fname = 'MathRenderer::_recall'; $this->md5 = md5( $this->tex ); - $dbr =& wfGetDB( DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); $rpage = $dbr->getArray( 'math', array( 'math_outputhash','math_html_conservativeness','math_html','math_mathml' ), array( 'math_inputhash' => pack("H32", $this->md5)), # Binary packed, not hex diff --git a/includes/MessageCache.php b/includes/MessageCache.php index a6f00f5f91..8b28aaf806 100755 --- a/includes/MessageCache.php +++ b/includes/MessageCache.php @@ -51,16 +51,18 @@ class MessageCache wfDebug( "MessageCache::load(): loading all messages\n" ); $this->lock(); # Other threads don't need to load the messages if another thread is doing it. - $this->mMemc->set( $this->mMemcKey, "loading", MSG_LOAD_TIMEOUT ); - $this->loadFromDB(); - # Save in memcached - # Keep trying if it fails, this is kind of important - for ( $i=0; $i<20 && !$this->mMemc->set( $this->mMemcKey, $this->mCache, $this->mExpiry ); $i++ ) { - usleep(mt_rand(500000,1500000)); - } - if ( $i == 20 ) { - $this->mMemc->set( $this->mMemcKey, "error", 86400 ); - wfDebug( "MemCached set error in MessageCache: restart memcached server!\n" ); + $success = $this->mMemc->set( $this->mMemcKey, "loading", MSG_LOAD_TIMEOUT ); + if ( $success ) { + $this->loadFromDB(); + # Save in memcached + # Keep trying if it fails, this is kind of important + for ( $i=0; $i<20 && !$this->mMemc->set( $this->mMemcKey, $this->mCache, $this->mExpiry ); $i++ ) { + usleep(mt_rand(500000,1500000)); + } + if ( $i == 20 ) { + $this->mMemc->set( $this->mMemcKey, "error", 86400 ); + wfDebug( "MemCached set error in MessageCache: restart memcached server!\n" ); + } } $this->unlock(); } @@ -90,7 +92,7 @@ class MessageCache function loadFromDB() { $fname = "MessageCache::loadFromDB"; - $dbr =& wfGetDB( DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); $res = $dbr->select( 'cur', array( 'cur_title', 'cur_text' ), array( 'cur_is_redirect' => 0, 'cur_namespace' => NS_MEDIAWIKI ), @@ -181,7 +183,7 @@ class MessageCache # If it wasn't in the cache, load each message from the DB individually if ( !$message && $useDB) { - $dbr =& wfGetDB( DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); $result = $dbr->getArray( "cur", array("cur_text"), array( "cur_namespace" => NS_MEDIAWIKI, "cur_title" => $title ), "MessageCache::get" ); diff --git a/includes/ObjectCache.php b/includes/ObjectCache.php index 5bcfde777f..18705d08d9 100644 --- a/includes/ObjectCache.php +++ b/includes/ObjectCache.php @@ -285,19 +285,19 @@ class /* abstract */ SqlBagOStuff extends BagOStuff { class MediaWikiBagOStuff extends SqlBagOStuff { function _doquery($sql) { - $dbw = wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); return $dbw->query($sql, "MediaWikiBagOStuff:_doquery"); } function _fetchobject($result) { - $dbw = wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); return $dbw->fetchObject($result); } function _freeresult($result) { - $dbw = wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); return $dbw->freeResult($result); } function _dberror($result) { - $dbw = wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); return $dbw->lastError(); } function _maxdatetime() { @@ -307,7 +307,7 @@ class MediaWikiBagOStuff extends SqlBagOStuff { return gmdate( "Y-m-d H:i:s", $ts ); } function _strencode($s) { - $dbw = wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); return $dbw->strencode($s); } } diff --git a/includes/OutputPage.php b/includes/OutputPage.php index fb662679f9..5f6fc1ef37 100644 --- a/includes/OutputPage.php +++ b/includes/OutputPage.php @@ -10,7 +10,7 @@ class OutputPage { var $mSubtitle, $mRedirect; var $mLastModified, $mCategoryLinks; var $mScripts; - + var $mSuppressQuickbar; var $mOnloadHandler; var $mDoNothing; @@ -345,8 +345,11 @@ class OutputPage { $this->sendCacheControl(); - + # Perform link colouring $this->mBodytext = $this->parseLinkHolders(); + + # Disable temporary placeholders, so that the skin produces HTML + $sk->postParseLinkColour( false ); header( "Content-type: $wgMimeType; charset={$wgOutputEncoding}" ); header( "Content-language: {$wgLanguageCode}" ); @@ -753,40 +756,45 @@ class OutputPage { } # FIXME: get these working # $fix = htmlspecialchars( $wgStylePath . "/ie-png-fix.js" ); - # $ret .= ""; + # $ret .= ""; return $ret; } # Parse link placeholders to avoid using linkcache - # $wgInternalLinks populated in Skin::makeLinkObj() + # Placeholders created in Skin::makeLinkObj() function parseLinkHolders() { - global $wgUser, $wgInternalLinks; + global $wgUser; $fname = 'OutputPage::parseLinkHolders'; wfProfileIn( $fname ); # Get placeholders from body - preg_match_all( "//", $this->mBodytext, $tmpLinks ); + preg_match_all( "//", $this->mBodytext, $tmpLinks ); if ( !empty( $tmpLinks[0] ) ) { - $dbr =& wfGetDB( DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); + $cur = $dbr->tableName( 'cur' ); $sk = $wgUser->getSkin(); + $threshold = $wgUser->getOption('stubthreshold'); - # Index the DB key along with other information - foreach ( $tmpLinks[1] as $key => $val ) { - $wgInternalLinks['dbkey'][$key] = $wgInternalLinks['obj'][$key]->getDBkey(); - } - - # Sort according to namespace - asort($wgInternalLinks['ns']); - + $namespaces =& $tmpLinks[1]; + $dbkeys =& $tmpLinks[2]; + $queries =& $tmpLinks[3]; + $texts =& $tmpLinks[4]; + + # Sort by namespace + asort( $namespaces ); + # Generate query - foreach ( $wgInternalLinks['ns'] as $key => $val ) { + foreach ( $namespaces as $key => $val ) { if ( !isset( $current ) ) { $current = $val; - $query = "SELECT cur_title, LENGTH(cur_text) AS cur_len, cur_is_redirect FROM cur "; - $query .= "WHERE (cur_namespace=$val AND cur_title IN("; + $query = "SELECT cur_namespace, cur_title"; + if ( $threshold > 0 ) { + $query .= ", LENGTH(cur_text) AS cur_len, cur_is_redirect"; + } + $query .= " FROM $cur WHERE (cur_namespace=$val AND cur_title IN("; } elseif ( $current != $val ) { $current = $val; $query .= ")) OR (cur_namespace=$val AND cur_title IN("; @@ -794,49 +802,52 @@ class OutputPage { $query .= ", "; } - $query .= $dbr->addQuotes( $wgInternalLinks['dbkey'][$key] ); + $query .= $dbr->addQuotes( $dbkeys[$key] ); } $query .= "))"; - $res = $dbr->query( $query ); + $res = $dbr->query( $query, $fname ); - # Fetch data and pass to appropriate make*LinkObj() - # Index search and replace strings to substitute placeholders for actual links - while ( $s = $dbr->fetchRow($res) ) { - $i = array_search($s['cur_title'], $wgInternalLinks['dbkey']); - $threshold = $wgUser->getOption('stubthreshold'); - if ( $threshold > 0 ) { - $size = $s['cur_len']; - if ( $s['cur_is_redirect'] || ( $wgInternalLinks['ns'][$i] != 0 ) ) { - $size = $threshold * 2; # Really big + # Fetch data and form into an associative array + # non-existent = broken + # 1 = known + # 2 = stub + $colours = array(); + while ( $s = $dbr->fetchObject($res) ) { + $key = $s->cur_namespace . ' ' . $s->cur_title; + if ( $threshold > 0 ) { + $size = $s->cur_len; + if ( $s->cur_is_redirect || $s->cur_namespace != 0 || $length < $threshold ) { + $colours[$key] = 1; + } else { + $colours[$key] = 2; } + $colours[$key] = array( $s->cur_len, $s->cur_is_redirect ); } else { - $size = 1; - } - - if ( $size < $threshold ) { - $wgInternalLinks['replace'][$i] = $sk->makeStubLinkObj( $wgInternalLinks['obj'][$i], - $wgInternalLinks['text'][$i], $wgInternalLinks['query'][$i], '', - $wgInternalLinks['prefix'][$i]); - } else { - $wgInternalLinks['replace'][$i] = $sk->makeKnownLinkObj( $wgInternalLinks['obj'][$i], - $wgInternalLinks['text'][$i], $wgInternalLinks['query'][$i], '', - $wgInternalLinks['prefix'][$i]); + $colours[$key] = 1; } } - # Finish populating search and replace arrays for broken links - foreach ( $wgInternalLinks['ns'] as $key => $val ) { - $search[] = $tmpLinks[0][$key]; - $replace[] = ( empty ( $wgInternalLinks['replace'][$key] ) ) ? - $sk->makeBrokenLinkObj( $wgInternalLinks['obj'][$key], - $wgInternalLinks['text'][$key], $wgInternalLinks['query'][$key], '', - $wgInternalLinks['prefix'][$key]) - : $wgInternalLinks['replace'][$key]; + # Construct search and replace arrays + $search = $replace = array(); + foreach ( $namespaces as $key => $ns ) { + $cKey = $ns . ' ' . $dbkeys[$key]; + $search[] = $tmpLinks[0][$key]; + $title = Title::makeTitle( $ns, $dbkeys[$key] ); + if ( empty( $colours[$cKey] ) ) { + $replace[] = $sk->makeBrokenLinkObj( $title, $texts[$key], $queries[$key] ); + } elseif ( $colours[$cKey] == 1 ) { + $replace[] = $sk->makeKnownLinkObj( $title, $texts[$key], $queries[$key] ); + } elseif ( $colours[$cKey] == 2 ) { + $replace[] = $sk->makeStubLinkObj( $title, $texts[$key], $queries[$key] ); + } } - + + # Do the thing $out = str_replace( $search, $replace, $this->mBodytext ); + } else { + $out = $this->mBodytext; } wfProfileOut( $fname ); diff --git a/includes/PageHistory.php b/includes/PageHistory.php index adc4790728..13c1b444d6 100644 --- a/includes/PageHistory.php +++ b/includes/PageHistory.php @@ -55,7 +55,7 @@ class PageHistory { $namespace = $this->mTitle->getNamespace(); $title = $this->mTitle->getText(); - $db =& wfGetDB( DB_READ ); + $db =& wfGetDB( DB_SLAVE ); $use_index = $db->useIndexClause( 'name_title_timestamp' ); $oldtable = $db->tableName( 'old' ); diff --git a/includes/Parser.php b/includes/Parser.php index 09784db28c..1d36b397f1 100644 --- a/includes/Parser.php +++ b/includes/Parser.php @@ -361,7 +361,7 @@ class Parser $id = $this->mTitle->getArticleID() ; # FIXME: add limits - $dbr =& wfGetDB( DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); $cur = $dbr->tableName( 'cur' ); $categorylinks = $dbr->tableName( 'categorylinks' ); @@ -425,7 +425,7 @@ class Parser $id = $this->mTitle->getArticleID() ; # FIXME: add limits - $dbr =& wfGetDB( DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); $cur = $dbr->tableName( 'cur' ); $categorylinks = $dbr->tableName( 'categorylinks' ); diff --git a/includes/Profiling.php b/includes/Profiling.php index e27c766e09..9998c45871 100755 --- a/includes/Profiling.php +++ b/includes/Profiling.php @@ -151,7 +151,7 @@ class Profiler /* static */ function logToDB($name, $timeSum, $eventCount) { - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); $profiling = $dbw->tableName( 'profiling' ); $name = $dbw->strencode( $name ); @@ -165,7 +165,7 @@ class Profiler if( $rc == 0) { $sql = "INSERT IGNORE INTO $profiling (pf_name,pf_count,pf_time) ". "VALUES ('{$name}', {$eventCount}, {$timeSum}) "; - $dbw->query($sql , DB_WRITE); + $dbw->query($sql , DB_MASTER); } // When we upgrade to mysql 4.1, the insert+update // can be merged into just a insert with this construct added: diff --git a/includes/QueryPage.php b/includes/QueryPage.php index a79897d471..4ed28cb220 100644 --- a/includes/QueryPage.php +++ b/includes/QueryPage.php @@ -66,8 +66,8 @@ class QueryPage { $sname = $this->getName(); $fname = get_class($this) . "::doQuery"; $sql = $this->getSQL(); - $dbr =& wfGetDB( DB_READ ); - $dbw =& wfGetDB( DB_WRITE ); + $dbr =& wfGetDB( DB_SLAVE ); + $dbw =& wfGetDB( DB_MASTER ); $querycache = $dbr->tableName( 'querycache' ); $wgOut->setSyndicated( true ); @@ -161,7 +161,7 @@ class QueryPage { $this->feedUrl() ); $feed->outHeader(); - $dbr = wfGetDB( DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); $sql = $this->getSQL() . $this->getOrderLimit( 0, 50 ); $res = $dbr->query( $sql, "QueryPage::doFeed" ); while( $obj = $dbr->fetchObject( $res ) ) { diff --git a/includes/RawPage.php b/includes/RawPage.php index 9179a5e6b1..4a8c936aae 100644 --- a/includes/RawPage.php +++ b/includes/RawPage.php @@ -64,7 +64,9 @@ class RawPage { $fname = 'RawPage::getrawtext'; if( !$this->mTitle ) return ''; - $dbr = wfGetDB( DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); + extract( $dbr->tableNames( 'cur', 'old' ) ); + $t = $dbr->strencode( $this->mTitle->getDBKey() ); $ns = $this->mTitle->getNamespace(); # special case @@ -76,13 +78,12 @@ class RawPage { } # else get it from the DB if(!empty($this->mOldId)) { - $oldtable = $dbr->tableName( 'old', DB_READ ); $sql = "SELECT old_text AS text,old_timestamp AS timestamp,". - "old_user AS user,old_flags AS flags FROM $oldtable " . + "old_user AS user,old_flags AS flags FROM $old " . "WHERE old_id={$this->mOldId}"; } else { $sql = "SELECT cur_id as id,cur_timestamp as timestamp,cur_user as user,cur_user_text as user_text," . - "cur_restrictions as restrictions,cur_comment as comment,cur_text as text FROM cur " . + "cur_restrictions as restrictions,cur_comment as comment,cur_text as text FROM $cur " . "WHERE cur_namespace=$ns AND cur_title='$t'"; } $res = $dbr->query( $sql, $fname ); diff --git a/includes/RecentChange.php b/includes/RecentChange.php index ed64ee213c..eb3aeb6361 100644 --- a/includes/RecentChange.php +++ b/includes/RecentChange.php @@ -88,6 +88,7 @@ class RecentChange global $wgUseRCQueue, $wgRCQueueID, $wgLocalInterwiki, $wgPutIPinRC; $fname = "RecentChange::save"; + $dbw =& wfGetDB( DB_MASTER ); if ( !is_array($this->mExtra) ) { $this->mExtra = array(); } @@ -98,26 +99,31 @@ class RecentChange } # Insert new row - wfInsertArray( "recentchanges", $this->mAttribs, $fname ); + $dbw->insertArray( "recentchanges", $this->mAttribs, $fname ); # Update old rows, if necessary if ( $this->mAttribs['rc_type'] == RC_EDIT ) { $oldid = $this->mAttribs['rc_last_oldid']; $ns = $this->mAttribs['rc_namespace']; - $title = wfStrencode($this->mAttribs['rc_title']); + $title = $this->mAttribs['rc_title']; $lastTime = $this->mExtra['lastTimestamp']; $now = $this->mAttribs['rc_timestamp']; $curId = $this->mAttribs['rc_cur_id']; # Update rc_this_oldid for the entries which were current - $sql = "UPDATE recentchanges SET rc_this_oldid={$oldid} " . - "WHERE rc_namespace=$ns AND rc_title='$title' AND rc_timestamp='$lastTime'"; - wfQuery( $sql, DB_WRITE, $fname ); + $dbw->updateArray( 'recentchanges', + array( /* SET */ + 'rc_this_oldid' => $oldid + ), array( /* WHERE */ + 'rc_namespace' => $ns, + 'rc_title' => $title, + 'rc_timestamp' => $lastTime + ), $fname + ); # Update rc_cur_time - $sql = "UPDATE recentchanges SET rc_cur_time='{$now}' " . - "WHERE rc_cur_id=" . $curId; - wfQuery( $sql, DB_WRITE, $fname ); + $dbw->updateArray( 'recentchanges', array( 'rc_cur_time' => $now ), + array( 'rc_cur_id' => $curId ), $fname ); } # Notify external application diff --git a/includes/SearchEngine.php b/includes/SearchEngine.php index bb2ed08b6e..df71975c62 100644 --- a/includes/SearchEngine.php +++ b/includes/SearchEngine.php @@ -180,23 +180,26 @@ class SearchEngine { $searchnamespaces = $this->queryNamespaces(); $redircond = $this->searchRedirects(); - + $dbr =& wfGetDB( DB_SLAVE ); + $searchindex = $dbr->tableName( 'searchindex' ); + $cur = $dbr->tableName( 'cur' ); + if ( $wgDisableTextSearch ) { $wgOut->addHTML( wfMsg( "searchdisabled" ) ); $wgOut->addHTML( wfMsg( "googlesearch", htmlspecialchars( $search ), $GLOBALS['wgInputEncoding'] ) ); } else { $sql = "SELECT cur_id,cur_namespace,cur_title," . - "cur_text FROM cur,searchindex " . + "cur_text FROM $cur,$searchindex " . "WHERE cur_id=si_page AND {$this->mTitlecond} " . "{$searchnamespaces} {$redircond}" . "LIMIT {$offset}, {$limit}"; - $res1 = wfQuery( $sql, DB_READ, $fname ); - $num = wfNumRows($res1); + $res1 = $dbr->query( $sql, $fname ); + $num = $dbr->numRows($res1); $sk = $wgUser->getSkin(); $text = ""; - $this->parseQuery(); + $this->parseQuery( $dbr ); if ( "" == $this->mTitlecond || "" == $this->mTextcond ) { $wgOut->addHTML( "

    " . wfMsg( "badquery" ) . "

    \n" . "

    " . wfMsg( "badquerytext" ) . "

    \n" ); @@ -208,20 +211,20 @@ class SearchEngine { $redircond = $this->searchRedirects(); $sql = "SELECT cur_id,cur_namespace,cur_title," . - "cur_text FROM cur,searchindex " . + "cur_text FROM $cur,$searchindex " . "WHERE cur_id=si_page AND {$this->mTitlecond} " . "{$searchnamespaces} {$redircond}" . "LIMIT {$offset}, {$limit}"; - $res1 = wfQuery( $sql, DB_READ, $fname ); - $num = wfNumRows($res1); + $res1 = $dbr->query( $sql, $fname ); + $num = $dbr->numRows($res1); $sql = "SELECT cur_id,cur_namespace,cur_title," . - "cur_text FROM cur,searchindex " . + "cur_text FROM $cur,$searchindex " . "WHERE cur_id=si_page AND {$this->mTextcond} " . "{$searchnamespaces} {$redircond} " . "LIMIT {$offset}, {$limit}"; - $res2 = wfQuery( $sql, DB_READ, $fname ); - $num = $num + wfNumRows($res2); + $res2 = $dbr->query( $sql, $fname ); + $num = $num + $dbr->numRows($res2); if ( $num == $limit ) { $top = wfShowingResults( $offset, $limit); @@ -244,7 +247,7 @@ class SearchEngine { $foundsome = false; - if ( 0 == wfNumRows( $res1 ) ) { + if ( 0 == $dbr->numRows( $res1 ) ) { $wgOut->addHTML( "

    " . wfMsg( "notitlematches" ) . "

    \n" ); } else { @@ -253,14 +256,14 @@ class SearchEngine { $wgOut->addHTML( "

    " . wfMsg( "titlematches" ) . "

    \n
      " ); - while ( $row = wfFetchObject( $res1 ) ) { + while ( $row = $dbr->fetchObject( $res1 ) ) { $this->showHit( $row ); } - wfFreeResult( $res1 ); + $dbr->freeResult( $res1 ); $wgOut->addHTML( "
    \n" ); } - if ( 0 == wfNumRows( $res2 ) ) { + if ( 0 == $dbr->numRows( $res2 ) ) { $wgOut->addHTML( "

    " . wfMsg( "notextmatches" ) . "

    \n" ); } else { @@ -268,10 +271,10 @@ class SearchEngine { $off = $offset + 1; $wgOut->addHTML( "

    " . wfMsg( "textmatches" ) . "

    \n" . "
      " ); - while ( $row = wfFetchObject( $res2 ) ) { + while ( $row = $dbr->fetchObject( $res2 ) ) { $this->showHit( $row ); } - wfFreeResult( $res2 ); + $dbr->freeResult( $res2 ); $wgOut->addHTML( "
    \n" ); } if ( ! $foundsome ) { @@ -288,13 +291,13 @@ class SearchEngine { return $lc; } - function parseQuery() + function parseQuery( &$db ) { global $wgDBminWordLen, $wgLang, $wgDBmysql4; if( $wgDBmysql4 ) { # Use cleaner boolean search if available - return $this->parseQuery4(); + return $this->parseQuery4( $db ); } # on non mysql4 database: get list of words we don't want to search for require_once( "FulltextStoplist.php" ); @@ -318,7 +321,7 @@ class SearchEngine { } else { if ( "" != $last ) { $cond .= " AND"; } $cond .= " (MATCH (##field##) AGAINST ('" . - wfStrencode( $word ). "'))"; + $db->strencode( $word ). "'))"; $last = $word; array_push( $this->mSearchterms, "\\b" . $word . "\\b" ); } @@ -332,7 +335,7 @@ class SearchEngine { "si_text", $cond ) . " AND (cur_is_redirect=0) )"; } - function parseQuery4() + function parseQuery4( &$db ) { global $wgLang; $lc = SearchEngine::legalSearchChars(); @@ -362,7 +365,7 @@ class SearchEngine { wfDebug( "Can't understand search query '$this->mUsertext'\n" ); } - $searchon = wfStrencode( $searchon ); + $searchon = $db->strencode( $searchon ); $this->mTitlecond = " MATCH(si_title) AGAINST('$searchon' IN BOOLEAN MODE)"; $this->mTextcond = " (MATCH(si_text) AGAINST('$searchon' IN BOOLEAN MODE) AND cur_is_redirect=0)"; } @@ -567,7 +570,8 @@ class SearchEngine { /* static */ function getTitlesByLength($aLength, $aNamespace = 0){ global $wgMemc, $wgDBname; - + $fname = 'SearchEngin::getTitlesByLength'; + // to avoid multiple costly SELECTs in case of no memcached if( $this->all_titles ){ if( isset( $this->all_titles[$aLength][$aNamespace] ) ){ @@ -589,10 +593,11 @@ class SearchEngine { } $wgMemc->set( $mkeyts, time() ); - - $res = wfQuery("SELECT cur_title, cur_namespace FROM cur", DB_READ); + + $dbr =& wfGetDB( DB_SLAVE ); + $res = $dbr->select( 'cur', array( 'cur_title', 'cur_namespace' ), false, $fname ); $titles = array(); // length, ns, [titles] - while( $obj = wfFetchObject( $res ) ){ + while( $obj = $dbr->fetchObject( $res ) ){ $title = $obj->cur_title; $ns = $obj->cur_namespace; $len = strlen( $title ); diff --git a/includes/SearchUpdate.php b/includes/SearchUpdate.php index 55bad7907d..9cbbb61aad 100644 --- a/includes/SearchUpdate.php +++ b/includes/SearchUpdate.php @@ -31,13 +31,14 @@ class SearchUpdate { return false; } $lc = SearchEngine::legalSearchChars() . "&#;"; - $db =& wfGetDB( DB_WRITE ); + $db =& wfGetDB( DB_MASTER ); + $searchindex = $db->tableName( 'searchindex' ); if( $this->mText == false ) { # Just update the title $lowpri = $db->lowPriorityOption(); - $sql = "UPDATE $lowpri searchindex SET si_title='" . - wfStrencode( Title::indexTitle( $this->mNamespace, $this->mTitle ) ) . + $sql = "UPDATE $lowpri $searchindex SET si_title='" . + $db->strencode( Title::indexTitle( $this->mNamespace, $this->mTitle ) ) . "' WHERE si_page={$this->mId}"; $db->query( $sql, "SearchUpdate::doUpdate" ); return; @@ -79,9 +80,9 @@ class SearchUpdate { # Strip wiki '' and ''' $text = preg_replace( "/''[']*/", " ", $text ); - $sql = "REPLACE INTO searchindex (si_page,si_title,si_text) VALUES ({$this->mId},'" . - wfStrencode( Title::indexTitle( $this->mNamespace, $this->mTitle ) ) . "','" . - wfStrencode( $text ) . "')"; + $sql = "REPLACE INTO $searchindex (si_page,si_title,si_text) VALUES ({$this->mId},'" . + $db->strencode( Title::indexTitle( $this->mNamespace, $this->mTitle ) ) . "','" . + $db->strencode( $text ) . "')"; $db->query( $sql, "SearchUpdate::doUpdate" ); } } diff --git a/includes/Setup.php b/includes/Setup.php index 90be866249..747d1c393b 100644 --- a/includes/Setup.php +++ b/includes/Setup.php @@ -74,6 +74,7 @@ global $wgMsgCacheExpiry, $wgCommandLineMode; global $wgBlockCache, $wgParserCache, $wgParser, $wgDBConnections; global $wgLoadBalancer, $wgDBservers; global $wgDBserver, $wgDBuser, $wgDBpassword, $wgDBname, $wgDBtype; +global $wgFullyInitialised; # Useful debug output if ( $wgCommandLineMode ) { @@ -126,13 +127,6 @@ if( $wgUseMemCached ) { $wgMemc->set_servers( $wgMemCachedServers ); $wgMemc->set_debug( $wgMemCachedDebug ); - # Test it to see if it's working - # This is necessary because otherwise wfMsg would be extremely inefficient - if ( !$wgMemc->set( 'test', '', 0 ) ) { - wfDebug( "Memcached failed setup test - connection error?\n" ); - $wgUseMemCached = false; - $wgMemc = new FakeMemCachedClient(); - } $messageMemc = &$wgMemc; } else { $wgMemc = new FakeMemCachedClient(); @@ -144,6 +138,16 @@ if( $wgUseMemCached ) { } wfProfileOut( $fname.'-memcached' ); +wfProfileIn( $fname.'-SetupSession' ); + +if( !$wgCommandLineMode && ( isset( $_COOKIE[ini_get('session.name')] ) || isset( $_COOKIE[$wgDBname.'Password'] ) ) ) { + User::SetupSession(); + $wgSessionStarted = true; +} else { + $wgSessionStarted = false; +} + +wfProfileOut( $fname.'-SetupSession' ); wfProfileIn( $fname.'-database' ); if ( !$wgDBservers ) { @@ -157,7 +161,7 @@ if ( !$wgDBservers ) { )); } $wgLoadBalancer = LoadBalancer::newFromParams( $wgDBservers ); -$wgLoadBalancer->force(0); +$wgLoadBalancer->loadMasterPos(); wfProfileOut( $fname.'-database' ); wfProfileIn( $fname.'-language' ); @@ -205,13 +209,6 @@ if ( $wgUseDynamicDates ) { } wfProfileOut( $fname.'-DateFormatter' ); -wfProfileIn( $fname.'-SetupSession' ); - -if( !$wgCommandLineMode && ( isset( $_COOKIE[ini_get('session.name')] ) || isset( $_COOKIE[$wgDBname.'Password'] ) ) ) { - User::SetupSession(); -} - -wfProfileOut( $fname.'-SetupSession' ); wfProfileIn( $fname.'-BlockCache' ); $wgBlockCache = new BlockCache( true ); @@ -238,6 +235,7 @@ $wgParserCache = new ParserCache(); $wgParser = new Parser(); $wgOut->setParserOptions( ParserOptions::newFromUser( $wgUser ) ); $wgDBConnections = array(); +wfSeedRandom(); # Placeholders in case of DB error $wgTitle = Title::newFromText( wfMsg( 'badtitle' ) ); @@ -254,6 +252,7 @@ foreach ( $wgExtensionFunctions as $func ) { $func(); } +$wgFullyInitialised = true; wfProfileOut( $fname.'-extensions' ); wfProfileOut( $fname ); diff --git a/includes/SiteStatsUpdate.php b/includes/SiteStatsUpdate.php index f8a6bb5931..247adabc56 100644 --- a/includes/SiteStatsUpdate.php +++ b/includes/SiteStatsUpdate.php @@ -32,9 +32,11 @@ class SiteStatsUpdate { else $m = ""; array_push( $a, "ss_good_articles=(ss_good_articles$m)" ); - $db =& wfGetDB( DB_WRITE ); + $db =& wfGetDB( DB_MASTER ); + $site_stats = $db->tableName( 'site_stats' ); $lowpri = $db->lowPriorityOption(); - $sql = "UPDATE $lowpri site_stats SET " . implode ( ",", $a ) . + + $sql = "UPDATE $lowpri $site_stats SET " . implode ( ",", $a ) . " WHERE ss_row_id=1"; $db->query( $sql, "SiteStatsUpdate::doUpdate" ); } diff --git a/includes/Skin.php b/includes/Skin.php index bf4efbbe0c..bc67c384e7 100644 --- a/includes/Skin.php +++ b/includes/Skin.php @@ -46,6 +46,7 @@ class Skin { var $rc_cache ; # Cache for Enhanced Recent Changes var $rcCacheIndex ; # Recent Changes Cache Counter for visibility toggle var $rcMoveIndex; + var $postParseLinkColour = true; function Skin() { @@ -65,6 +66,11 @@ class Skin { function getSkinName() { return "standard"; } + + # Get/set accessor for delayed link colouring + function postParseLinkColour( $setting = NULL ) { + return wfSetVar( $this->postParseLinkColour, $setting ); + } function qbSetting() { @@ -1440,7 +1446,6 @@ class Skin { function makeLinkObj( &$nt, $text= '', $query = '', $trail = '', $prefix = '' ) { global $wgOut, $wgUser; - global $wgInternalLinks; $fname = 'Skin::makeLinkObj'; if ( $nt->isExternal() ) { @@ -1463,21 +1468,48 @@ class Skin { ( Namespace::getImage() == $nt->getNamespace() ) ) { $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix ); } else { - $inside = ''; - if ( '' != $trail ) { - if ( preg_match( $this->linktrail, $trail, $m ) ) { - $inside = $m[1]; - $trail = $m[2]; + if ( $this->postParseLinkColour() ) { + $inside = ''; + if ( '' != $trail ) { + if ( preg_match( $this->linktrail, $trail, $m ) ) { + $inside = $m[1]; + $trail = $m[2]; + } + } + + # Allows wiki to bypass using linkcache, see OutputPage::parseLinkHolders() + $retVal = "getNamespace(), $nt->getDBkey(), + $query, $prefix . $text . $inside ) ) . ">{$trail}"; + } else { + # Work out link colour immediately + $aid = $nt->getArticleID() ; + if ( 0 == $aid ) { + $retVal = $this->makeBrokenLinkObj( $nt, $text, $query, $trail, $prefix ); + } else { + $threshold = $wgUser->getOption('stubthreshold') ; + if ( $threshold > 0 ) { + $dbr =& wfGetDB( DB_SLAVE ); + $s = $dbr->selectRow( 'cur', array( 'LENGTH(cur_text) AS x', 'cur_namespace', + 'cur_is_redirect' ), array( 'cur_id' => $aid ), $fname ) ; + if ( $s !== false ) { + $size = $s->x; + if ( $s->cur_is_redirect OR $s->cur_namespace != 0 ) { + $size = $threshold*2 ; # Really big + } + $dbr->freeResult( $res ); + } else { + $size = $threshold*2 ; # Really big + } + } else { + $size = 1 ; + } + if ( $size < $threshold ) { + $retVal = $this->makeStubLinkObj( $nt, $text, $query, $trail, $prefix ); + } else { + $retVal = $this->makeKnownLinkObj( $nt, $text, $query, $trail, $prefix ); + } } } - - # Allows wiki to bypass using linkcache, see OutputPage::parseLinkHolders() - $wgInternalLinks['obj'][] = $nt; - $wgInternalLinks['text'][] = $text . $inside; - $wgInternalLinks['query'][] = $query; - $wgInternalLinks['prefix'][] = $prefix; - $wgInternalLinks['ns'][] = $nt->getNamespace(); - $retVal = "getDBkey() . ">{$trail}"; } return $retVal; } diff --git a/includes/SpecialAllpages.php b/includes/SpecialAllpages.php index 27b2b3b0fe..32dcb6e833 100644 --- a/includes/SpecialAllpages.php +++ b/includes/SpecialAllpages.php @@ -30,43 +30,39 @@ function indexShowToplevel() $log->showAsDisabledPage(); return; } - - $fromwhere = "FROM cur WHERE cur_namespace=0"; - $order = "ORDER BY cur_title"; + + $dbr =& wfGetDB( DB_SLAVE ); + $cur = $dbr->tableName( 'cur' ); + $fromwhere = "FROM $cur WHERE cur_namespace=0"; + $order = 'ORDER BY cur_title'; $out = ""; + $where = array( 'cur_namespace' => 0 ); - $sql = "SELECT COUNT(*) AS count $fromwhere"; - $res = wfQuery( $sql, DB_READ, $fname ); - $s = wfFetchObject( $res ); - $count = $s->count; + $count = $dbr->selectField( 'cur', 'COUNT(*)', $where, $fname ); $sections = ceil( $count / $indexMaxperpage ); - - $sql = "SELECT cur_title $fromwhere $order LIMIT 1"; - $res = wfQuery( $sql, DB_READ, $fname ); - $s = wfFetchObject( $res ); - $inpoint = $s->cur_title; - + $inpoint = $dbr->selectField( 'cur', 'cur_title', $where, $fname, $order ); + $out .= "\n"; # There's got to be a cleaner way to do this! for( $i = 1; $i < $sections; $i++ ) { $from = $i * $indexMaxperpage; $sql = "SELECT cur_title $fromwhere $order ".wfLimitResult(2,$from); - $res = wfQuery( $sql, DB_READ, $fname ); + $res = $dbr->query( $sql, $fname ); - $s = wfFetchObject( $res ); + $s = $dbr->fetchObject( $res ); $outpoint = $s->cur_title; $out .= indexShowline( $inpoint, $outpoint ); - $s = wfFetchObject( $res ); + $s = $dbr->fetchObject( $res ); $inpoint = $s->cur_title; - wfFreeResult( $res ); + $dbr->freeResult( $res ); } $from = $i * $indexMaxperpage; $sql = "SELECT cur_title $fromwhere $order ".wfLimitResult(1,$count-1); - $res = wfQuery( $sql, DB_READ, $fname ); - $s = wfFetchObject( $res ); + $res = $dbr->query( $sql, $fname ); + $s = $dbr->fetchObject( $res ); $outpoint = $s->cur_title; $out .= indexShowline( $inpoint, $outpoint ); $out .= "
    \n"; @@ -81,13 +77,14 @@ function indexShowline( $inpoint, $outpoint ) { global $wgOut, $wgLang, $wgUser; $sk = $wgUser->getSkin(); + $dbr =& wfGetDB( DB_SLAVE ); # Fixme: this is ugly $out = wfMsg( "alphaindexline", $sk->makeKnownLink( $wgLang->specialPage( "Allpages" ), str_replace( "_", " ", $inpoint ), - "from=" . wfStrencode( $inpoint ) ) . "", + "from=" . $dbr->strencode( $inpoint ) ) . "", "" . str_replace( "_", " ", $outpoint ) ); @@ -101,15 +98,17 @@ function indexShowChunk( $from ) $maxPlusOne = $indexMaxperpage + 1; $out = ""; - $sql = "SELECT cur_title FROM cur WHERE cur_namespace=0 AND cur_title >= '" - . wfStrencode( $from ) . "' ORDER BY cur_title LIMIT " . $maxPlusOne; - $res = wfQuery( $sql, DB_READ, "indexShowChunk" ); + $dbr =& wfGetDB( DB_SLAVE ); + $cur = $dbr->tableName( 'cur' ); + $sql = "SELECT cur_title FROM $cur WHERE cur_namespace=0 AND cur_title >= '" + . $dbr->strencode( $from ) . "' ORDER BY cur_title LIMIT " . $maxPlusOne; + $res = $dbr->query( $sql, "indexShowChunk" ); ### FIXME: side link to previous $n = 0; $out = "\n"; - while( ($n < $indexMaxperpage) && ($s = wfFetchObject( $res )) ) { + while( ($n < $indexMaxperpage) && ($s = $dbr->fetchObject( $res )) ) { $t = Title::makeTitle( 0, $s->cur_title ); if( $t ) { $link = $sk->makeKnownLinkObj( $t ); @@ -133,11 +132,11 @@ function indexShowChunk( $from ) $out2 = "
    " . $sk->makeKnownLink( $wgLang->specialPage( "Allpages" ), wfMsg ( 'allpages' ) ); - if ( ($n == $indexMaxperpage) && ($s = wfFetchObject( $res )) ) { + if ( ($n == $indexMaxperpage) && ($s = $dbr->fetchObject( $res )) ) { $out2 .= " | " . $sk->makeKnownLink( $wgLang->specialPage( "Allpages" ), wfMsg ( 'nextpage', $s->cur_title ), - "from=" . wfStrencode( $s->cur_title ) ); + "from=" . $dbr->strencode( $s->cur_title ) ); } $out2 .= "
    "; diff --git a/includes/SpecialAncientpages.php b/includes/SpecialAncientpages.php index 69d2d43eb8..6029f06bc1 100644 --- a/includes/SpecialAncientpages.php +++ b/includes/SpecialAncientpages.php @@ -13,14 +13,15 @@ class AncientPagesPage extends QueryPage { } function getSQL() { - $db = wfGetDB( DB_READ ); + $db =& wfGetDB( DB_SLAVE ); + $cur = $db->tableName( 'cur' ); $use_index = $db->useIndexClause( 'cur_timestamp' ); return "SELECT 'Ancientpages' as type, cur_namespace as namespace, cur_title as title, UNIX_TIMESTAMP(cur_timestamp) as value - FROM cur $use_index + FROM $cur $use_index WHERE cur_namespace=0 AND cur_is_redirect=0"; } diff --git a/includes/SpecialBooksources.php b/includes/SpecialBooksources.php index 8e7aa72c81..13994c404a 100644 --- a/includes/SpecialBooksources.php +++ b/includes/SpecialBooksources.php @@ -41,15 +41,11 @@ class BookSourceList { # First, see if we have a custom list setup in # [[Wikipedia:Book sources]] or equivalent. - $bstitle = Title::newFromText( wfmsg( "booksources" ) ); - $sql = "SELECT cur_text FROM cur " . - "WHERE cur_namespace=4 and cur_title='" . - wfStrencode( $bstitle->getDBkey() ) . "'"; - $res = wfQuery( $sql, DB_READ, $fname ); - if( ( $s = wfFetchObject( $res ) ) and ( $s->cur_text != "" ) ) { - $bstext = $s->cur_text; + $bstitle = Title::makeTitle( NS_WIKIPEDIA, wfMsg( "booksources" ) ); + $dbr =& wfGetDB( DB_SLAVE ); + $bstext = $dbr->selectField( 'cur', 'cur_text', $bstitle->curCond(), $fname ); + if( $bstext ) { $bstext = str_replace( "MAGICNUMBER", $this->mIsbn, $bstext ); - $wgOut->addWikiText( $bstext ); return; } diff --git a/includes/SpecialCategories.php b/includes/SpecialCategories.php index 6cc493e7cc..4e0656016b 100644 --- a/includes/SpecialCategories.php +++ b/includes/SpecialCategories.php @@ -14,11 +14,13 @@ class CategoriesPage extends QueryPage { function getSQL() { $NScat = NS_CATEGORY; + $dbr =& wfGetDB( DB_SLAVE ); + $categorylinks = $dbr->tableName( 'categorylinks' ); return "SELECT DISTINCT 'Categories' as type, {$NScat} as namespace, cl_to as title, 1 as value - FROM categorylinks"; + FROM $categorylinks"; } function sortDescending() { diff --git a/includes/SpecialContributions.php b/includes/SpecialContributions.php index 5fd831ae49..279f58ccc6 100644 --- a/includes/SpecialContributions.php +++ b/includes/SpecialContributions.php @@ -22,7 +22,7 @@ function wfSpecialContributions( $par = "" ) $querylimit = $offlimit + 1; $hideminor = ($wgRequest->getVal( 'hideminor' ) ? 1 : 0); $sk = $wgUser->getSkin(); - + $dbr =& wfGetDB( DB_SLAVE ); $userCond = ""; $nt = Title::newFromURL( $target ); @@ -44,8 +44,8 @@ function wfSpecialContributions( $par = "" ) if ( $target == 'newbies' ) { # View the contributions of all recently created accounts - $row = wfGetArray("user",array("max(user_id) as m"),false); - $userCond = ">" . ($row->m - $row->m / 100); + $max = $dbr->selectField( 'user', 'max(user_id)', false, $fname ); + $userCond = ">" . ($max - $max / 100); $ul = ""; $id = 0; } @@ -65,28 +65,28 @@ function wfSpecialContributions( $par = "" ) "&offset={$offset}&limit={$limit}&hideminor=1" ); } - $oldtable = wfTableName( 'old', DB_READ ); + extract( $dbr->tableNames( 'old', 'cur' ) ); if ( $userCond == "" ) { - $sql = "SELECT cur_namespace,cur_title,cur_timestamp,cur_comment,cur_minor_edit,cur_is_new,cur_user_text FROM cur " . - "WHERE cur_user_text='" . wfStrencode( $nt->getText() ) . "' {$cmq} " . + $sql = "SELECT cur_namespace,cur_title,cur_timestamp,cur_comment,cur_minor_edit,cur_is_new,cur_user_text FROM $cur " . + "WHERE cur_user_text='" . $dbr->strencode( $nt->getText() ) . "' {$cmq} " . "ORDER BY inverse_timestamp LIMIT {$querylimit}"; - $res1 = wfQuery( $sql, DB_READ, $fname ); + $res1 = $dbr->query( $sql, $fname ); - $sql = "SELECT old_namespace,old_title,old_timestamp,old_comment,old_minor_edit,old_user_text FROM $oldtable " . - "WHERE old_user_text='" . wfStrencode( $nt->getText() ) . "' {$omq} " . + $sql = "SELECT old_namespace,old_title,old_timestamp,old_comment,old_minor_edit,old_user_text FROM $old " . + "WHERE old_user_text='" . $dbr->strencode( $nt->getText() ) . "' {$omq} " . "ORDER BY inverse_timestamp LIMIT {$querylimit}"; - $res2 = wfQuery( $sql, DB_READ, $fname ); + $res2 = $dbr->query( $sql, $fname ); } else { - $sql = "SELECT cur_namespace,cur_title,cur_timestamp,cur_comment,cur_minor_edit,cur_is_new,cur_user_text FROM cur " . + $sql = "SELECT cur_namespace,cur_title,cur_timestamp,cur_comment,cur_minor_edit,cur_is_new,cur_user_text FROM $cur " . "WHERE cur_user {$userCond} {$cmq} ORDER BY inverse_timestamp LIMIT {$querylimit}"; - $res1 = wfQuery( $sql, DB_READ, $fname ); + $res1 = $dbr->query( $sql, $fname ); - $sql = "SELECT old_namespace,old_title,old_timestamp,old_comment,old_minor_edit,old_user_text FROM $oldtable " . + $sql = "SELECT old_namespace,old_title,old_timestamp,old_comment,old_minor_edit,old_user_text FROM $old " . "WHERE old_user {$userCond} {$omq} ORDER BY inverse_timestamp LIMIT {$querylimit}"; - $res2 = wfQuery( $sql, DB_READ, $fname ); + $res2 = $dbr->query( $sql, $fname ); } - $nCur = wfNumRows( $res1 ); - $nOld = wfNumRows( $res2 ); + $nCur = $dbr->numRows( $res1 ); + $nOld = $dbr->numRows( $res2 ); $top = wfShowingResults( $offset, $limit ); $wgOut->addHTML( "

    {$top}\n" ); @@ -104,8 +104,8 @@ function wfSpecialContributions( $par = "" ) $wgOut->addHTML( "\n

    " . wfMsg( "nocontribs" ) . "

    \n" ); return; } - if ( 0 != $nCur ) { $obj1 = wfFetchObject( $res1 ); } - if ( 0 != $nOld ) { $obj2 = wfFetchObject( $res2 ); } + if ( 0 != $nCur ) { $obj1 = $dbr->fetchObject( $res1 ); } + if ( 0 != $nOld ) { $obj2 = $dbr->fetchObject( $res2 ); } $wgOut->addHTML( "
      \n" ); for( $n = 0; $n < $offlimit; $n++ ) { @@ -122,7 +122,7 @@ function wfSpecialContributions( $par = "" ) $isnew = $obj1->cur_is_new; $usertext = $obj1->cur_user_text; - $obj1 = wfFetchObject( $res1 ); + $obj1 = $dbr->fetchObject( $res1 ); $topmark = true; --$nCur; } else { @@ -133,7 +133,7 @@ function wfSpecialContributions( $par = "" ) $me = $obj2->old_minor_edit; $usertext = $obj2->old_user_text; - $obj2 = wfFetchObject( $res2 ); + $obj2 = $dbr->fetchObject( $res2 ); $topmark = false; $isnew = false; --$nOld; diff --git a/includes/SpecialDeadendpages.php b/includes/SpecialDeadendpages.php index a571d68388..24a36993f0 100644 --- a/includes/SpecialDeadendpages.php +++ b/includes/SpecialDeadendpages.php @@ -19,8 +19,10 @@ class DeadendPagesPage extends PageQueryPage { } function getSQL() { + $dbr =& wfGetDB( DB_SLAVE ); + extract( $dbr->tableNames( 'cur', 'links' ) ); return "SELECT 'Deadendpages' as type, cur_namespace AS namespace, cur_title as title, cur_title AS value " . - "FROM cur LEFT JOIN links ON cur_id = l_from " . + "FROM $cur LEFT JOIN $links ON cur_id = l_from " . "WHERE l_from IS NULL " . "AND cur_namespace = 0 " . "AND cur_is_redirect = 0"; diff --git a/includes/SpecialExport.php b/includes/SpecialExport.php index 06aa57de45..a72904bc2a 100644 --- a/includes/SpecialExport.php +++ b/includes/SpecialExport.php @@ -65,15 +65,16 @@ function pages2xml( $pages, $curonly = false ) { function page2xml( $page, $curonly, $full = false ) { global $wgLang; + $fname = 'page2xml'; + $title = Title::NewFromText( $page ); if( !$title ) return ""; - $t = wfStrencode( $title->getDBKey() ); - $ns = $title->getNamespace(); - $sql = "SELECT cur_id as id,cur_timestamp as timestamp,cur_user as user,cur_user_text as user_text," . - "cur_restrictions as restrictions,cur_comment as comment,cur_text as text FROM cur " . - "WHERE cur_namespace=$ns AND cur_title='$t'"; - $res = wfQuery( $sql, DB_READ ); - if( $s = wfFetchObject( $res ) ) { + + $dbr =& wfGetDB( DB_SLAVE ); + $s = $dbr->selectRow( 'cur', array( 'cur_id as id','cur_timestamp as timestamp','cur_user as user', + 'cur_user_text as user_text', 'cur_restrictions as restrictions','cur_comment as comment', + 'cur_text as text' ), $title->curCond(), $fname ); + if( $s !== false ) { $tl = htmlspecialchars( $title->getPrefixedText() ); $xml = " \n"; $xml .= " $tl\n"; @@ -84,12 +85,13 @@ function page2xml( $page, $curonly, $full = false ) { $xml .= " $s->restrictions\n"; } if( !$curonly ) { - $sql = "SELECT old_id as id,old_timestamp as timestamp, old_user as user, old_user_text as user_text," . - "old_comment as comment, old_text as text, old_flags as flags FROM old " . - "WHERE old_namespace=$ns AND old_title='$t' ORDER BY old_timestamp"; - $res = wfQuery( $sql, DB_READ ); + $res = $dbr->select( 'old', array( 'old_id as id','old_timestamp as timestamp', + 'old_user as user', 'old_user_text as user_text', 'old_comment as comment', + 'old_text as text', 'old_flags as flags' ), $title->curCond(), + array( 'ORDER BY' => 'old_timestamp' ), $fname + ); - while( $s2 = wfFetchObject( $res ) ) { + while( $s2 = $dbr->fetchObject( $res ) ) { $xml .= revision2xml( $s2, $full, false ); } } diff --git a/includes/SpecialGeo.php b/includes/SpecialGeo.php index f57f49a0cc..c20c40fd66 100644 --- a/includes/SpecialGeo.php +++ b/includes/SpecialGeo.php @@ -18,8 +18,8 @@ # http://www.gnu.org/copyleft/gpl.html function wfSpecialGeo( $page = "" ) { - global $wgOut, $wgLang; - $coordinates = $_GET['coordinates'] ; + global $wgOut, $wgLang, $wgRequest; + $coordinates = $wgRequest->getText( 'coordinates' ) ; $coordinates = explode ( ":" , $coordinates ) ; $ns = array_shift ( $coordinates ) ; $ew = array_shift ( $coordinates ) ; diff --git a/includes/SpecialImagelist.php b/includes/SpecialImagelist.php index 40e4dc946c..0b4db55078 100644 --- a/includes/SpecialImagelist.php +++ b/includes/SpecialImagelist.php @@ -6,9 +6,10 @@ function wfSpecialImagelist() $sort = $wgRequest->getVal( 'sort' ); $wpIlMatch = $wgRequest->getText( 'wpIlMatch' ); - + $dbr =& wfGetDB( DB_SLAVE ); + $image = $dbr->tableName( 'image' ); $sql = "SELECT img_size,img_name,img_user,img_user_text," . - "img_description,img_timestamp FROM image"; + "img_description,img_timestamp FROM $image"; $byname = wfMsg( "byname" ); $bydate = wfMsg( "bydate" ); @@ -20,7 +21,7 @@ function wfSpecialImagelist() } else if ( "byname" == $sort ) { if ( $wpIlMatch ) { $nt = Title::newFromUrl( $wpIlMatch ); - $m = wfStrencode( strtolower( $nt->getDBkey() ) ); + $m = $dbr->strencode( strtolower( $nt->getDBkey() ) ); $m = str_replace( "%", "\\%", $m ); $m = str_replace( "_", "\\_", $m ); $sql .= " WHERE LCASE(img_name) LIKE '%{$m}%'"; @@ -93,8 +94,8 @@ function wfSpecialImagelist() $text = wfMsg( "showlast", $fill, $bydate ); $wgOut->addHTML( "{$text}

      \n

      " ); - $res = wfQuery( $sql, DB_READ, "wfSpecialImagelist" ); - while ( $s = wfFetchObject( $res ) ) { + $res = $dbr->query( $sql, "wfSpecialImagelist" ); + while ( $s = $dbr->fetchObject( $res ) ) { $name = $s->img_name; $ut = $s->img_user_text; if ( 0 == $s->img_user ) { $ul = $ut; } @@ -117,7 +118,7 @@ function wfSpecialImagelist() $wgOut->addHTML( "{$l}
      \n" ); } $wgOut->addHTML( "

      " ); - wfFreeResult( $res ); + $dbr->freeResult( $res ); } ?> diff --git a/includes/SpecialImport.php b/includes/SpecialImport.php index 52de966b3c..153683418f 100644 --- a/includes/SpecialImport.php +++ b/includes/SpecialImport.php @@ -95,40 +95,8 @@ function wfSpecialImport( $page = "" ) { } function wfImportOldRevision( &$revision ) { - global $wgOut; - $fname = "wfImportOldRevision"; - - # Sneak a single revision into place - $ns = IntVal( $revision->title->getNamespace() ); - $t = wfStrencode( $revision->title->getDBkey() ); - $text = wfStrencode( $revision->getText() ); - $ts = wfStrencode( $revision->timestamp ); - $its = wfStrencode( wfInvertTimestamp( $revision->timestamp ) ) ; - $comment = wfStrencode( $revision->getComment() ); - - $user = User::newFromName( $revision->getUser() ); - $user_id = IntVal( $user->getId() ); - $user_text = wfStrencode( $user->getName() ); - - $minor = 0; # ?? - $flags = ""; - - # Make sure it doesn't already exist - $sql = "SELECT 1 FROM old WHERE old_namespace=$ns AND old_title='$t' AND old_timestamp='$ts'"; - $res = wfQuery( $sql, DB_WRITE, $fname ); - $numrows = wfNumRows( $res ); - wfFreeResult( $res ); - if( $numrows > 0 ) { - return wfMsg( "importhistoryconflict" ); - } - - $res = wfQuery( "INSERT INTO old " . - "(old_namespace,old_title,old_text,old_comment,old_user,old_user_text," . - "old_timestamp,inverse_timestamp,old_minor_edit,old_flags) " . - "VALUES ($ns,'$t','$text','$comment',$user_id,'$user_text','$ts','$its',$minor,'$flags')", - DB_WRITE, $fname ); - - return wfMsg( "ok" ); + $dbw =& wfGetDB( DB_MASTER ); + $dbw->deadlockLoop( array( &$revision, 'importOldRevision' ) ); } class WikiRevision { @@ -486,6 +454,44 @@ class WikiImporter { } xml_set_element_handler( $parser, "in_revision", "out_revision" ); } + + function importOldRevision() { + $fname = "WikiImporter::importOldRevision"; + $dbw =& wfGetDB( DB_MASTER ); + + # Sneak a single revision into place + $user = User::newFromName( $this->getUser() ); + + $res = $dbw->select( 'old', 1, + $this->title->oldCond() + array( 'old_timestamp' => $this->timestamp ), + $fname, 'FOR UPDATE' + ); + + $numrows = $dbw->numRows( $res ); + $dbw->freeResult( $res ); + if( $numrows > 0 ) { + return wfMsg( "importhistoryconflict" ); + } + + # Insert the row + $oldIgnore = $dbw->setIgnoreErrors( true ); + $success = $dbw->insert( 'old', + array( + 'old_namespace' => intval( $this->title->getNamespace() ), + 'old_title' => $this->title->getDBkey(), + 'old_text' => $this->getText(), + 'old_comment' => $this->getComment(), + 'old_user' => intval( $user->getId() ), + 'old_user_text' => $user->getName(), + 'old_timestamp' => $this->timestamp + 'inverse_timestamp' => wfInvertTimestamp( $this->timestamp ), + 'old_minor_edit' => 0, + 'old_flags' => '' + ), $fname + ); + + return wfMsg( "ok" ); + } } diff --git a/includes/SpecialListadmins.php b/includes/SpecialListadmins.php index ba5a579b76..41588d9650 100644 --- a/includes/SpecialListadmins.php +++ b/includes/SpecialListadmins.php @@ -16,11 +16,12 @@ class ListAdminsPage extends PageQueryPage { } function getSQL() { - $usertable = wfTableName( 'user' ); + $dbr =& wfGetDB( DB_SLAVE ); + $user = $dbr->tableName( 'user' ); $userspace = Namespace::getUser(); return 'SELECT user_rights as type,'.$userspace.' as namespace,'. 'user_name as title, user_name as value '. - "FROM $usertable ". + "FROM $user ". 'WHERE user_rights LIKE "%sysop%"'; } } diff --git a/includes/SpecialListusers.php b/includes/SpecialListusers.php index 5a317f2a02..4a9f659149 100644 --- a/includes/SpecialListusers.php +++ b/includes/SpecialListusers.php @@ -13,9 +13,11 @@ class ListUsersPage extends QueryPage { } function getSQL() { - $usertable = wfTableName( 'user', DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); + $usertable = $dbr->tableName( 'user' ); $userspace = Namespace::getUser(); - return "SELECT user_rights as type, $userspace as namespace, user_name as title, user_name as value FROM $usertable"; + return "SELECT user_rights as type, $userspace as namespace, user_name as title, " . + "user_name as value FROM $usertable"; } function sortDescending() { diff --git a/includes/SpecialLonelypages.php b/includes/SpecialLonelypages.php index ebb4f0b034..0c026e22a8 100644 --- a/includes/SpecialLonelypages.php +++ b/includes/SpecialLonelypages.php @@ -13,8 +13,11 @@ class LonelyPagesPage extends PageQueryPage { } function getSQL() { + $dbr =& wfGetDB( DB_SLAVE ); + extract( $dbr->tableNames( 'cur', 'links' ) ); + return "SELECT 'Lonelypages' as type, cur_namespace AS namespace, cur_title AS title, cur_title AS value " . - "FROM cur LEFT JOIN links ON cur_id=l_to ". + "FROM $cur LEFT JOIN $links ON cur_id=l_to ". "WHERE l_to IS NULL AND cur_namespace=0 AND cur_is_redirect=0"; } } diff --git a/includes/SpecialLongpages.php b/includes/SpecialLongpages.php index 6139fdb58c..36c1c754fc 100644 --- a/includes/SpecialLongpages.php +++ b/includes/SpecialLongpages.php @@ -13,12 +13,15 @@ class LongPagesPage extends QueryPage { } function getSQL() { + $dbr =& wfGetDB( DB_SLAVE ); + $cur = $dbr->tableName( 'cur' ); + return "SELECT 'Longpages' as type, cur_namespace as namespace, cur_title as title, LENGTH(cur_text) AS value - FROM cur + FROM $cur WHERE cur_namespace=0 AND cur_is_redirect=0"; } diff --git a/includes/SpecialMaintenance.php b/includes/SpecialMaintenance.php index 6e3f2d0aa5..e294dead9d 100644 --- a/includes/SpecialMaintenance.php +++ b/includes/SpecialMaintenance.php @@ -36,10 +36,10 @@ function wfSpecialMaintenance( $par=NULL ) $ns = $wgLang->getNamespaces() ; $r = wfMsg("maintnancepagetext") ; $r .= "
        \n" ; - $r .= "
      • ".getMPL("disambiguations")."
      • \n" ; + #$r .= "
      • ".getMPL("disambiguations")."
      • \n" ; # Doesn't work $r .= "
      • ".getMPL("doubleredirects")."
      • \n" ; $r .= "
      • ".getMPL("brokenredirects")."
      • \n" ; - $r .= "
      • ".getMPL("selflinks")."
      • \n" ; + #$r .= "
      • ".getMPL("selflinks")."
      • \n" ; # Doesn't work $r .= "
      • ".getMPL("mispeelings")."
      • \n" ; $r .= "
      • "; @@ -97,15 +97,17 @@ function wfSpecialDisambiguations() $fname = "wfSpecialDisambiguations"; list( $limit, $offset ) = wfCheckLimits(); + $dbr =& wfGetDB( DB_SLAVE ); + extract( $dbr->tableNames( 'links', 'cur' ) ); - $dp = wfStrencode( wfMsg("disambiguationspage") ); + $dp = $dbr->strencode( wfMsg("disambiguationspage") ); die( "wfSpecialDisambiguation is broken. Link tables have changed...\n" ); $sql = "SELECT la.l_from,la.l_to," . " lb.l_from AS source,lb.l_to AS dest," . " c.cur_id, c.cur_title AS dt" - . " FROM links AS la, links AS lb, cur AS c, cur AS d" + . " FROM $links AS la, $links AS lb, $cur AS c, $cur AS d" . " WHERE la.l_from='{$dp}'" . " AND la.l_to=lb.l_to" . " AND la.l_from<>lb.l_from" @@ -115,7 +117,7 @@ function wfSpecialDisambiguations() . " AND d.cur_namespace=0" . " LIMIT {$offset}, {$limit}"; - $res = wfQuery( $sql, DB_READ, $fname ); + $res = $dbr->query( $sql, $fname ); $sk = $wgUser->getSkin(); @@ -129,13 +131,13 @@ function wfSpecialDisambiguations() $wgOut->addHTML( "
        {$sl}\n" ); $s = "
          "; - while ( $obj = wfFetchObject( $res ) ) { + while ( $obj = $dbr->fetchObject( $res ) ) { $l1 = $sk->makeKnownLink ( $obj->source , "" , "redirect=no" ) ; $l2 = $sk->makeKnownLink ( $obj->dt ) ; $l3 = $sk->makeBrokenLink ( $obj->source , "(".wfMsg("qbedit").")" , "redirect=no" ) ; $s .= "
        1. {$l1} {$l3} => {$l2}
        2. \n" ; } - wfFreeResult( $res ); + $dbr->freeResult( $res ); $s .= "
        "; $wgOut->addHTML( $s ); $wgOut->addHTML( "

        {$sl}\n" ); @@ -147,15 +149,17 @@ function wfSpecialDoubleRedirects() $fname = "wfSpecialDoubleRedirects"; list( $limit, $offset ) = wfCheckLimits(); + $dbr =& wfGetDB( DB_SLAVE ); + extract( $dbr->tableNames( 'cur', 'links' ) ); $sql = "SELECT ca.cur_namespace as ns_a, ca.cur_title as title_a," . " cb.cur_namespace as ns_b, cb.cur_title as title_b," . " cb.cur_text AS rt " . - "FROM links,cur AS ca,cur AS cb ". + "FROM $links,$cur AS ca,$cur AS cb ". "WHERE ca.cur_is_redirect=1 AND cb.cur_is_redirect=1 AND l_to=cb.cur_id " . " AND l_from=ca.cur_id LIMIT {$offset}, {$limit}" ; - $res = wfQuery( $sql, DB_READ, $fname ); + $res = $dbr->query( $sql, $fname ); $top = getMaintenancePageBacklink( "doubleredirects" ); $top .= "

        ".wfMsg("doubleredirectstext")."


        \n"; @@ -168,7 +172,7 @@ function wfSpecialDoubleRedirects() $sk = $wgUser->getSkin(); $s = "
          "; - while ( $obj = wfFetchObject( $res ) ) { + while ( $obj = $dbr->fetchObject( $res ) ) { $n = explode ( "\n" , $obj->rt ) ; $n = $n[0] ; $sourceTitle = Title::makeTitle( $obj->ns_a, $obj->title_a ); @@ -179,7 +183,7 @@ function wfSpecialDoubleRedirects() $l3 = $sk->makeBrokenLinkObj( $sourceTitle , "(".wfMsg("qbedit").")" , "redirect=no" ) ; $s .= "
        1. {$l1} {$l3} => {$l2} (\"{$n}\")
        2. \n" ; } - wfFreeResult( $res ); + $dbr->freeResult( $res ); $s .= "
        "; $wgOut->addHTML( $s ); $wgOut->addHTML( "

        {$sl}\n" ); @@ -191,12 +195,15 @@ function wfSpecialBrokenRedirects() $fname = "wfSpecialBrokenRedirects"; list( $limit, $offset ) = wfCheckLimits(); + $dbr =& wfGetDB( DB_SLAVE ); + extract( $dbr->tableNames( 'cur', 'brokenlinks' ) ); - $sql = "SELECT bl_to,cur_title FROM brokenlinks,cur " . + + $sql = "SELECT bl_to,cur_title FROM $brokenlinks,$cur " . "WHERE cur_is_redirect=1 AND cur_namespace=0 AND bl_from=cur_id " . "LIMIT {$offset}, {$limit}" ; - $res = wfQuery( $sql, DB_READ, $fname ); + $res = $dbr->query( $sql, $fname ); $top = getMaintenancePageBacklink( "brokenredirects" ); $top .= "

        ".wfMsg("brokenredirectstext")."


        \n"; @@ -209,13 +216,13 @@ function wfSpecialBrokenRedirects() $sk = $wgUser->getSkin(); $s = "
          "; - while ( $obj = wfFetchObject( $res ) ) { + while ( $obj = $dbr->fetchObject( $res ) ) { $l1 = $sk->makeKnownLink ( $obj->cur_title , "" , "redirect=no" ) ; $l2 = $sk->makeBrokenLink ( $obj->cur_title , "(".wfMsg("qbedit").")" , "redirect=no" ) ; $l3 = $sk->makeBrokenLink ( $obj->bl_to , "" , "redirect=no" ) ; $s .= "
        1. {$l1} {$l2} => {$l3}
        2. \n" ; } - wfFreeResult( $res ); + $dbr->freeResult( $res ); $s .= "
        "; $wgOut->addHTML( $s ); $wgOut->addHTML( "

        {$sl}\n" ); @@ -234,7 +241,7 @@ function wfSpecialSelfLinks() "WHERE l_from=l_to AND l_to=cur_id " . "LIMIT {$offset}, {$limit}"; - $res = wfQuery( $sql, DB_READ, $fname ); + $res = wfQuery( $sql, DB_SLAVE, $fname ); $top = getMaintenancePageBacklink( "selflinks" ); $top .= "

        ".wfMsg("selflinkstext")."


        \n"; @@ -264,18 +271,17 @@ function wfSpecialMispeelings () $fname = "wfSpecialMispeelings"; list( $limit, $offset ) = wfCheckLimits(); + $dbr =& wfGetDB( DB_SLAVE ); + extract( $dbr->tableNames( 'cur', 'searchindex' ) ); # Determine page name $ms = wfMsg ( "mispeelingspage" ) ; - $mss = wfStrencode( str_replace ( " " , "_" , $ms ) ); + $mss = str_replace ( " " , "_" , $ms ); $msp = $wgLang->getNsText(4).":".$ms ; $msl = $sk->makeKnownLink ( $msp ) ; # Load list from database - $sql = "SELECT cur_text FROM cur WHERE cur_title='{$mss}' AND cur_namespace=4" ; - $res = wfQuery( $sql, DB_READ, $fname ); - $obj = wfFetchObject ( $res ) ; - $l = $obj->cur_text ; + $l = $dbr->selectField( 'cur', 'cur_text', array( 'cur_title' => $mss, 'cur_namespace' => 4 ), $fname ); $l = explode ( "\n" , $l ) ; $a = array () ; foreach ( $l as $x ) @@ -289,10 +295,11 @@ function wfSpecialMispeelings () if ( $cnt < $offset+$limit && $x != "" ) { $y = $x ; $x = preg_replace( '/^(\S+).*$/', '$1', $x ); - #$sql = "SELECT DISTINCT cur_title FROM cur WHERE cur_namespace=0 AND cur_is_redirect=0 AND (MATCH(cur_ind_text) AGAINST ('" . wfStrencode( $wgLang->stripForSearch( $x ) ) . "'))" ; - $sql = "SELECT DISTINCT cur_title FROM cur,searchindex WHERE cur_id=si_page AND cur_namespace=0 AND cur_is_redirect=0 AND (MATCH(si_text) AGAINST ('" . wfStrencode( $wgLang->stripForSearch( $x ) ) . "'))" ; - $res = wfQuery( $sql, DB_READ, $fname ); - while ( $obj = wfFetchObject ( $res ) ) { + $sql = "SELECT DISTINCT cur_title FROM $cur,$searchindex WHERE cur_id=si_page AND ". + "cur_namespace=0 AND cur_is_redirect=0 AND " . + "(MATCH(si_text) AGAINST ('" . $dbr->strencode( $wgLang->stripForSearch( $x ) ) . "'))" ; + $res = $dbr->query( $sql, $fname ); + while ( $obj = $dbr->fetchObject ( $res ) ) { if ( $cnt >= $offset AND $cnt < $offset+$limit ) { if ( $y != "" ) { if ( count ( $b ) > 0 ) $b[] = "\n" ; @@ -334,13 +341,15 @@ function wfSpecialMissingLanguageLinks() if ( $thelang == "w" ) $thelang = "en" ; # Fix for international wikis list( $limit, $offset ) = wfCheckLimits(); + $dbr =& wfGetDB( DB_SLAVE ); + $cur = $dbr->tableName( 'cur' ); - $sql = "SELECT cur_title FROM cur " . + $sql = "SELECT cur_title FROM $cur " . "WHERE cur_namespace=0 AND cur_is_redirect=0 " . "AND cur_title NOT LIKE '%/%' AND cur_text NOT LIKE '%[[{$thelang}:%' " . "LIMIT {$offset}, {$limit}"; - $res = wfQuery( $sql, DB_READ, $fname ); + $res = $dbr->query( $sql, $fname ); $mll = wfMsg( "missinglanguagelinkstext", $wgLang->getLanguageName($thelang) ); @@ -356,9 +365,9 @@ function wfSpecialMissingLanguageLinks() $sk = $wgUser->getSkin(); $s = "
          "; - while ( $obj = wfFetchObject( $res ) ) + while ( $obj = $dbr->fetchObject( $res ) ) $s .= "
        1. ".$sk->makeKnownLink ( $obj->cur_title )."
        2. \n" ; - wfFreeResult( $res ); + $dbr->freeResult( $res ); $s .= "
        "; $wgOut->addHTML( $s ); $wgOut->addHTML( "

        {$sl}\n" ); diff --git a/includes/SpecialMakesysop.php b/includes/SpecialMakesysop.php index a9564f167f..622dd2673c 100644 --- a/includes/SpecialMakesysop.php +++ b/includes/SpecialMakesysop.php @@ -123,40 +123,42 @@ class MakesysopForm { { global $wgOut, $wgUser, $wgLang; global $wgDBname, $wgMemc, $wgLocalDatabases; - + + $dbw =& wfGetDB( DB_MASTER ); $parts = explode( "@", $this->mUser ); - if( count( $parts ) == 2 && $wgUser->isDeveloper() ){ - $username = wfStrencode( $parts[0] ); + $usertable = $dbw->tableName( 'user' ); + + if( count( $parts ) == 2 && $wgUser->isDeveloper() && strpos( '.', $usertable ) === false ){ + $username = $dbw->strencode( $parts[0] ); if ( array_key_exists( $parts[1], $wgLocalDatabases ) ) { $dbName = $wgLocalDatabases[$parts[1]]; - $usertable = $dbName . ".user"; + $usertable = $dbName . "." . $usertable; } else { $this->showFail(); return; } } else { $username = wfStrencode( $this->mUser ); - $usertable = "user"; $dbName = $wgDBname; } if ( $username{0} == "#" ) { $id = intval( substr( $username, 1 ) ); - $sql = "SELECT user_id,user_rights FROM $usertable WHERE user_id=$id"; + $sql = "SELECT user_id,user_rights FROM $usertable WHERE user_id=$id FOR UPDATE"; } else { - $encName = wfStrencode( $username ); - $sql = "SELECT user_id, user_rights FROM $usertable WHERE user_name = '{$username}'"; + $encName = $dbw->strencode( $username ); + $sql = "SELECT user_id, user_rights FROM $usertable WHERE user_name = '{$username}' FOR UPDATE"; } - $prev = wfIgnoreSQLErrors( TRUE ); - $res = wfQuery( $sql, DB_WRITE ); - wfIgnoreSQLErrors( $prev ); + $prev = $dbw->setIgnoreErrors( TRUE ); + $res = $dbw->query( $sql ); + $dbw->setIgnoreSQLErrors( $prev ); - if( wfLastErrno() || ! $username || wfNumRows( $res ) == 0 ){ + if( $dbw->lastErrno() || ! $username || $dbw->numRows( $res ) == 0 ){ $this->showFail(); return; } - $row = wfFetchObject( $res ); + $row = $dbw->fetchObject( $res ); $id = intval( $row->user_id ); $rightsNotation = array(); @@ -189,7 +191,7 @@ class MakesysopForm { $this->showFail(); } else { $sql = "UPDATE $usertable SET user_rights = '{$newrights}' WHERE user_id = $id LIMIT 1"; - wfQuery($sql, DB_WRITE); + $dbw->query($sql); $wgMemc->delete( "$dbName:user:id:$id" ); $bureaucratLog = wfMsg( "bureaucratlog" ); diff --git a/includes/SpecialNewpages.php b/includes/SpecialNewpages.php index 095bb7f77d..802e9f9e29 100644 --- a/includes/SpecialNewpages.php +++ b/includes/SpecialNewpages.php @@ -15,6 +15,9 @@ class NewPagesPage extends QueryPage { } function getSQL() { + $dbr =& wfGetDB( DB_SLAVE ); + extract( $dbr->tableNames( 'recentchanges', 'cur' ) ); + return "SELECT 'Newpages' as type, rc_namespace AS namespace, @@ -27,7 +30,7 @@ class NewPagesPage extends QueryPage { rc_timestamp AS timestamp, length(cur_text) as length, cur_text as text - FROM recentchanges,cur + FROM $recentchanges,$cur WHERE rc_cur_id=cur_id AND rc_new=1 AND rc_namespace=0 AND cur_is_redirect=0"; } diff --git a/includes/SpecialPopularpages.php b/includes/SpecialPopularpages.php index e69743314c..23ad5709fb 100644 --- a/includes/SpecialPopularpages.php +++ b/includes/SpecialPopularpages.php @@ -14,12 +14,15 @@ class PopularPagesPage extends QueryPage { } function getSQL() { + $dbr =& wfGetDB( DB_SLAVE ); + $cur = $dbr->tableName( 'cur' ); + return "SELECT 'Popularpages' as type, cur_namespace as namespace, cur_title as title, cur_counter as value - FROM cur + FROM $cur WHERE cur_namespace=0 AND cur_is_redirect=0"; } diff --git a/includes/SpecialRandompage.php b/includes/SpecialRandompage.php index 0dd4b60487..fa8c348148 100644 --- a/includes/SpecialRandompage.php +++ b/includes/SpecialRandompage.php @@ -6,19 +6,20 @@ function wfSpecialRandompage() global $wgOut, $wgTitle, $wgArticle, $wgExtraRandompageSQL; $fname = "wfSpecialRandompage"; - wfSeedRandom(); $rand = mt_rand() / mt_getrandmax(); # interpolation and sprintf() can muck up with locale-specific decimal separator $randstr = number_format( $rand, 12, ".", "" ); - $db =& wfGetDB( DB_READ ); + $db =& wfGetDB( DB_SLAVE ); $use_index = $db->useIndexClause( 'cur_random' ); + $cur = $db->tableName( 'cur' ); + if ( $wgExtraRandompageSQL ) { $extra = "AND ($wgExtraRandompageSQL)"; } else { $extra = ''; } $sqlget = "SELECT cur_id,cur_title - FROM cur $use_index + FROM $cur $use_index WHERE cur_namespace=0 AND cur_is_redirect=0 $extra AND cur_random>$randstr ORDER BY cur_random diff --git a/includes/SpecialRecentchanges.php b/includes/SpecialRecentchanges.php index 4470c7622c..2d378b25ab 100644 --- a/includes/SpecialRecentchanges.php +++ b/includes/SpecialRecentchanges.php @@ -33,23 +33,24 @@ function wfSpecialRecentchanges( $par ) if( in_array( "hideliu", $bits) ) $hideliu = 1; } - $sql = "SELECT MAX(rc_timestamp) AS lastmod FROM recentchanges"; - $res = wfQuery( $sql, DB_READ, $fname ); - $s = wfFetchObject( $res ); + $dbr =& wfGetDB( DB_SLAVE ); + extract( $dbr->tableNames( 'recentchanges', 'watchlist' ) ); + + $lastmod = $dbr->selectField( 'recentchanges', 'MAX(rc_timestamp)', false, $fname ); # 10 seconds server-side caching max $wgOut->setSquidMaxage( 10 ); - if( $wgOut->checkLastModified( $s->lastmod ) ){ + if( $wgOut->checkLastModified( $lastmod ) ){ # Client cache fresh and headers sent, nothing more to do. return; } - $rctext = wfMsg( "recentchangestext" ); - # The next few lines can probably be commented out now that wfMsg can get text from the DB - $sql = "SELECT cur_text FROM cur WHERE cur_namespace=4 AND cur_title='Recentchanges'"; - $res = wfQuery( $sql, DB_READ, $fname ); - if( ( $s = wfFetchObject( $res ) ) and ( $s->cur_text != "" ) ) { - $rctext = $s->cur_text; + $rctext = $dbr->selectField( 'cur', 'cur_text', + array( 'cur_namespace' => NS_WIKIPEDIA, 'cur_title' => 'Recentchanges' ), + $fname + ); + if( !$rctext ) { + $rctext = wfMsg( "recentchangestext" ); } $wgOut->addWikiText( $rctext ); @@ -94,17 +95,18 @@ function wfSpecialRecentchanges( $par ) $showhide[1-$hideliu], wfArrayToCGI( array( "hideliu" => 1-$hideliu ), $urlparams ) ); $uid = $wgUser->getID(); - $sql2 = "SELECT recentchanges.*" . ($uid ? ",wl_user" : "") . " FROM recentchanges " . - ($uid ? "LEFT OUTER JOIN watchlist ON wl_user={$uid} AND wl_title=rc_title AND wl_namespace=rc_namespace & 65534 " : "") . + $sql2 = "SELECT $recentchanges.*" . ($uid ? ",wl_user" : "") . " FROM $recentchanges " . + ($uid ? "LEFT OUTER JOIN $watchlist ON wl_user={$uid} AND wl_title=rc_title AND wl_namespace=rc_namespace & 65534 " : "") . "WHERE rc_timestamp > '{$cutoff}' {$hidem} " . "ORDER BY rc_timestamp DESC LIMIT {$limit}"; - $res = wfQuery( $sql2, DB_READ, $fname ); + $res = $dbr->query( $sql2, DB_SLAVE, $fname ); $rows = array(); - while( $row = wfFetchObject( $res ) ){ + while( $row = $dbr->fetchObject( $res ) ){ $rows[] = $row; } - + $dbr->freeResult( $res ); + if(isset($from)) { $note = wfMsg( "rcnotefrom", $wgLang->formatNum( $limit ), $wgLang->timeanddate( $from, true ) ); @@ -160,7 +162,6 @@ function wfSpecialRecentchanges( $par ) $s .= $sk->endRecentChangesList(); $wgOut->addHTML( $s ); } - wfFreeResult( $res ); } function rcCountLink( $lim, $d, $page="Recentchanges", $more="" ) diff --git a/includes/SpecialRecentchangeslinked.php b/includes/SpecialRecentchangeslinked.php index 88cd47827d..53bb972166 100644 --- a/includes/SpecialRecentchangeslinked.php +++ b/includes/SpecialRecentchangeslinked.php @@ -51,11 +51,14 @@ function wfSpecialRecentchangeslinked( $par = NULL ) $cmq = "AND cur_minor_edit=0"; } else { $cmq = ""; } + $dbr =& wfGetDB( DB_SLAVE ); + extract( $dbr->tableNames( 'cur', 'links' ) ); + $sql = "SELECT cur_id,cur_namespace,cur_title,cur_user,cur_comment," . - "cur_user_text,cur_timestamp,cur_minor_edit,cur_is_new FROM links, cur " . + "cur_user_text,cur_timestamp,cur_minor_edit,cur_is_new FROM $links, $cur " . "WHERE cur_timestamp > '{$cutoff}' {$cmq} AND l_to=cur_id AND l_from=$id " . "GROUP BY cur_id ORDER BY inverse_timestamp LIMIT {$limit}"; - $res = wfQuery( $sql, DB_READ, $fname ); + $res = $dbr->query( $sql, $fname ); $wgOut->addHTML("< ".$sk->makeKnownLinkObj($nt, "", "redirect=no" )."
        \n"); $note = wfMsg( "rcnote", $limit, $days ); @@ -68,12 +71,12 @@ function wfSpecialRecentchangeslinked( $par = NULL ) $wgOut->addHTML( "{$note}\n" ); $s = $sk->beginRecentChangesList(); - $count = wfNumRows( $res ); + $count = $dbr->numRows( $res ); $counter = 1; while ( $limit ) { if ( 0 == $count ) { break; } - $obj = wfFetchObject( $res ); + $obj = $dbr->fetchObject( $res ); --$count; $rc = RecentChange::newFromCurRow( $obj ); @@ -83,7 +86,7 @@ function wfSpecialRecentchangeslinked( $par = NULL ) } $s .= $sk->endRecentChangesList(); - wfFreeResult( $res ); + $dbr->freeResult( $res ); $wgOut->addHTML( $s ); } diff --git a/includes/SpecialShortpages.php b/includes/SpecialShortpages.php index c3eafc4118..4feb514e27 100644 --- a/includes/SpecialShortpages.php +++ b/includes/SpecialShortpages.php @@ -17,12 +17,15 @@ class ShortPagesPage extends QueryPage { } function getSQL() { + $dbr =& wfGetDB( DB_SLAVE ); + $cur = $dbr->tableName( 'cur' ); + return "SELECT 'Shortpages' as type, cur_namespace as namespace, cur_title as title, LENGTH(cur_text) AS value - FROM cur + FROM $cur WHERE cur_namespace=0 AND cur_is_redirect=0"; } diff --git a/includes/SpecialStatistics.php b/includes/SpecialStatistics.php index 883ef0fc71..6995c033e7 100644 --- a/includes/SpecialStatistics.php +++ b/includes/SpecialStatistics.php @@ -7,17 +7,18 @@ function wfSpecialStatistics() $wgOut->addHTML( "

        " . wfMsg( "sitestats" ) . "

        \n" ); - $db =& wfGetDB( DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); + extract( $dbr->tableNames( 'cur', 'site_stats', 'user' ) ); - $sql = "SELECT COUNT(cur_id) AS total FROM cur"; - $res = $db->query( $sql, $fname ); - $row = $db->fetchObject( $res ); + $sql = "SELECT COUNT(cur_id) AS total FROM $cur"; + $res = $dbr->query( $sql, $fname ); + $row = $dbr->fetchObject( $res ); $total = $row->total; $sql = "SELECT ss_total_views, ss_total_edits, ss_good_articles " . - "FROM site_stats WHERE ss_row_id=1"; - $res = $db->query( $sql, $fname ); - $row = $db->fetchObject( $res ); + "FROM $site_stats WHERE ss_row_id=1"; + $res = $dbr->query( $sql, $fname ); + $row = $dbr->fetchObject( $res ); $views = $row->ss_total_views; $edits = $row->ss_total_edits; $good = $row->ss_good_articles; @@ -33,16 +34,15 @@ function wfSpecialStatistics() $wgOut->addWikiText( $text ); $wgOut->addHTML( "

        " . wfMsg( "userstats" ) . "

        \n" ); - $usertable = $db->tableName( 'user' ); - $sql = "SELECT COUNT(user_id) AS total FROM $usertable"; - $res = $db->query( $sql, $fname ); - $row = $db->fetchObject( $res ); + $sql = "SELECT COUNT(user_id) AS total FROM $user"; + $res = $dbr->query( $sql, $fname ); + $row = $dbr->fetchObject( $res ); $total = $row->total; - $sql = "SELECT COUNT(user_id) AS total FROM $usertable " . + $sql = "SELECT COUNT(user_id) AS total FROM $user " . "WHERE user_rights LIKE '%sysop%'"; - $res = $db->query( $sql, $fname ); - $row = $db->fetchObject( $res ); + $res = $dbr->query( $sql, $fname ); + $row = $dbr->fetchObject( $res ); $admins = $row->total; $sk = $wgUser->getSkin(); diff --git a/includes/SpecialUndelete.php b/includes/SpecialUndelete.php index e504b31a9e..c226aff192 100644 --- a/includes/SpecialUndelete.php +++ b/includes/SpecialUndelete.php @@ -47,9 +47,13 @@ class UndeleteForm { $fname = "UndeleteForm::showList"; # List undeletable articles - $sql = "SELECT ar_namespace,ar_title, COUNT(*) AS count FROM archive " . + $dbr =& wfGetDB( DB_SLAVE ); + $archive = $dbr->tableName( 'archive' ); + + $sql = "SELECT ar_namespace,ar_title, COUNT(*) AS count FROM $archive " . "GROUP BY ar_namespace,ar_title ORDER BY ar_namespace,ar_title"; - $res = wfQuery( $sql, DB_READ, $fname ); + + $res = $dbr->query( $sql, $fname ); $wgOut->setPagetitle( wfMsg( "undeletepage" ) ); $wgOut->addWikiText( wfMsg( "undeletepagetext" ) ); @@ -57,7 +61,7 @@ class UndeleteForm { $special = $wgLang->getNsText( Namespace::getSpecial() ); $sk = $wgUser->getSkin(); $wgOut->addHTML( "
          \n" ); - while ($row = wfFetchObject( $res )) { + while ($row = $dbr->fetchObject( $res )) { $n = ($row->ar_namespace ? ($wgLang->getNsText( $row->ar_namespace ) . ":") : ""). $row->ar_title; @@ -77,12 +81,14 @@ class UndeleteForm { $fname = "UndeleteForm::showRevision"; if(!preg_match("/[0-9]{14}/",$timestamp)) return 0; - - $sql = "SELECT ar_text,ar_flags FROM archive ". + + $dbr =& wfGetDB( DB_SLAVE ); + $archive = $dbr->tableName( 'archive' ); + $sql = "SELECT ar_text,ar_flags FROM $archive ". "WHERE ar_namespace={$namespace} AND ar_title='" . - wfStrencode( $title ) . "' AND ar_timestamp='" . wfStrencode( $timestamp ) ."'"; - $ret = wfQuery( $sql, DB_READ, $fname ); - $row = wfFetchObject( $ret ); + $dbr->strencode( $title ) . "' AND ar_timestamp='" . $dbr->strencode( $timestamp ) ."'"; + $ret = $dbr->query( $sql, $fname ); + $row = $dbr->fetchObject( $ret ); $wgOut->setPagetitle( wfMsg( "undeletepage" ) ); $wgOut->addWikiText( "(" . wfMsg( "undeleterevision", $wgLang->date($timestamp, true) ) @@ -96,26 +102,28 @@ class UndeleteForm { $sk = $wgUser->getSkin(); $wgOut->setPagetitle( wfMsg( "undeletepage" ) ); + $dbr =& wfGetDB( DB_SLAVE ); + $archive = $dbr->tableName( 'archive' ); # Get text of first revision - $sql = "SELECT ar_text FROM archive WHERE ar_namespace={$namespace} AND ar_title='" . - wfStrencode( $title ) . "' ORDER BY ar_timestamp DESC LIMIT 1"; - $ret = wfQuery( $sql, DB_READ ); + $sql = "SELECT ar_text FROM $archive WHERE ar_namespace={$namespace} AND ar_title='" . + $dbr->strencode( $title ) . "' ORDER BY ar_timestamp DESC LIMIT 1"; + $ret = $dbr->query( $sql ); - if( wfNumRows( $ret ) == 0 ) { + if( $dbr->numRows( $ret ) == 0 ) { $wgOut->addWikiText( wfMsg( "nohistory" ) ); return 0; } - $row = wfFetchObject( $ret ); + $row = $dbr->fetchObject( $ret ); $wgOut->addWikiText( wfMsg( "undeletehistory" ) . "\n
          \n" . $row->ar_text ); # Get remaining revisions $sql = "SELECT ar_minor_edit,ar_timestamp,ar_user,ar_user_text,ar_comment - FROM archive WHERE ar_namespace={$namespace} AND ar_title='" . wfStrencode( $title ) . + FROM archive WHERE ar_namespace={$namespace} AND ar_title='" . $dbr->strencode( $title ) . "' ORDER BY ar_timestamp DESC"; - $ret = wfQuery( $sql, DB_READ ); + $ret = $dbr->query( $sql ); # Ditch first row - $row = wfFetchObject( $ret ); + $row = $dbr->fetchObject( $ret ); $titleObj = Title::makeTitle( NS_SPECIAL, "Undelete" ); $action = $titleObj->escapeLocalURL( "action=submit" ); @@ -127,8 +135,8 @@ class UndeleteForm { "); - $log = wfGetSQL("cur", "cur_text", "cur_namespace=4 AND cur_title='". - wfStrencode( wfMsg("dellogpage") ) . "'" ); + $log = $dbr->selectField( "cur", "cur_text", + array( 'cur_namespace' => NS_WIKIPEDIA, 'cur_title' => wfMsg("dellogpage") ) ); if(preg_match("/^(.*". preg_quote( ($namespace ? ($wgLang->getNsText($namespace) . ":") : "") . str_replace("_", " ", $title), "/" ).".*)$/m", $log, $m)) { @@ -137,7 +145,7 @@ class UndeleteForm { $special = $wgLang->getNsText( Namespace::getSpecial() ); $wgOut->addHTML("
            "); - while( $row = wfFetchObject( $ret ) ) { + while( $row = $dbr->fetchObject( $ret ) ) { $wgOut->addHTML( "
          • " . $sk->makeKnownLink( $wgLang->specialPage( "Undelete" ), $wgLang->timeanddate( $row->ar_timestamp, true ), @@ -154,7 +162,7 @@ class UndeleteForm { /* private */ function undelete( $namespace, $title ) { global $wgUser, $wgOut, $wgLang, $wgDeferredUpdateList; - global $wgUseSquid, $wgInternalServer; + global $wgUseSquid, $wgInternalServer, $wgLinkCache; $fname = "doUndeleteArticle"; @@ -162,30 +170,35 @@ class UndeleteForm { $wgOut->fatalError( wfMsg( "cannotundelete" ) ); return; } - $t = wfStrencode($title); + $dbw =& wfGetDB( DB_MASTER ); + extract( $dbw->tableNames( 'cur', 'archive' ) ); + $t = $dbw->strencode($title); # Move article and history from the "archive" table - $sql = "SELECT COUNT(*) AS count FROM cur WHERE cur_namespace={$namespace} AND cur_title='{$t}'"; - $res = wfQuery( $sql, DB_READ ); - $row = wfFetchObject( $res ); + $sql = "SELECT COUNT(*) AS count FROM $cur WHERE cur_namespace={$namespace} AND cur_title='{$t}' FOR UPDATE"; + $res = $dbw->query( $sql, $fname ); + $row = $dbw->fetchObject( $res ); $now = wfTimestampNow(); if( $row->count == 0) { # Have to create new article... - $sql = "SELECT ar_text,ar_timestamp,ar_flags FROM archive WHERE ar_namespace={$namespace} AND ar_title='{$t}' ORDER BY ar_timestamp DESC LIMIT 1"; - $res = wfQuery( $sql, DB_READ, $fname ); - $s = wfFetchObject( $res ); + $sql = "SELECT ar_text,ar_timestamp,ar_flags FROM $archive WHERE ar_namespace={$namespace} AND ar_title='{$t}' " . + "ORDER BY ar_timestamp DESC LIMIT 1 FOR UPDATE"; + $res = $dbw->query( $sql, $fname ); + $s = $dbw->fetchObject( $res ); $max = $s->ar_timestamp; $redirect = MagicWord::get( MAG_REDIRECT ); $redir = $redirect->matchStart( $s->ar_text ) ? 1 : 0; - $sql = "INSERT INTO cur (cur_namespace,cur_title,cur_text," . + $seqVal = addQuotes( $dbw->nextSequenceValue( 'cur_cur_id_seq' ) ); + + $sql = "INSERT INTO $cur (cur_id,cur_namespace,cur_title,cur_text," . "cur_comment,cur_user,cur_user_text,cur_timestamp,inverse_timestamp,cur_minor_edit,cur_is_redirect,cur_random,cur_touched)" . - "SELECT ar_namespace,ar_title,ar_text,ar_comment," . - "ar_user,ar_user_text,ar_timestamp,99999999999999-ar_timestamp,ar_minor_edit,{$redir},RAND(),'{$now}' FROM archive " . + "SELECT $seqVal,ar_namespace,ar_title,ar_text,ar_comment," . + "ar_user,ar_user_text,ar_timestamp,99999999999999-ar_timestamp,ar_minor_edit,{$redir},RAND(),'{$now}' FROM $archive " . "WHERE ar_namespace={$namespace} AND ar_title='{$t}' AND ar_timestamp={$max}"; - wfQuery( $sql, DB_WRITE, $fname ); - $newid = wfInsertId(); + $dbw->query( $sql, $fname ); + $newid = $dbw->insertId(); $oldones = "AND ar_timestamp<{$max}"; } else { # If already exists, put history entirely into old table @@ -193,45 +206,46 @@ class UndeleteForm { $newid = 0; # But to make the history list show up right, we need to touch it. - $sql = "UPDATE cur SET cur_touched='{$now}' WHERE cur_namespace={$namespace} AND cur_title='{$t}'"; - wfQuery( $sql, DB_WRITE, $fname ); + $sql = "UPDATE $cur SET cur_touched='{$now}' WHERE cur_namespace={$namespace} AND cur_title='{$t}'"; + $dbw->query( $sql, $fname ); # FIXME: Sometimes restored entries will be _newer_ than the current version. # We should merge. } - $sql = "INSERT INTO old (old_namespace,old_title,old_text," . + $sql = "INSERT INTO $old (old_namespace,old_title,old_text," . "old_comment,old_user,old_user_text,old_timestamp,inverse_timestamp,old_minor_edit," . "old_flags) SELECT ar_namespace,ar_title,ar_text,ar_comment," . "ar_user,ar_user_text,ar_timestamp,99999999999999-ar_timestamp,ar_minor_edit,ar_flags " . - "FROM archive WHERE ar_namespace={$namespace} AND ar_title='{$t}' {$oldones}"; - wfQuery( $sql, DB_WRITE, $fname ); + "FROM $archive WHERE ar_namespace={$namespace} AND ar_title='{$t}' {$oldones}"; + $dbw->query( $sql, $fname ); # Finally, clean up the link tables if( $newid ) { + $wgLinkCache = new LinkCache(); + # Select for update + $wgLinkCache->forUpdate( true ); # Create a dummy OutputPage to update the outgoing links - # This works at the moment due to good luck. It may stop working in the - # future. Damn globals. $dummyOut = new OutputPage(); - $res = wfQuery( "SELECT cur_text FROM cur WHERE cur_id={$newid} " . - "AND cur_namespace={$namespace}", DB_READ, $fname ); - $row = wfFetchObject( $res ); - $text = $row->cur_text; + # Get the text + $text = $dbw->selectField( 'cur', 'cur_text', + array( 'cur_id' => $newid, 'cur_namespace' => $namespace ), + $fname, 'FOR UPDATE' + ); $dummyOut->addWikiText( $text ); - wfFreeResult( $res ); $u = new LinksUpdate( $newid, $this->mTargetObj->getPrefixedDBkey() ); array_push( $wgDeferredUpdateList, $u ); - + Article::onArticleCreate( $this->mTargetObj ); #TODO: SearchUpdate, etc. } # Now that it's safely stored, take it out of the archive - $sql = "DELETE FROM archive WHERE ar_namespace={$namespace} AND " . + $sql = "DELETE FROM $archive WHERE ar_namespace={$namespace} AND " . "ar_title='{$t}'"; - wfQuery( $sql, DB_WRITE, $fname ); + $dbw->query( $sql, $fname ); # Touch the log? diff --git a/includes/SpecialUnusedimages.php b/includes/SpecialUnusedimages.php index 4bc8d7bbf8..1807e411bb 100644 --- a/includes/SpecialUnusedimages.php +++ b/includes/SpecialUnusedimages.php @@ -5,11 +5,13 @@ function wfSpecialUnusedimages() { $fname = "wfSpecialUnusedimages"; list( $limit, $offset ) = wfCheckLimits(); + $dbr =& wfGetDB( DB_SLAVE ); + extract( $dbr->tableNames( 'image','imagelinks' ) ); $sql = "SELECT img_name,img_user,img_user_text,img_timestamp,img_description " . - "FROM image LEFT JOIN imagelinks ON img_name=il_to WHERE il_to IS NULL " . + "FROM $image LEFT JOIN $imagelinks ON img_name=il_to WHERE il_to IS NULL " . "ORDER BY img_timestamp ".wfLimitResult($limit,$offset); - $res = wfQuery( $sql, DB_READ, $fname ); + $res = $dbr->query( $sql, $fname ); $sk = $wgUser->getSkin(); @@ -23,7 +25,7 @@ function wfSpecialUnusedimages() { $ins = $wgLang->getNsText ( 6 ) ; $s = "
              "; - while ( $obj = wfFetchObject( $res ) ) { + while ( $obj = $dbr->fetchObject( $res ) ) { $name = $obj->img_name; $dlink = $sk->makeKnownLink( "{$ins}:{$name}", wfMsg( "imgdesc" ) ); $ilink = "{$name}"; @@ -41,7 +43,7 @@ function wfSpecialUnusedimages() { if ( "" != $c && "*" != $c ) { $s .= " ({$c})"; } $s .= "\n"; } - wfFreeResult( $res ); + $dbr->freeResult( $res ); $s .= "
            \n\n"; $wgOut->addHTML( $s ); $wgOut->addHTML( "

            {$sl}

            \n" ); diff --git a/includes/SpecialWantedpages.php b/includes/SpecialWantedpages.php index bf2d630096..95e65b63df 100644 --- a/includes/SpecialWantedpages.php +++ b/includes/SpecialWantedpages.php @@ -13,6 +13,9 @@ class WantedPagesPage extends QueryPage { } function getSQL() { + $dbr =& wfGetDB( DB_SLAVE ); + $brokenlinks = $dbr->tableName( 'brokenlinks' ); + # We cheat and return the full-text from bl_to in the title. # In the future, a pre-parsed name will be available. return @@ -20,7 +23,7 @@ class WantedPagesPage extends QueryPage { 0 as namespace, bl_to as title, COUNT(DISTINCT bl_from) as value - FROM brokenlinks + FROM $brokenlinks GROUP BY bl_to HAVING value > 1"; } diff --git a/includes/SpecialWatchlist.php b/includes/SpecialWatchlist.php index ba933092bf..b80dd241b7 100644 --- a/includes/SpecialWatchlist.php +++ b/includes/SpecialWatchlist.php @@ -51,9 +51,12 @@ function wfSpecialWatchlist() } } - $sql = "SELECT COUNT(*) AS n FROM watchlist WHERE wl_user=$uid"; - $res = wfQuery( $sql, DB_READ ); - $s = wfFetchObject( $res ); + $dbr =& wfGetDB( DB_SLAVE ); + extract( $dbr->tableNames( 'cur', 'watchlist', 'recentchanges' ) ); + + $sql = "SELECT COUNT(*) AS n FROM $watchlist WHERE wl_user=$uid"; + $res = $dbr->query( $sql ); + $s = $dbr->fetchObject( $res ); $nitems = $s->n; if($nitems == 0) { $wgOut->addHTML( wfMsg( "nowatchlist" ) ); @@ -80,9 +83,9 @@ function wfSpecialWatchlist() $docutoff = "AND cur_timestamp > '" . ( $cutoff = wfUnix2Timestamp( time() - intval( $days * 86400 ) ) ) . "'"; - $sql = "SELECT COUNT(*) AS n FROM cur WHERE cur_timestamp>'$cutoff'"; - $res = wfQuery( $sql, DB_READ ); - $s = wfFetchObject( $res ); + $sql = "SELECT COUNT(*) AS n FROM $cur WHERE cur_timestamp>'$cutoff'"; + $res = $dbr->query( $sql ); + $s = $dbr->fetchObject( $res ); $npages = $s->n; } @@ -95,11 +98,11 @@ function wfSpecialWatchlist() $specialTitle->escapeLocalUrl( "action=submit" ) . "' method='post'>\n" . "
              \n" ); - $sql = "SELECT wl_namespace,wl_title FROM watchlist WHERE wl_user=$uid"; - $res = wfQuery( $sql, DB_READ ); + $sql = "SELECT wl_namespace,wl_title FROM $watchlist WHERE wl_user=$uid"; + $res = $dbr->query( $sql ); global $wgUser, $wgLang; $sk = $wgUser->getSkin(); - while( $s = wfFetchObject( $res ) ) { + while( $s = $dbr->fetchObject( $res ) ) { $t = Title::makeTitle( $s->wl_namespace, $s->wl_title ); if( is_null( $t ) ) { $wgOut->addHTML( '\n" ); @@ -140,11 +143,11 @@ function wfSpecialWatchlist() $wgLang->formatNum( $nitems ), $wgLang->formatNum( $npages ), $y, $specialTitle->escapeLocalUrl( "magic=yes" ) ) . "
              \n" ); - $use_index = wfUseIndexClause( $x, DB_READ ); + $use_index = $dbr->useIndexClause( $x ); $sql = "SELECT cur_namespace,cur_title,cur_comment, cur_id, cur_user,cur_user_text,cur_timestamp,cur_minor_edit,cur_is_new - FROM watchlist,cur $use_index + FROM $watchlist,$cur $use_index WHERE wl_user=$uid AND $z AND wl_title=cur_title @@ -152,7 +155,7 @@ function wfSpecialWatchlist() ORDER BY cur_timestamp DESC"; - $res = wfQuery( $sql, DB_READ, $fname ); + $res = $dbr->query( $sql, $fname ); if($days >= 1) $note = wfMsg( "rcnote", $wgLang->formatNum( $limit ), $wgLang->formatNum( $days ) ); @@ -164,7 +167,7 @@ function wfSpecialWatchlist() $note = wlCutoffLinks( $days, $limit ); $wgOut->addHTML( "{$note}\n" ); - if ( wfNumRows( $res ) == 0 ) { + if ( $dbr->numRows( $res ) == 0 ) { $wgOut->addHTML( "

              " . wfMsg( "watchnochange" ) . "

              " ); return; } @@ -172,7 +175,7 @@ function wfSpecialWatchlist() $sk = $wgUser->getSkin(); $s = $sk->beginRecentChangesList(); $counter = 1; - while ( $obj = wfFetchObject( $res ) ) { + while ( $obj = $dbr->fetchObject( $res ) ) { # Make fake RC entry $rc = RecentChange::newFromCurRow( $obj ); $rc->counter = $counter++; @@ -180,7 +183,7 @@ function wfSpecialWatchlist() } $s .= $sk->endRecentChangesList(); - wfFreeResult( $res ); + $dbr->freeResult( $res ); $wgOut->addHTML( $s ); if ( $wgUseWatchlistCache ) { diff --git a/includes/SpecialWhatlinkshere.php b/includes/SpecialWhatlinkshere.php index d8770bb438..92a4931b45 100644 --- a/includes/SpecialWhatlinkshere.php +++ b/includes/SpecialWhatlinkshere.php @@ -28,19 +28,21 @@ function wfSpecialWhatlinkshere($par = NULL) $isredir = " (" . wfMsg( "isredirect" ) . ")\n"; $wgOut->addHTML("< ".$sk->makeKnownLinkObj($nt, "", "redirect=no" )."
              \n"); - + $dbr =& wfGetDB( DB_SLAVE ); + extract( $dbr->tableNames( 'cur', 'brokenlinks', 'links' ) ); + if ( 0 == $id ) { - $sql = "SELECT cur_id,cur_namespace,cur_title,cur_is_redirect FROM brokenlinks,cur WHERE bl_to='" . - wfStrencode( $nt->getPrefixedDBkey() ) . "' AND bl_from=cur_id LIMIT $limit"; - $res = wfQuery( $sql, DB_READ, $fname ); + $sql = "SELECT cur_id,cur_namespace,cur_title,cur_is_redirect FROM $brokenlinks,$cur WHERE bl_to='" . + $dbr->strencode( $nt->getPrefixedDBkey() ) . "' AND bl_from=cur_id LIMIT $limit"; + $res = $dbr->query( $sql, $fname ); - if ( 0 == wfNumRows( $res ) ) { + if ( 0 == $dbr->numRows( $res ) ) { $wgOut->addHTML( wfMsg( "nolinkshere" ) ); } else { $wgOut->addHTML( wfMsg( "linkshere" ) ); $wgOut->addHTML( "\n
                " ); - while ( $row = wfFetchObject( $res ) ) { + while ( $row = $dbr->fetchObject( $res ) ) { $nt = Title::makeTitle( $row->cur_namespace, $row->cur_title ); if( !$nt ) { continue; @@ -55,7 +57,7 @@ function wfSpecialWhatlinkshere($par = NULL) $wgOut->addHTML( "\n" ); } $wgOut->addHTML( "
              \n" ); - wfFreeResult( $res ); + $dbr->freeResult( $res ); } } else { wfShowIndirectLinks( 0, $id, $limit ); @@ -67,10 +69,13 @@ function wfShowIndirectLinks( $level, $lid, $limit ) global $wgOut, $wgUser; $fname = "wfShowIndirectLinks"; - $sql = "SELECT cur_id,cur_namespace,cur_title,cur_is_redirect FROM links,cur WHERE l_to={$lid} AND l_from=cur_id LIMIT $limit"; - $res = wfQuery( $sql, DB_READ, $fname ); + $dbr =& wfGetDB( DB_READ ); + extract( $dbr->tableNames( 'links','cur' ) ); + + $sql = "SELECT cur_id,cur_namespace,cur_title,cur_is_redirect FROM $links,$cur WHERE l_to={$lid} AND l_from=cur_id LIMIT $limit"; + $res = $dbr->query( $sql, $fname ); - if ( 0 == wfNumRows( $res ) ) { + if ( 0 == $dbr->numRows( $res ) ) { if ( 0 == $level ) { $wgOut->addHTML( wfMsg( "nolinkshere" ) ); } @@ -83,27 +88,27 @@ function wfShowIndirectLinks( $level, $lid, $limit ) $isredir = " (" . wfMsg( "isredirect" ) . ")\n"; $wgOut->addHTML( "
                " ); - while ( $row = wfFetchObject( $res ) ) { + while ( $row = $dbr->fetchObject( $res ) ) { $nt = Title::makeTitle( $row->cur_namespace, $row->cur_title ); if( !$nt ) { $wgOut->addHTML( "\n" ); continue; } - + if ( $row->cur_is_redirect ) { - $extra = "redirect=no"; + $extra = "redirect=no"; } else { - $extra = ""; + $extra = ""; } - + $link = $sk->makeKnownLinkObj( $nt, "", $extra ); $wgOut->addHTML( "
              • {$link}" ); if ( $row->cur_is_redirect ) { - $wgOut->addHTML( $isredir ); - if ( $level < 2 ) { - wfShowIndirectLinks( $level + 1, $row->cur_id, $limit ); - } + $wgOut->addHTML( $isredir ); + if ( $level < 2 ) { + wfShowIndirectLinks( $level + 1, $row->cur_id, $limit ); + } } $wgOut->addHTML( "
              • \n" ); } diff --git a/includes/SquidUpdate.php b/includes/SquidUpdate.php index 154b3d553e..d78bdca761 100644 --- a/includes/SquidUpdate.php +++ b/includes/SquidUpdate.php @@ -18,36 +18,54 @@ class SquidUpdate { } /* static */ function newFromLinksTo( &$title ) { + $fname = 'SquidUpdate::newFromLinksTo'; + wfProfileIn( $fname ); + # Get a list of URLs linking to this page $id = $title->getArticleID(); - $sql = "SELECT cur_namespace,cur_title FROM links,cur WHERE l_to={$id} and l_from=cur_id" ; - $res = wfQuery ( $sql, DB_READ ) ; + + $dbr =& wfGetDB( DB_SLAVE ); + $links = $dbr->tableName( 'links' ); + $cur = $dbr->tableName( 'cur' ); + + $sql = "SELECT cur_namespace,cur_title FROM $links,$cur WHERE l_to={$id} and l_from=cur_id" ; + $res = $dbr->query( $sql, $fname ) ; $blurlArr = $title->getSquidURLs(); - if ( wfNumRows( $res ) <= $this->mMaxTitles ) { - while ( $BL = wfFetchObject ( $res ) ) + if ( $dbr->numRows( $res ) <= $this->mMaxTitles ) { + while ( $BL = $dbr->fetchObject ( $res ) ) { $tobj = Title::makeTitle( $BL->cur_namespace, $BL->cur_title ) ; $blurlArr[] = $tobj->getInternalURL(); } } - wfFreeResult ( $res ) ; + $dbr->freeResult ( $res ) ; + + wfProfileOut( $fname ); return new SquidUpdate( $blurlArr ); } /* static */ function newFromBrokenLinksTo( &$title ) { + $fname = 'SquidUpdate::newFromBrokenLinksTo'; + wfProfileIn( $fname ); + # Get a list of URLs linking to this (currently non-existent) page - $encTitle = $title->getPrefixedDBkey(); - $sql = "SELECT cur_namespace,cur_title FROM brokenlinks,cur WHERE bl_to={$encTitle} AND bl_from=cur_id"; - $res = wfQuery( $sql, DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); + $brokenlinks = $dbr->tableName( 'brokenlinks' ); + $cur = $dbr->tableName( 'cur' ); + $encTitle = $dbr->addQuotes( $title->getPrefixedDBkey() ); + + $sql = "SELECT cur_namespace,cur_title FROM $brokenlinks,$cur WHERE bl_to={$encTitle} AND bl_from=cur_id"; + $res = $dbr->query( $sql, $fname ); $blurlArr = array(); - if ( wfNumRows( $res ) <= $this->mMaxTitles ) { - while ( $BL = wfFetchObject( $res ) ) + if ( $dbr->numRows( $res ) <= $this->mMaxTitles ) { + while ( $BL = $dbr->fetchObject( $res ) ) { $tobj = Title::makeTitle( $BL->cur_namespace, $BL->cur_title ); $blurlArr[] = $tobj->getInternalURL(); } } - wfFreeResult( $res ); + $dbr->freeResult( $res ); + wfProfileOut( $fname ); return new SquidUpdate( $blurlArr ); } @@ -73,6 +91,9 @@ class SquidUpdate { return; } + $fname = 'SquidUpdate::purge'; + wfProfileIn( $fname ); + $maxsocketspersquid = 8; // socket cap per Squid $urlspersocket = 400; // 400 seems to be a good tradeoff, opening a socket takes a while $firsturl = $urlArr[0]; @@ -169,6 +190,7 @@ class SquidUpdate { @fclose($socket); } #$this->debug("\n"); + wfProfileOut( $fname ); } function debug( $text ) { diff --git a/includes/Title.php b/includes/Title.php index 14728c8338..b2f39bc864 100644 --- a/includes/Title.php +++ b/includes/Title.php @@ -110,7 +110,7 @@ class Title { $t->mDbkeyform = str_replace( " ", "_", $s ); if( $t->secureAndSplit() ) { # check that length of title is < cur_title size - $dbr =& wfGetDB( DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); $maxSize = $dbr->textFieldSize( 'cur', 'cur_title' ); if ( $maxSize != -1 && strlen( $t->mDbkeyform ) > $maxSize ) { return NULL; @@ -128,7 +128,7 @@ class Title { /* static */ function newFromID( $id ) { $fname = "Title::newFromID"; - $dbr =& wfGetDB( DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); $row = $dbr->getArray( "cur", array( "cur_namespace", "cur_title" ), array( "cur_id" => $id ), $fname ); if ( $row !== false ) { @@ -164,7 +164,7 @@ class Title { /* static */ function nameOf( $id ) { $fname = 'Title::nameOf'; - $dbr =& wfGetDB( DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); $s = $dbr->getArray( 'cur', array( 'cur_namespace','cur_title' ), array( 'cur_id' => $id ), $fname ); if ( $s === false ) { return NULL; } @@ -247,7 +247,7 @@ class Title { $wgTitleInterwikiCache[$k] = $s; return $s->iw_url; } - $dbr =& wfGetDB( DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); $res = $dbr->select( 'interwiki', array( 'iw_url', 'iw_local' ), array( 'iw_prefix' => $key ), $fname ); if(!$res) return ""; @@ -285,7 +285,7 @@ class Title { if ( $timestamp == "" ) { $timestamp = wfTimestampNow(); } - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); $cur = $dbw->tableName( 'cur' ); $sql = "UPDATE $cur SET cur_touched='{$timestamp}' WHERE cur_id IN ("; $first = true; @@ -558,7 +558,7 @@ class Title { if ( 0 == $id ) { return array(); } if ( ! $this->mRestrictionsLoaded ) { - $dbr =& wfGetDB( DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); $res = $dbr->getField( "cur", "cur_restrictions", "cur_id=$id" ); $this->mRestrictions = explode( ",", trim( $res ) ); $this->mRestrictionsLoaded = true; @@ -570,7 +570,7 @@ class Title { # Returns the number of archived revisions function isDeleted() { $fname = 'Title::isDeleted'; - $dbr =& wfGetDB( DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); $n = $dbr->getField( 'archive', 'COUNT(*)', array( 'ar_namespace' => $this->getNamespace(), 'ar_title' => $this->getDBkey() ), $fname ); return (int)$n; @@ -605,7 +605,7 @@ class Title { # Called from LinksUpdate.php function invalidateCache() { $now = wfTimestampNow(); - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); $success = $dbw->updateArray( 'cur', array( /* SET */ 'cur_touched' => wfTimestampNow() @@ -776,9 +776,9 @@ class Title { $id = $this->getArticleID(); if ( $options ) { - $db =& wfGetDB( DB_WRITE ); + $db =& wfGetDB( DB_MASTER ); } else { - $db =& wfGetDB( DB_READ ); + $db =& wfGetDB( DB_SLAVE ); } $cur = $db->tableName( 'cur' ); $links = $db->tableName( 'links' ); @@ -804,9 +804,9 @@ class Title { global $wgLinkCache; if ( $options ) { - $db =& wfGetDB( DB_WRITE ); + $db =& wfGetDB( DB_MASTER ); } else { - $db =& wfGetDB( DB_READ ); + $db =& wfGetDB( DB_SLAVE ); } $cur = $db->tableName( 'cur' ); $brokenlinks = $db->tableName( 'brokenlinks' ); @@ -912,7 +912,7 @@ class Title { $won = wfInvertTimestamp( $now ); $newid = $nt->getArticleID(); $oldid = $this->getArticleID(); - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); $links = $dbw->tableName( 'links' ); # Change the name of the target page: @@ -1008,7 +1008,7 @@ class Title { $sql .= "($id, $oldid)"; } - $dbw->query( $sql, DB_WRITE, $fname ); + $dbw->query( $sql, DB_MASTER, $fname ); } # Now, we record the link from the redirect to the new title. @@ -1041,7 +1041,7 @@ class Title { $won = wfInvertTimestamp( $now ); $newid = $nt->getArticleID(); $oldid = $this->getArticleID(); - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); # Rename cur entry $dbw->updateArray( 'cur', @@ -1122,7 +1122,7 @@ class Title { function isValidMoveTarget( $nt ) { $fname = "Title::isValidMoveTarget"; - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); # Is it a redirect? $id = $nt->getArticleID(); @@ -1163,7 +1163,7 @@ class Title { } $fname = "Title::createRedirect"; - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); $now = wfTimestampNow(); $won = wfInvertTimestamp( $now ); $seqVal = $dbw->nextSequenceValue( 'cur_cur_id_seq' ); @@ -1216,7 +1216,7 @@ class Title { $cns = Namespace::getCategory(); $sk =& $wgUser->getSkin(); $parents = array(); - $dbr =& wfGetDB( DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); $cur = $dbr->tableName( 'cur' ); $categorylinks = $dbr->tableName( 'categorylinks' ); @@ -1286,6 +1286,13 @@ class Title { else { return ''; }; } - + # Returns an associative array for selecting this title from cur + function curCond() { + return array( 'cur_namespace' => $this->mNamespace, 'cur_title' => $this->mDbkeyform ); + } + + function oldCond() { + return array( 'old_namespace' => $this->mNamespace, 'old_title' => $this->mDbkeyform ); + } } ?> diff --git a/includes/User.php b/includes/User.php index 322ae18dd8..9170ce7eed 100644 --- a/includes/User.php +++ b/includes/User.php @@ -11,7 +11,8 @@ class User { /* private */ var $mBlockedby, $mBlockreason; /* private */ var $mTouched; /* private */ var $mCookiePassword; - /* private */ var $mRealName; + /* private */ var $mRealName; + /* private */ var $mHash; function User() { $this->loadDefaults(); @@ -30,28 +31,29 @@ class User { } /* static */ function whoIs( $id ) { - return wfGetSQL( 'user', 'user_name', 'user_id='.$id ); + $dbr =& wfGetDB( DB_SLAVE ); + return $dbr->getField( 'user', 'user_name', array( 'user_id' => $id ) ); } /* static */ function whoIsReal( $id ) { - return wfGetSQL( 'user', 'user_real_name', 'user_id='.$id ); + $dbr =& wfGetDB( DB_SLAVE ); + return $dbr->getField( 'user', 'user_real_name', array( 'user_id' => $id ) ); } /* static */ function idFromName( $name ) { + $fname = "User::idFromName"; + $nt = Title::newFromText( $name ); if( is_null( $nt ) ) { # Illegal name return null; } - $sql = "SELECT user_id FROM user WHERE user_name='" . - wfStrencode( $nt->getText() ) . "'"; - $res = wfQuery( $sql, DB_READ, 'User::idFromName' ); + $dbr =& wfGetDB( DB_SLAVE ); + $s = $dbr->getArray( 'user', array( 'user_id' ), array( 'user_name' => $nt->getText() ), $fname ); - if ( 0 == wfNumRows( $res ) ) { + if ( $s === false ) { return 0; } else { - $s = wfFetchObject( $res ); - wfFreeResult( $res ); return $s->user_id; } } @@ -66,7 +68,6 @@ class User { $pwchars = 'ABCDEFGHJKLMNPQRSTUVWXYZabcdefghjkmnpqrstuvwxyz'; $l = strlen( $pwchars ) - 1; - wfSeedRandom(); $np = $pwchars{mt_rand( 0, $l )} . $pwchars{mt_rand( 0, $l )} . $pwchars{mt_rand( 0, $l )} . chr( mt_rand(48, 57) ) . $pwchars{mt_rand( 0, $l )} . $pwchars{mt_rand( 0, $l )} . @@ -95,6 +96,7 @@ class User { $this->mBlockedby = -1; # Unset $this->mTouched = '0'; # Allow any pages to be cached $this->cookiePassword = ''; + $this->mHash = false; } /* private */ function getBlockedStatus() @@ -221,6 +223,7 @@ class User { function loadFromDatabase() { global $wgCommandLineMode; + $fname = "User::loadFromDatabase"; if ( $this->mDataLoaded || $wgCommandLineMode ) { return; } @@ -230,24 +233,23 @@ class User { # check in separate table if there are changes to the talk page $this->mNewtalk=0; # reset talk page status + $dbr =& wfGetDB( DB_SLAVE ); if($this->mId) { - $sql = "SELECT 1 FROM user_newtalk WHERE user_id={$this->mId}"; - $res = wfQuery ($sql, DB_READ, "User::loadFromDatabase" ); + $res = $dbr->select( 'user_newtalk', 1, array( 'user_id' => $this->mId ), $fname ); - if (wfNumRows($res)>0) { + if ( $dbr->numRows($res)>0 ) { $this->mNewtalk= 1; } - wfFreeResult( $res ); + $dbr->freeResult( $res ); } else { global $wgDBname, $wgMemc; $key = "$wgDBname:newtalk:ip:{$this->mName}"; $newtalk = $wgMemc->get( $key ); if( ! is_integer( $newtalk ) ){ - $sql = "SELECT 1 FROM user_newtalk WHERE user_ip='{$this->mName}'"; - $res = wfQuery ($sql, DB_READ, "User::loadFromDatabase" ); + $res = $dbr->select( 'user_newtalk', 1, array( 'user_ip' => $this->mName ), $fname ); - $this->mNewtalk = (wfNumRows($res)>0) ? 1 : 0; - wfFreeResult( $res ); + $this->mNewtalk = $dbr->numRows( $res ) > 0 ? 1 : 0; + $dbr->freeResult( $res ); $wgMemc->set( $key, $this->mNewtalk, time() ); // + 1800 ); } else { @@ -259,13 +261,11 @@ class User { return; } # the following stuff is for non-anonymous users only - $sql = "SELECT user_name,user_password,user_newpassword,user_email," . - "user_real_name,user_options,user_rights,user_touched " . - " FROM user WHERE user_id=" . $this->mId; - $res = wfQuery( $sql, DB_READ, "User::loadFromDatabase" ); + $s = $dbr->getArray( 'user', array( 'user_name','user_password','user_newpassword','user_email', + 'user_real_name','user_options','user_rights','user_touched' ), + array( 'user_id' => $this->mId ), $fname ); - if ( wfNumRows( $res ) > 0 ) { - $s = wfFetchObject( $res ); + if ( $s !== false ) { $this->mName = $s->user_name; $this->mEmail = $s->user_email; $this->mRealName = $s->user_real_name; @@ -276,7 +276,6 @@ class User { $this->mTouched = $s->user_touched; } - wfFreeResult( $res ); $this->mDataLoaded = true; } @@ -514,7 +513,7 @@ class User { array_push( $a, $oname.'='.$oval ); } $s = implode( "\n", $a ); - return wfStrencode( $s ); + return $s; } /* private */ function decodeOptions( $str ) { @@ -558,65 +557,71 @@ class User { function saveSettings() { global $wgMemc, $wgDBname; + $fname = 'User::saveSettings'; + $dbw =& wfGetDB( DB_MASTER ); if ( ! $this->mNewtalk ) { + # Delete user_newtalk row if( $this->mId ) { - $sql="DELETE FROM user_newtalk WHERE user_id={$this->mId}"; - wfQuery ($sql, DB_WRITE, "User::saveSettings"); + $dbw->delete( 'user_newtalk', array( 'user_id' => $this->mId ), $fname ); } else { - $sql="DELETE FROM user_newtalk WHERE user_ip='{$this->mName}'"; - wfQuery ($sql, DB_WRITE, "User::saveSettings"); + $dbw->delete( 'user_newtalk', array( 'user_ip' => $this->mName ), $fname ); $wgMemc->delete( "$wgDBname:newtalk:ip:{$this->mName}" ); } } if ( 0 == $this->mId ) { return; } - $sql = "UPDATE user SET " . - "user_name= '" . wfStrencode( $this->mName ) . "', " . - "user_password= '" . wfStrencode( $this->mPassword ) . "', " . - "user_newpassword= '" . wfStrencode( $this->mNewpassword ) . "', " . - "user_real_name= '" . wfStrencode( $this->mRealName ) . "', " . - "user_email= '" . wfStrencode( $this->mEmail ) . "', " . - "user_options= '" . $this->encodeOptions() . "', " . - "user_rights= '" . wfStrencode( implode( ",", $this->mRights ) ) . "', " . - "user_touched= '" . wfStrencode( $this->mTouched ) . - "' WHERE user_id={$this->mId}"; - wfQuery( $sql, DB_WRITE, "User::saveSettings" ); + $dbw->update( 'user', + array( /* SET */ + 'user_name' => $this->mName, + 'user_password' => $this->mPassword, + 'user_newpassword' => $this->mNewpassword, + 'user_real_name' => $this->mRealName, + 'user_email' => $this->mEmail, + 'user_options' => $this->encodeOptions(), + 'user_rights' => implode( ",", $this->mRights ), + 'user_touched' => $this->mTouched + ), array( /* WHERE */ + 'user_id' => $this->mId + ), $fname + ); $wgMemc->delete( "$wgDBname:user:id:$this->mId" ); } - # Checks if a user with the given name exists + # Checks if a user with the given name exists, returns the ID # function idForName() { + $fname = 'User::idForName'; + $gotid = 0; $s = trim( $this->mName ); if ( 0 == strcmp( '', $s ) ) return 0; - - $sql = "SELECT user_id FROM user WHERE user_name='" . - wfStrencode( $s ) . "'"; - $res = wfQuery( $sql, DB_READ, "User::idForName" ); - if ( 0 == wfNumRows( $res ) ) { return 0; } - - $s = wfFetchObject( $res ); - if ( '' == $s ) return 0; - - $gotid = $s->user_id; - wfFreeResult( $res ); - return $gotid; + + $dbr =& wfGetDB( DB_SLAVE ); + $id = $dbr->selectField( 'user', 'user_id', array( 'user_name' => $s ), $fname ); + if ( $id === false ) { + $id = 0; + } + return $id; } function addToDatabase() { - $sql = "INSERT INTO user (user_name,user_password,user_newpassword," . - "user_email, user_real_name, user_rights, user_options) " . - " VALUES ('" . wfStrencode( $this->mName ) . "', '" . - wfStrencode( $this->mPassword ) . "', '" . - wfStrencode( $this->mNewpassword ) . "', '" . - wfStrencode( $this->mEmail ) . "', '" . - wfStrencode( $this->mRealName ) . "', '" . - wfStrencode( implode( ',', $this->mRights ) ) . "', '" . - $this->encodeOptions() . "')"; - wfQuery( $sql, DB_WRITE, "User::addToDatabase" ); - $this->mId = $this->idForName(); + $fname = 'User::addToDatabase'; + $dbw =& wfGetDB( DB_MASTER ); + $seqVal = $dbw->nextSequenceValue( 'user_user_id_seq' ); + $dbw->insert( 'user', + array( + 'user_id' => $seqVal, + 'user_name' => $this->mName, + 'user_password' => $this->mPassword, + 'user_newpassword' => $this->mNewpassword, + 'user_email' => $this->mEmail, + 'user_real_name' => $this->mRealName, + 'user_rights' => implode( ',', $this->mRights ), + 'user_options' => $this->encodeOptions() + ), $fname + ); + $this->mId = $dbw->insertId(); } function spreadBlock() @@ -666,19 +671,14 @@ class User { } function getPageRenderingHash(){ - static $hash = false; - if( $hash ){ - return $hash; + if( $this->mHash ){ + return $this->mHash; } // stubthreshold is only included below for completeness, // it will always be 0 when this function is called by parsercache. - $confstr = $this->getOption( 'quickbar' ); - $confstr .= '!' . $this->getOption( 'underline' ); - $confstr .= '!' . $this->getOption( 'hover' ); - $confstr .= '!' . $this->getOption( 'skin' ); - $confstr .= '!' . $this->getOption( 'math' ); + $confstr = $this->getOption( 'math' ); $confstr .= '!' . $this->getOption( 'highlightbroken' ); $confstr .= '!' . $this->getOption( 'stubthreshold' ); $confstr .= '!' . $this->getOption( 'editsection' ); @@ -686,11 +686,8 @@ class User { $confstr .= '!' . $this->getOption( 'showtoc' ); $confstr .= '!' . $this->getOption( 'date' ); - if(strlen($confstr) > 32) - $hash = md5($confstr); - else - $hash = $confstr; - return $hash; + $this->mHash = $confstr; + return $confstr ; } function isAllowedToCreateAccount() { @@ -709,7 +706,7 @@ class User { # Use this to prevent DB access in command-line scripts or similar situations function setLoaded( $loaded ) { - wfSetVar( $this->mDataLoaded, $loaded ); + return wfSetVar( $this->mDataLoaded, $loaded ); } function getUserPage() { @@ -717,8 +714,8 @@ class User { } /* static */ function getMaxID() { - $row = wfGetArray( 'user', array('max(user_id) as m'), false ); - return $row->m; + $dbr =& wfGetDB( DB_SLAVE ); + return $dbr->selectField( 'user', 'max(user_id)', false ); } function isNewbie() { diff --git a/includes/UserTalkUpdate.php b/includes/UserTalkUpdate.php index 66ea7a9aee..95cfa7e00e 100644 --- a/includes/UserTalkUpdate.php +++ b/includes/UserTalkUpdate.php @@ -34,22 +34,25 @@ class UserTalkUpdate { # Not ours. If writing, mark it as modified. $sql = false; + $dbw =& wfGetDB( DB_MASTER ); + $user_newtalk = $dbw->tableName( 'user_newtalk' ); + if ( 1 == $this->mAction ) { $user = new User(); $user->setID(User::idFromName($this->mTitle)); if ($id=$user->getID()) { - $sql = "INSERT INTO user_newtalk (user_id) values ({$id})"; + $sql = "INSERT INTO $user_newtalk (user_id) values ({$id})"; $wgMemc->delete( "$wgDBname:user:id:$id" ); } else { #anon if(preg_match("/^\d{1,3}\.\d{1,3}.\d{1,3}\.\d{1,3}$/",$this->mTitle)) { #real anon (user:xxx.xxx.xxx.xxx) - $sql = "INSERT INTO user_newtalk (user_id,user_ip) values (0,\"{$this->mTitle}\")"; + $sql = "INSERT INTO $user_newtalk (user_id,user_ip) values (0,\"{$this->mTitle}\")"; $wgMemc->delete( "$wgDBname:newtalk:ip:$this->mTitle" ); } } if($sql && !$user->getNewtalk()) { # only insert if real user and it's not already there - wfQuery( $sql, DB_WRITE, $fname ); + $dbw->query( $sql, $fname ); } } } diff --git a/includes/ViewCountUpdate.php b/includes/ViewCountUpdate.php index 470fa69f61..9b1c7eca6b 100644 --- a/includes/ViewCountUpdate.php +++ b/includes/ViewCountUpdate.php @@ -14,7 +14,7 @@ class ViewCountUpdate { { global $wgDisableCounters; if ( $wgDisableCounters ) { return; } - $db =& wfGetDB( DB_WRITE ); + $db =& wfGetDB( DB_MASTER ); $lowpri = $db->lowPriorityOption(); $sql = "UPDATE $lowpri cur SET cur_counter=(1+cur_counter)," . "cur_timestamp=cur_timestamp WHERE cur_id={$this->mPageID}"; diff --git a/includes/WatchedItem.php b/includes/WatchedItem.php index e2d9506f79..4342fc7a2b 100644 --- a/includes/WatchedItem.php +++ b/includes/WatchedItem.php @@ -1,7 +1,9 @@ mUser =& $user; @@ -9,27 +11,31 @@ class WatchedItem { $wl->id = $user->getId(); $wl->ns = $title->getNamespace() & ~1; $wl->ti = $title->getDBkey(); - $wl->eti = wfStrencode( $wl->ti ); return $wl; } + # Returns the memcached key for this item function watchKey() { global $wgDBname; return "$wgDBname:watchlist:user:$this->id:page:$this->ns:$this->ti"; } + # Is mTitle being watched by mUser? function isWatched() { # Pages and their talk pages are considered equivalent for watching; # remember that talk namespaces are numbered as page namespace+1. global $wgMemc; + $fname = 'WatchedItem::isWatched'; + $key = $this->watchKey(); $iswatched = $wgMemc->get( $key ); if( is_integer( $iswatched ) ) return $iswatched; - $sql = "SELECT 1 FROM watchlist WHERE wl_user=$this->id AND wl_namespace=$this->ns AND wl_title='$this->eti'"; - $res = wfQuery( $sql, DB_READ ); - $iswatched = (wfNumRows( $res ) > 0) ? 1 : 0; + $dbr =& wfGetDB( DB_SLAVE ); + $res = $dbr->select( 'watchlist', 1, array( 'wl_user' => $this->id, 'wl_namespace' => $this->ns, + 'wl_title' => $this->ti ), $fname ); + $iswatched = ($dbr->numRows( $res ) > 0) ? 1 : 0; $wgMemc->set( $key, $iswatched ); return $iswatched; } @@ -39,12 +45,12 @@ class WatchedItem { $fname = "WatchedItem::addWatch"; # REPLACE instead of INSERT because occasionally someone # accidentally reloads a watch-add operation. - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); $dbw->replace( 'watchlist', array(array('wl_user', 'wl_namespace', 'wl_title')), array( 'wl_user' => $this->id, 'wl_namespace' => $this->ns, - 'wl_title' => $this->eti, + 'wl_title' => $this->ti, ), $fname ); global $wgMemc; @@ -54,13 +60,22 @@ class WatchedItem { function removeWatch() { - $sql = "DELETE FROM watchlist WHERE wl_user=$this->id AND wl_namespace=$this->ns AND wl_title='$this->eti'"; - $res = wfQuery( $sql, DB_WRITE ); - if( $res === false ) return false; + $dbw =& wfGetDB( DB_MASTER ); + $dbw->delete( 'watchlist', + array( + 'wl_user' => $this->id, + 'wl_namespace' => $this->ns, + 'wl_title' => $this->ti + ), $fname + ); - global $wgMemc; - $wgMemc->set( $this->watchkey(), 0 ); - return true; + if ( $dbw->affectedRows() ) { + global $wgMemc; + $wgMemc->set( $this->watchkey(), 0 ); + return true; + } else { + return false; + } } /* static */ function duplicateEntries( $ot, $nt ) { @@ -70,25 +85,29 @@ class WatchedItem { $newnamespace = $nt->getNamespace() & ~1; $oldtitle = $ot->getDBkey(); $newtitle = $nt->getDBkey(); - $eoldtitle = wfStrencode( $oldtitle ); - $enewtitle = wfStrencode( $newtitle ); - $sql = "SELECT wl_user FROM watchlist - WHERE wl_namespace={$oldnamespace} AND wl_title='{$eoldtitle}'"; - $res = wfQuery( $sql, DB_READ, $fname ); - if( $s = wfFetchObject( $res ) ) { - $sql = "REPLACE INTO watchlist (wl_user,wl_namespace,wl_title) - VALUES ({$s->wl_user},{$newnamespace},'{$enewtitle}')"; - $key = "$wgDBname:watchlist:user:$s->wl_user:page:$newnamespace:$newtitle"; - $wgMemc->set( $key, 1 ); - while( $s = wfFetchObject( $res ) ) { - $sql .= ",({$s->wl_user},{$newnamespace},'{$enewtitle}')"; - $key = "$wgDBname:watchlist:user:$s->wl_user:page:$newnamespace:$newtitle"; - $wgMemc->set( $key, 1 ); - } - $res = wfQuery( $sql, DB_WRITE, $fname ); - if( $res === false ) return false; # db error? + $dbw =& wfGetDB( DB_MASTER ); + $watchlist = $dbw->tableName( 'watchlist' ); + + $res = $dbw->select( 'watchlist', 'wl_user', + array( 'wl_namespace' => $oldnamespace, 'wl_title' => $oldtitle ), + $fname, 'FOR UPDATE' + ); + # Construct array to replace into the watchlist + $values = array(); + while ( $s = $dbw->fetchObject( $res ) ) { + $values[] = array( + 'wl_user' => $s->wl_user, + 'wl_namespace' => $newnamespace, + 'wl_title' => $newtitle + ); } + $dbw->freeResult( $res ); + + # Perform replace + # Note that multi-row replace is very efficient for MySQL but may be inefficient for + # some other DBMSes, mostly due to poor simulation by us + $dbw->replace( 'watchlist', array(array( 'wl_user', 'wl_namespace', 'wl_title')), $values, $fname ); return true; } diff --git a/index.php b/index.php index 075e721b10..803a5486ae 100644 --- a/index.php +++ b/index.php @@ -54,6 +54,8 @@ if ( !is_null( $wgTitle ) && !$wgTitle->userCanRead() ) { exit; } +$db =& wfGetDB( DB_MASTER ); + if ( $search = $wgRequest->getText( 'search' ) ) { $wgTitle = Title::makeTitle( NS_SPECIAL, "Search" ); if( $wgRequest->getVal( 'fulltext' ) || !is_null( $wgRequest->getVal( 'offset' ) ) ) { @@ -95,8 +97,7 @@ if ( $search = $wgRequest->getText( 'search' ) ) { $wgArticle = new Article( $wgTitle ); } - $db =& wfGetDB( DB_WRITE ); - $db->query("BEGIN", DB_WRITE); + $db->query("BEGIN"); switch( $action ) { case "view": $wgOut->setSquidMaxage( $wgSquidMaxage ); @@ -169,12 +170,13 @@ if ( $search = $wgRequest->getText( 'search' ) ) { $db->query("COMMIT"); } +$wgLoadBalancer->saveMasterPos(); $wgOut->output(); foreach ( $wgDeferredUpdateList as $up ) { - wfQuery("BEGIN", DB_WRITE); + $db->query("BEGIN"); $up->doUpdate(); - wfQuery("COMMIT", DB_WRITE); + $db->query("COMMIT"); } logProfilingData(); wfDebug( "Request ended normally\n" ); diff --git a/install-utils.inc b/install-utils.inc index 2ee841f459..34dd701762 100644 --- a/install-utils.inc +++ b/install-utils.inc @@ -132,11 +132,11 @@ function dbsource( $fname, $database = false ) { # Obsolete, use Database::fieldExists() function field_exists( $table, $field ) { $fname = "Update script: field_exists"; - $db =& wfGetDB( DB_READ ); + $db =& wfGetDB( DB_SLAVE ); $res = $db->query( "DESCRIBE $table", $fname ); $found = false; - while ( $row = wfFetchObject( $res ) ) { + while ( $row = $db->fetchObject( $res ) ) { if ( $row->Field == $field ) { $found = true; break; diff --git a/irc/rcdumper.php b/irc/rcdumper.php index 41052bc533..bcc860d94f 100644 --- a/irc/rcdumper.php +++ b/irc/rcdumper.php @@ -32,16 +32,18 @@ $wgCommandLineMode = true; set_time_limit(0); sleep(30); +$dbr =& wfGetDB( DB_SLAVE ); +$recentchanges = $dbr->tableName( 'recentchanges' ); -$res = wfQuery( "SELECT rc_timestamp FROM recentchanges ORDER BY rc_timestamp DESC LIMIT 1", DB_READ ); -$row = wfFetchObject( $res ); +$res = $dbr->query( "SELECT rc_timestamp FROM $recentchanges ORDER BY rc_timestamp DESC LIMIT 1" ); +$row = $dbr->fetchObject( $res ); $oldTimestamp = $row->rc_timestamp; $serverCount = 0; while (1) { - $res = wfQuery( "SELECT * FROM recentchanges WHERE rc_timestamp>'$oldTimestamp' ORDER BY rc_timestamp", DB_READ ); + $res = $dbr->query( "SELECT * FROM $recentchanges WHERE rc_timestamp>'$oldTimestamp' ORDER BY rc_timestamp" ); $rowIndex = 0; - while ( $row = wfFetchObject( $res ) ) { + while ( $row = $dbr->fetchObject( $res ) ) { if ( ++$serverCount % 20 == 0 ) { print "/server $ircServer\n"; } diff --git a/languages/Language.php b/languages/Language.php index 96790ccc01..0a61d6246d 100644 --- a/languages/Language.php +++ b/languages/Language.php @@ -1350,11 +1350,12 @@ You might want to check the following regular expression for patterns that are c # Info page "infosubtitle" => "Information for page", -"numedits" => "Number of edits (article): ", -"numtalkedits" => "Number of edits (discussion page): ", -"numwatchers" => "Number of watchers: ", -"numauthors" => "Number of distinct authors (article): ", -"numtalkauthors" => "Number of distinct authors (discussion page): ", +"numedits" => "Number of edits (article): $1", +"numtalkedits" => "Number of edits (discussion page): $1", +"numwatchers" => "Number of watchers: $1", +"numauthors" => "Number of distinct authors (article): $1", +"numtalkauthors" => "Number of distinct authors (discussion page): $1", + # Math options 'mw_math_png' => 'Always render PNG', 'mw_math_simple' => 'HTML if very simple or else PNG', diff --git a/maintenance/InitialiseMessages.inc b/maintenance/InitialiseMessages.inc index 699ec66d5e..3f3dff2522 100755 --- a/maintenance/InitialiseMessages.inc +++ b/maintenance/InitialiseMessages.inc @@ -40,7 +40,13 @@ function initialiseMessages( $overwrite = false, $messageArray = false ) { "; print "Initialising \"MediaWiki\" namespace...\n"; - $sql = "SELECT cur_title,cur_is_new,cur_user_text FROM cur WHERE cur_namespace=$ns AND cur_title IN("; + + + $dbr =& wfGetDB( DB_SLAVE ); + $dbw =& wfGetDB( DB_MASTER ); + $cur = $dbr->tableName( 'cur' ); + + $sql = "SELECT cur_title,cur_is_new,cur_user_text FROM $cur WHERE cur_namespace=$ns AND cur_title IN("; # Get keys from $wgAllMessagesEn, which is more complete than the local language $first = true; @@ -51,8 +57,9 @@ function initialiseMessages( $overwrite = false, $messageArray = false ) { } ksort( $sortedArray ); - + # SELECT all existing messages + # Can't afford to be locking all rows for update, this script can take quite a long time to complete foreach ( $sortedArray as $key => $enMsg ) { if ( $key == '' ) { continue; // Skip odd members @@ -63,12 +70,12 @@ function initialiseMessages( $overwrite = false, $messageArray = false ) { $sql .= ','; } $titleObj = Title::newFromText( $key ); - $enctitle = wfStrencode($titleObj->getDBkey()); + $enctitle = $dbr->strencode($titleObj->getDBkey()); $sql .= "'$enctitle'"; } $sql .= ')'; - $res = wfQuery( $sql, DB_READ ); - $row = wfFetchObject( $res ); + $res = $dbr->query( $sql ); + $row = $dbr->fetchObject( $res ); # Read the results into an array # Decide whether or not each one needs to be overwritten @@ -80,12 +87,12 @@ function initialiseMessages( $overwrite = false, $messageArray = false ) { $existingTitles[$row->cur_title] = 'chuck'; } - $row = wfFetchObject( $res ); + $row = $dbr->fetchObject( $res ); } # Insert queries are done in one multi-row insert # Here's the start of it: - $sql = "INSERT INTO cur (cur_namespace, cur_title, cur_text, + $sql = "INSERT INTO $cur (cur_namespace, cur_title, cur_text, cur_user_text, cur_timestamp, cur_restrictions, cur_is_new, inverse_timestamp, cur_touched) VALUES "; $first = true; @@ -105,7 +112,7 @@ function initialiseMessages( $overwrite = false, $messageArray = false ) { } $titleObj = Title::newFromText( $key ); $title = $titleObj->getDBkey(); - $dbencMsg = wfStrencode( $message ); + $dbencMsg = $dbw->strencode( $message ); # Update messages which already exist if ( array_key_exists( $title, $existingTitles ) ) { @@ -150,7 +157,7 @@ $message # Perform the insert query if ( !$first ) { - wfQuery( $sql, DB_WRITE, $fname ); + $dbw->query( $sql, $fname ); } # Write the navigation page diff --git a/maintenance/archives/convertdb.php b/maintenance/archives/convertdb.php index 4b330fa7f8..3950fabb08 100644 --- a/maintenance/archives/convertdb.php +++ b/maintenance/archives/convertdb.php @@ -63,14 +63,14 @@ function convertUserTable() print "Converting USER table.\n"; $sql = "LOCK TABLES old_user READ, user WRITE"; - $newres = wfQuery( $sql, DB_WRITE ); + $newres = wfQuery( $sql, DB_MASTER ); $sql = "SELECT user_id,user_name,user_rights,user_password," . "user_email,user_options,user_watch FROM old_user"; - $oldres = wfQuery( $sql, DB_READ ); + $oldres = wfQuery( $sql, DB_SLAVE ); $sql = "DELETE FROM user"; - $newres = wfQuery( $sql, DB_WRITE ); + $newres = wfQuery( $sql, DB_MASTER ); $sql = ""; while ( $row = mysql_fetch_object( $oldres ) ) { @@ -78,7 +78,7 @@ function convertUserTable() if ( "" == $name ) continue; # Don't convert illegal names if ( 0 == ( $count % 10 ) ) { - if ( 0 != $count ) { $newres = wfQuery( $sql, DB_WRITE ); } + if ( 0 != $count ) { $newres = wfQuery( $sql, DB_MASTER ); } $sql = "INSERT INTO user (user_id,user_name,user_rights," . "user_password,user_newpassword,user_email,user_options," . @@ -99,13 +99,13 @@ function convertUserTable() print "$count user records processed.\n"; } } - if ( $sql ) { $newres = wfQuery( $sql, DB_WRITE ); } + if ( $sql ) { $newres = wfQuery( $sql, DB_MASTER ); } print "$count user records processed.\n"; mysql_free_result( $oldres ); $sql = "UNLOCK TABLES"; - $newres = wfQuery( $sql, DB_WRITE ); + $newres = wfQuery( $sql, DB_MASTER ); } # Convert May 2002 version of database into new format. @@ -116,18 +116,18 @@ function convertCurTable() print "Converting CUR table.\n"; $sql = "LOCK TABLES old_cur READ, cur WRITE, site_stats WRITE"; - $newres = wfQuery( $sql, DB_WRITE ); + $newres = wfQuery( $sql, DB_MASTER ); $sql = "SELECT cur_id,cur_title,cur_text,cur_comment,cur_user," . "cur_timestamp,cur_minor_edit,cur_restrictions," . "cur_counter,cur_ind_title,cur_user_text FROM old_cur"; - $oldres = wfQuery( $sql, DB_READ ); + $oldres = wfQuery( $sql, DB_SLAVE ); $sql = "DELETE FROM cur"; - wfQuery( $sql, DB_WRITE ); + wfQuery( $sql, DB_MASTER ); $sql = "DELETE FROM site_stats"; - wfQuery( $sql, DB_WRITE ); + wfQuery( $sql, DB_MASTER ); $sql = ""; while ( $row = mysql_fetch_object( $oldres ) ) { @@ -166,7 +166,7 @@ function convertCurTable() "'{$com}',{$row->cur_user},'{$row->cur_timestamp}'," . "{$isme},{$isnew},'{$cr}',0,'{$ititle}','{$itext}'," . "{$redir},'{$cut}')"; - wfQuery( $sql, DB_WRITE ); + wfQuery( $sql, DB_MASTER ); if ( ( ++$count % 1000 ) == 0 ) { print "$count article records processed.\n"; @@ -181,10 +181,10 @@ function convertCurTable() $sql = "REPLACE INTO site_stats (ss_row_id,ss_total_views," . "ss_total_edits,ss_good_articles) VALUES (1,0,0,{$countables})"; - wfQuery( $sql, DB_WRITE ); + wfQuery( $sql, DB_MASTER ); $sql = "UNLOCK TABLES"; - $newres = wfQuery( $sql, DB_WRITE ); + $newres = wfQuery( $sql, DB_MASTER ); } # Convert May 2002 version of database into new format. @@ -195,14 +195,14 @@ function convertOldTable() print "Converting OLD table.\n"; $sql = "LOCK TABLES old_old READ, old WRITE"; - $newres = wfQuery( $sql, DB_WRITE ); + $newres = wfQuery( $sql, DB_MASTER ); $sql = "SELECT old_id,old_title,old_text,old_comment,old_user," . "old_timestamp,old_minor_edit,old_user_text FROM old_old"; - $oldres = wfQuery( $sql, DB_READ ); + $oldres = wfQuery( $sql, DB_SLAVE ); $sql = "DELETE FROM old"; - $newres = wfQuery( $sql, DB_WRITE ); + $newres = wfQuery( $sql, DB_MASTER ); while ( $row = mysql_fetch_object( $oldres ) ) { $nt = Title::newFromDBkey( $row->old_title ); @@ -231,7 +231,7 @@ function convertOldTable() $sql .= "({$row->old_id},{$ns},'{$title}','{$text}'," . "'{$com}',{$row->old_user},'{$row->old_timestamp}'," . "{$isme},'{$cut}')"; - wfQuery( $sql, DB_WRITE ); + wfQuery( $sql, DB_MASTER ); if ( ( ++$count % 1000 ) == 0 ) { print "$count history records processed.\n"; @@ -241,7 +241,7 @@ function convertOldTable() mysql_free_result( $oldres ); $sql = "UNLOCK TABLES"; - $newres = wfQuery( $sql, DB_WRITE ); + $newres = wfQuery( $sql, DB_MASTER ); } function convertImageDirectoriesX() @@ -284,14 +284,14 @@ function convertImageDirectoriesX() $sql = "DELETE FROM image WHERE img_name='" . addslashes( $nname ) . "'"; - $res = wfQuery( $sql, DB_WRITE ); + $res = wfQuery( $sql, DB_MASTER ); $sql = "INSERT INTO image (img_name,img_timestamp,img_user," . "img_user_text,img_size,img_description) VALUES ('" . addslashes( $nname ) . "','" . date( "YmdHis" ) . "',0,'(Automated conversion)','" . filesize( "{$dest}/{$nname}" ) . "','')"; - $res = wfQuery( $sql, DB_WRITE ); + $res = wfQuery( $sql, DB_MASTER ); } else { die( "Couldn't copy \"{$oname}\" to \"{$nname}\"\n" ); } @@ -306,7 +306,7 @@ function convertImageDirectories() $sql = "SELECT DISTINCT il_to FROM imagelinks"; - $result = wfQuery ( $sql, DB_READ ) ; + $result = wfQuery ( $sql, DB_SLAVE ) ; while ( $row = mysql_fetch_object ( $result ) ) { $oname = $row->il_to ; @@ -347,14 +347,14 @@ function convertImageDirectories() $sql = "DELETE FROM image WHERE img_name='" . addslashes( $nname ) . "'"; - $res = wfQuery( $sql, DB_WRITE ); + $res = wfQuery( $sql, DB_MASTER ); $sql = "INSERT INTO image (img_name,img_timestamp,img_user," . "img_user_text,img_size,img_description) VALUES ('" . addslashes( $nname ) . "','" . date( "YmdHis" ) . "',0,'(Automated conversion)','" . filesize( "{$dest}/{$nname}" ) . "','')"; - $res = wfQuery( $sql, DB_WRITE ); + $res = wfQuery( $sql, DB_MASTER ); } else { echo( "Couldn't copy \"{$oname}\" to \"{$nname}\"\n" ); } @@ -557,36 +557,36 @@ function refillRandom() $sql = "INSERT INTO random(ra_current,ra_title) SELECT 0,cur_title " . "FROM cur WHERE cur_namespace=0 AND cur_is_redirect=0 " . "ORDER BY RAND() LIMIT 1000"; - wfQuery( $sql, DB_WRITE, $fname ); + wfQuery( $sql, DB_MASTER, $fname ); $sql = "UPDATE random SET ra_current=(ra_current+1)"; - wfQuery( $sql, DB_WRITE, $fname ); + wfQuery( $sql, DB_MASTER, $fname ); $sql = "DELETE FROM random WHERE ra_current>1"; - wfQuery( $sql, DB_WRITE, $fname ); + wfQuery( $sql, DB_MASTER, $fname ); } function renameOldTables() { $sql = "ALTER TABLE user RENAME TO old_user"; - wfQuery( $sql, DB_WRITE ); + wfQuery( $sql, DB_MASTER ); $sql = "ALTER TABLE cur RENAME TO old_cur"; - wfQuery( $sql, DB_WRITE ); + wfQuery( $sql, DB_MASTER ); $sql = "ALTER TABLE old RENAME TO old_old"; - wfQuery( $sql, DB_WRITE ); + wfQuery( $sql, DB_MASTER ); $sql = "DROP TABLE IF EXISTS linked"; - wfQuery( $sql, DB_WRITE ); + wfQuery( $sql, DB_MASTER ); $sql = "DROP TABLE IF EXISTS unlinked"; - wfQuery( $sql, DB_WRITE ); + wfQuery( $sql, DB_MASTER ); } function removeOldTables() { - wfQuery( "DROP TABLE IF EXISTS old_user", DB_WRITE ); - wfQuery( "DROP TABLE IF EXISTS old_linked", DB_WRITE ); - wfQuery( "DROP TABLE IF EXISTS old_unlinked", DB_WRITE ); - wfQuery( "DROP TABLE IF EXISTS old_cur", DB_WRITE ); - wfQuery( "DROP TABLE IF EXISTS old_old", DB_WRITE ); + wfQuery( "DROP TABLE IF EXISTS old_user", DB_MASTER ); + wfQuery( "DROP TABLE IF EXISTS old_linked", DB_MASTER ); + wfQuery( "DROP TABLE IF EXISTS old_unlinked", DB_MASTER ); + wfQuery( "DROP TABLE IF EXISTS old_cur", DB_MASTER ); + wfQuery( "DROP TABLE IF EXISTS old_old", DB_MASTER ); } ?> diff --git a/maintenance/archives/moveCustomMessages.inc b/maintenance/archives/moveCustomMessages.inc index 5438194690..e4eadd5e70 100644 --- a/maintenance/archives/moveCustomMessages.inc +++ b/maintenance/archives/moveCustomMessages.inc @@ -1,9 +1,11 @@ select( 'cur', 1, array( 'cur_namespace' => NS_TEMPLATE ), $fname, array( 'LIMIT' => 1 ) ); + return $dbw->numRows( $res ) ? true : false; } function moveCustomMessages( $phase ) { @@ -15,7 +17,9 @@ function moveCustomMessages( $phase ) { $wgUser->setName( "Template namespace initialisation script" ); $wgUser->addRight( "bot" ); - wfIgnoreSQLErrors( true ); + $dbw =& wfGetDB( DB_MASTER ); + + $dbw->setIgnoreErrors( true ); # Compose DB key array $dbkeys = array(); @@ -25,17 +29,16 @@ function moveCustomMessages( $phase ) { $dbkeys[$title->getDBkey()] = 1; } - $sql = "SELECT cur_id, cur_title FROM cur WHERE cur_namespace= " . NS_MEDIAWIKI; - $res = wfQuery( $sql, DB_READ ); + $res = $dbw->select( 'cur', array( 'cur_id', 'cur_title' ), array( 'cur_namespace' => NS_MEDIAWIKI ) ); # Compile target array $targets = array(); - while ( $row = wfFetchObject( $res ) ) { + while ( $row = $dbw->fetchObject( $res ) ) { if ( !array_key_exists( $row->cur_title, $dbkeys ) ) { $targets[$row->cur_title] = 1; } } - wfFreeResult( $res ); + $dbw->freeResult( $res ); # Create redirects from destination to source if ( $phase == 0 || $phase == 1 ) { @@ -61,7 +64,7 @@ function moveCustomMessages( $phase ) { if ( $phase == 0 || $phase == 2 ) { print "\nMoving pages...\n"; foreach ( $targets as $partial => $dummy ) { - wfQuery( "BEGIN", DB_WRITE ); + $dbw->query( "BEGIN" ); $ot = Title::makeTitle( NS_MEDIAWIKI, $partial ); $nt = Title::makeTitle( NS_TEMPLATE, $partial ); print "$partial..."; @@ -76,7 +79,7 @@ function moveCustomMessages( $phase ) { $up = array_pop( $wgDeferredUpdateList ); $up->doUpdate(); } - wfQuery( "COMMIT", DB_WRITE ); + $dbw->query( "COMMIT" ); } } @@ -97,12 +100,12 @@ function moveCustomMessages( $phase ) { $dest = Title::makeTitle( NS_MEDIAWIKI, $partial ); $linksTo = $dest->getLinksTo(); foreach( $linksTo as $source ) { - wfQuery( "BEGIN", DB_WRITE ); + $dbw->query( "BEGIN" ); $pdbk = $source->getPrefixedDBkey(); if ( !array_key_exists( $pdbk, $completedTitles ) ) { $completedTitles[$pdbk] = 1; $id = $source->getArticleID(); - $row = wfGetArray( 'cur', array( 'cur_text' ), + $row = $dbw->selectRow( 'cur', array( 'cur_text' ), array( 'cur_id' => $source->getArticleID() ) ); $parser->startExternalParse( $source, $options, OT_WIKI ); $text = $parser->strip( $row->cur_text, $stripState, false ); @@ -125,7 +128,7 @@ function moveCustomMessages( $phase ) { print "($pdbk)\n"; } } - wfQuery( "COMMIT", DB_WRITE ); + $dbw->query( "COMMIT" ); } } } diff --git a/maintenance/archives/patch-image_name_unique.sql b/maintenance/archives/patch-image_name_unique.sql new file mode 100644 index 0000000000..118b068ddc --- /dev/null +++ b/maintenance/archives/patch-image_name_unique.sql @@ -0,0 +1,6 @@ +-- Make the image name index unique + +ALTER TABLE image DROP INDEX img_name; + +ALTER TABLE image + ADD UNIQUE INDEX img_name (img_name); diff --git a/maintenance/archives/upgradeWatchlist.php b/maintenance/archives/upgradeWatchlist.php index cd32eb5fb5..20914fca03 100644 --- a/maintenance/archives/upgradeWatchlist.php +++ b/maintenance/archives/upgradeWatchlist.php @@ -19,19 +19,19 @@ $wgDBuser = "wikiadmin"; $wgDBpassword = $wgDBadminpassword; $sql = "DROP TABLE IF EXISTS watchlist"; -wfQuery( $sql, DB_WRITE ); +wfQuery( $sql, DB_MASTER ); $sql = "CREATE TABLE watchlist ( wl_user int(5) unsigned NOT NULL, wl_page int(8) unsigned NOT NULL, UNIQUE KEY (wl_user, wl_page) ) TYPE=MyISAM PACK_KEYS=1"; -wfQuery( $sql, DB_WRITE ); +wfQuery( $sql, DB_MASTER ); $lc = new LinkCache; # Now, convert! $sql = "SELECT user_id,user_watch FROM user"; -$res = wfQuery( $sql, DB_READ ); +$res = wfQuery( $sql, DB_SLAVE ); $nu = wfNumRows( $res ); $sql = "INSERT into watchlist (wl_user,wl_page) VALUES "; $i = $n = 0; @@ -47,7 +47,7 @@ while( $row = wfFetchObject( $res ) ) { } echo "$n users done.\n"; if( $i ) { - wfQuery( $sql, DB_WRITE ); + wfQuery( $sql, DB_MASTER ); } @@ -56,6 +56,6 @@ if( $i ) { $sql = "ALTER TABLE watchlist ADD INDEX wl_user (wl_user), ADD INDEX wl_page (wl_page)"; -#wfQuery( $sql, DB_WRITE ); +#wfQuery( $sql, DB_MASTER ); ?> diff --git a/maintenance/attribute.php b/maintenance/attribute.php index a6dcf4a673..61c43b0898 100644 --- a/maintenance/attribute.php +++ b/maintenance/attribute.php @@ -16,12 +16,14 @@ if ( count( $args ) < 2 ) { $source = $args[0]; $dest = $args[1]; -$eSource = wfStrencode( $source ); -$eDest = wfStrencode( $dest ); +$dbr =& wfGetDB( DB_SLAVE ); +extract( $dbr->tableNames( 'cur','old','user' ); +$eSource = $dbr->strencode( $source ); +$eDest = $dbr->strencode( $dest ); # Get user id -$res = wfQuery( "SELECT user_id FROM user WHERE user_name='$eDest'", DB_READ ); -$row = wfFetchObject( $res ); +$res = $dbr->query( "SELECT user_id FROM $user WHERE user_name='$eDest'" ); +$row = $dbr->fetchObject( $res ); if ( !$row ) { print "Warning: the target name \"$dest\" does not exist"; $uid = 0; @@ -46,8 +48,8 @@ $omitTitle = "Wikipedia:Changing_attribution_for_an_edit"; # Get old entries print "\nOld entries\n\n"; -$res = wfQuery( "SELECT old_namespace, old_title, old_id, old_timestamp FROM old WHERE old_user_text='$eSource'", DB_READ ); -$row = wfFetchObject( $res ); +$res = $dbr->query( "SELECT old_namespace, old_title, old_id, old_timestamp FROM $old WHERE old_user_text='$eSource'" ); +$row = $dbr->fetchObject( $res ); if ( $row ) { /* @@ -59,7 +61,7 @@ if ( $row ) { fwrite( $logfile, "**Old IDs: " ); fwrite( $sqlfile, "UPDATE old SET old_user=$uid, old_user_text='$eDest' WHERE old_id IN (\n" ); - for ( $first=true; $row; $row = wfFetchObject( $res ) ) { + for ( $first=true; $row; $row = $dbr->fetchObject( $res ) ) { $ns = $wgLang->getNsText( $row->old_namespace ); if ( $ns ) { $fullTitle = "$ns:{$row->old_title}"; @@ -72,19 +74,7 @@ if ( $row ) { print "$fullTitle\n"; $url = "http://$lang.wikipedia.org/w/wiki.phtml?title=" . urlencode( $fullTitle ); - $eTitle = wfStrencode( $row->old_title ); -/* - # Find previous entry - $lastres = wfQuery( "SELECT old_id FROM old WHERE - old_title='$eTitle' AND old_namespace={$row->old_namespace} AND - old_timestamp<'{$row->old_timestamp}' ORDER BY inverse_timestamp LIMIT 1", DB_READ ); - $lastrow = wfFetchObject( $lastres ); - if ( $lastrow ) { - $last = $lastrow->old_id; - $url .= "&diff={$row->old_id}&oldid=$last"; - } else {*/ - $url .= "&oldid={$row->old_id}"; -# } + $url .= "&oldid={$row->old_id}"; # Output fwrite( $sqlfile, " " ); @@ -106,13 +96,12 @@ if ( $row ) { # Get cur entries print "\n\nCur entries\n\n"; -$res = wfQuery( "SELECT cur_title, cur_namespace, cur_timestamp, cur_id FROM cur WHERE cur_user_text='$eSource'", - DB_READ ); -$row = wfFetchObject( $res ); +$res = $dbr->query( "SELECT cur_title, cur_namespace, cur_timestamp, cur_id FROM $cur WHERE cur_user_text='$eSource'" ); +$row = $dbr->fetchObject( $res ); if ( $row ) { fwrite( $sqlfile, "\n\nUPDATE cur SET cur_user=$uid, cur_user_text='$eDest' WHERE cur_id IN(\n" ); fwrite( $logfile, "**Cur entries:\n" ); - for ( $first=true; $row; $row = wfFetchObject( $res ) ) { + for ( $first=true; $row; $row = $dbr->fetchObject( $res ) ) { $ns = $wgLang->getNsText( $row->cur_namespace ); if ( $ns ) { $fullTitle = "$ns:{$row->cur_title}"; diff --git a/maintenance/compressOld.inc b/maintenance/compressOld.inc index 8da4272571..249816eaa2 100644 --- a/maintenance/compressOld.inc +++ b/maintenance/compressOld.inc @@ -1,22 +1,26 @@ tableName( 'old' ); do { $end = $start + $chunksize; - $sql = "SELECT old_id,old_flags,old_namespace,old_title,old_text FROM old WHERE old_id>=$start ORDER BY old_id LIMIT $chunksize"; - $res = wfQuery( $sql, DB_READ, "compressOldPages" ); - if( wfNumRows( $res ) == 0 ) { + $res = dbw->select( 'old', array( 'old_id','old_flags','old_namespace','old_title','old_text' ), + "old_id>=$start", $fname, array( 'ORDER BY' => 'old_id', 'LIMIT' => $chunksize, 'FOR UPDATE' ) ); + if( $dbw->numRows( $res ) == 0 ) { break; } $last = $start; - while( $row = wfFetchObject( $res ) ) { + while( $row = $dbw->fetchObject( $res ) ) { # print " {$row->old_id} - {$row->old_namespace}:{$row->old_title}\n"; compressPage( $row ); $last = $row->old_id; } - wfFreeResult( $res ); + $dbw->freeResult( $res ); $start = $last + 1; # Deletion may leave long empty stretches print "$start...\n"; } while( true ); @@ -27,11 +31,17 @@ function compressPage( $row ) { print "Already compressed row {$row->old_id}?\n"; return false; } + $dbw =& wfGetDB( DB_MASTER ); $flags = $row->old_flags ? "{$row->old_flags},gzip" : "gzip"; - $compress = wfStrencode( gzdeflate( $row->old_text ) ); - - $sql = "UPDATE old SET old_flags='$flags', old_text='$compress' WHERE old_id={$row->old_id} LIMIT 1"; - $res = wfQuery( $sql, DB_WRITE, 'compressPage' ); + $compress = $dbw->strencode( gzdeflate( $row->old_text ) ); + $dbw->update( 'old', + array( /* SET */ + 'old_flags' => $flags, + 'old_text' => $compress + ), array( /* WHERE */ + 'old_id' => $row->old_id + ), $fname, 'LIMIT 1' + ); return $res; } diff --git a/maintenance/convertLinks.inc b/maintenance/convertLinks.inc index 3a25930ff4..62ec7a2412 100644 --- a/maintenance/convertLinks.inc +++ b/maintenance/convertLinks.inc @@ -30,17 +30,20 @@ function convertLinks() { $logPerformance = false; # output performance data to a file $perfLogFilename = "convLinksPerf.txt"; #-------------------------------------------------------------------- + + $dbw =& wfGetDB( DB_MASTER ); + extract( $dbw->tableNames( 'cur', 'links', 'links_temp', 'links_backup' ) ); - $res = wfQuery( "SELECT l_from FROM links LIMIT 1", DB_READ ); - if ( mysql_field_type( $res, 0 ) == "int" ) { + $res = $dbw->query( "SELECT l_from FROM $links LIMIT 1" ); + if ( $dbw->fieldType( $res, 0 ) == "int" ) { print "Schema already converted\n"; return; } - $res = wfQuery( "SELECT COUNT(*) AS count FROM links", DB_WRITE ); - $row = wfFetchObject($res); + $res = $dbw->query( "SELECT COUNT(*) AS count FROM $links" ); + $row = $dbw->fetchObject($res); $numRows = $row->count; - wfFreeResult( $res ); + $dbw->freeResult( $res ); if ( $numRows == 0 ) { print "Updating schema (no rows to convert)...\n"; @@ -49,14 +52,15 @@ function convertLinks() { if ( $logPerformance ) { $fh = fopen ( $perfLogFilename, "w" ); } $baseTime = $startTime = getMicroTime(); # Create a title -> cur_id map - print "Loading IDs from cur table...\n"; + print "Loading IDs from $cur table...\n"; performanceLog ( "Reading $numRows rows from cur table...\n" ); performanceLog ( "rows read vs seconds elapsed:\n" ); - wfBufferSQLResults( false ); - $res = wfQuery( "SELECT cur_namespace,cur_title,cur_id FROM cur", DB_WRITE ); + + $dbw->setBufferResults( false ); + $res = $dbw->query( "SELECT cur_namespace,cur_title,cur_id FROM $cur" ); $ids = array(); - while ( $row = wfFetchObject( $res ) ) { + while ( $row = $dbw->fetchObject( $res ) ) { $title = $row->cur_title; if ( $row->cur_namespace ) { $title = $wgLang->getNsText( $row->cur_namespace ) . ":$title"; @@ -66,12 +70,12 @@ function convertLinks() { if ($reportCurReadProgress) { if (($curRowsRead % $curReadReportInterval) == 0) { performanceLog( $curRowsRead . " " . (getMicroTime() - $baseTime) . "\n" ); - print "\t$curRowsRead rows of cur table read.\n"; + print "\t$curRowsRead rows of $cur table read.\n"; } } } - wfFreeResult( $res ); - wfBufferSQLResults( true ); + $dbw->freeResult( $res ); + $dbw->setBufferResults( true ); print "Finished loading IDs.\n\n"; performanceLog( "Took " . (getMicroTime() - $baseTime) . " seconds to load IDs.\n\n" ); #-------------------------------------------------------------------- @@ -81,21 +85,21 @@ function convertLinks() { createTempTable(); performanceLog( "Resetting timer.\n\n" ); $baseTime = getMicroTime(); - print "Processing $numRows rows from links table...\n"; - performanceLog( "Processing $numRows rows from links table...\n" ); + print "Processing $numRows rows from $links table...\n"; + performanceLog( "Processing $numRows rows from $links table...\n" ); performanceLog( "rows inserted vs seconds elapsed:\n" ); for ($rowOffset = $initialRowOffset; $rowOffset < $numRows; $rowOffset += $linksConvInsertInterval) { - $sqlRead = "SELECT * FROM links ".wfLimitResult($linksConvInsertInterval,$rowOffset); - $res = wfQuery($sqlRead, DB_READ); + $sqlRead = "SELECT * FROM $links ".wfLimitResult($linksConvInsertInterval,$rowOffset); + $res = $dbw->query($sqlRead); if ( $noKeys ) { - $sqlWrite = array("INSERT INTO links_temp(l_from,l_to) VALUES "); + $sqlWrite = array("INSERT INTO $links_temp (l_from,l_to) VALUES "); } else { - $sqlWrite = array("INSERT IGNORE INTO links_temp(l_from,l_to) VALUES "); + $sqlWrite = array("INSERT IGNORE INTO $links_temp (l_from,l_to) VALUES "); } $tuplesAdded = 0; # no tuples added to INSERT yet - while ( $row = wfFetchObject($res) ) { + while ( $row = $dbw->fetchObject($res) ) { $fromTitle = $row->l_from; if ( array_key_exists( $fromTitle, $ids ) ) { # valid title $from = $ids[$fromTitle]; @@ -109,13 +113,13 @@ function convertLinks() { $numBadLinks++; } } - wfFreeResult($res); + $dbw->freeResult($res); #print "rowOffset: $rowOffset\ttuplesAdded: $tuplesAdded\tnumBadLinks: $numBadLinks\n"; if ( $tuplesAdded != 0 ) { if ($reportLinksConvProgress) { - print "Inserting $tuplesAdded tuples into links_temp..."; + print "Inserting $tuplesAdded tuples into $links_temp..."; } - wfQuery( implode("",$sqlWrite) , DB_WRITE ); + $dbw->query( implode("",$sqlWrite) ); $totalTuplesInserted += $tuplesAdded; if ($reportLinksConvProgress) print " done. Total $totalTuplesInserted tuples inserted.\n"; @@ -137,19 +141,19 @@ function convertLinks() { } # Check for existing links_backup, and delete it if it exists. print "Dropping backup links table if it exists..."; - $dbConn->query( "DROP TABLE IF EXISTS links_backup", DB_WRITE); + $dbConn->query( "DROP TABLE IF EXISTS $links_backup", DB_MASTER); print " done.\n"; # Swap in the new table, and move old links table to links_backup - print "Swapping tables 'links' to 'links_backup'; 'links_temp' to 'links'..."; - $dbConn->query( "RENAME TABLE links TO links_backup, links_temp TO links", DB_WRITE ); + print "Swapping tables '$links' to '$links_backup'; '$links_temp' to '$links'..."; + $dbConn->query( "RENAME TABLE links TO $links_backup, $links_temp TO $links", DB_MASTER ); print " done.\n\n"; $dbConn->close(); - print "Conversion complete. The old table remains at links_backup;\n"; + print "Conversion complete. The old table remains at $links_backup;\n"; print "delete at your leisure.\n"; } else { - print "Conversion complete. The converted table is at links_temp;\n"; + print "Conversion complete. The converted table is at $links_temp;\n"; print "the original links table is unchanged.\n"; } } @@ -165,22 +169,23 @@ function createTempTable() { print "Opening connection to database failed.\n"; return; } + $links_temp = $dbConn->tableName( 'links_temp' ); print "Dropping temporary links table if it exists..."; - $dbConn->query( "DROP TABLE IF EXISTS links_temp", DB_WRITE); + $dbConn->query( "DROP TABLE IF EXISTS $links_temp"); print " done.\n"; print "Creating temporary links table..."; if ( $noKeys ) { - $dbConn->query( "CREATE TABLE links_temp ( " . + $dbConn->query( "CREATE TABLE $links_temp ( " . "l_from int(8) unsigned NOT NULL default '0', " . - "l_to int(8) unsigned NOT NULL default '0')", DB_WRITE); + "l_to int(8) unsigned NOT NULL default '0')"); } else { - $dbConn->query( "CREATE TABLE links_temp ( " . + $dbConn->query( "CREATE TABLE $links_temp ( " . "l_from int(8) unsigned NOT NULL default '0', " . "l_to int(8) unsigned NOT NULL default '0', " . "UNIQUE KEY l_from(l_from,l_to), " . - "KEY (l_to))", DB_WRITE); + "KEY (l_to))"); } print " done.\n\n"; } diff --git a/maintenance/importPhase2.php b/maintenance/importPhase2.php index 66c02d86dc..42120e295f 100644 --- a/maintenance/importPhase2.php +++ b/maintenance/importPhase2.php @@ -88,7 +88,7 @@ class Phase2Importer { # MySQL copies everything over to the new database and tweaks a few things. function importCurData() { print "Clearing pages from default install, if any...\n"; - wfQuery( "DELETE FROM cur", DB_WRITE ); + wfQuery( "DELETE FROM cur", DB_MASTER ); print "Importing current revision data...\n"; wfQuery( "INSERT INTO cur (cur_id,cur_namespace,cur_title,cur_text,cur_comment, @@ -97,35 +97,35 @@ class Phase2Importer { SELECT cur_id,0,cur_title,cur_text,cur_comment, cur_user,cur_user_text,cur_timestamp,REPLACE(cur_restrictions,'is_',''),cur_counter, cur_text like '#redirect%',cur_minor_edit,0,RAND(),NOW()+0,99999999999999-cur_timestamp - FROM {$this->olddb}.cur", DB_WRITE ); + FROM {$this->olddb}.cur", DB_MASTER ); $n = mysql_affected_rows(); print "$n rows imported.\n"; } function importOldData() { print "Clearing old revision data from default install, if any...\n"; - wfQuery( "DELETE FROM old", DB_WRITE ); + wfQuery( "DELETE FROM old", DB_MASTER ); print "Importing old revision data...\n"; wfQuery( "INSERT INTO old (old_id,old_namespace,old_title,old_text,old_comment, old_user,old_user_text,old_timestamp,old_minor_edit,old_flags,inverse_timestamp) SELECT old_id,0,old_title,old_text,old_comment, old_user,old_user_text,old_timestamp,old_minor_edit,'',99999999999999-old_timestamp - FROM {$this->olddb}.old", DB_WRITE ); + FROM {$this->olddb}.old", DB_MASTER ); $n = mysql_affected_rows(); print "$n rows imported.\n"; } function importUserData() { print "Clearing users from default install, if any...\n"; - wfQuery( "DELETE FROM user", DB_WRITE ); + wfQuery( "DELETE FROM user", DB_MASTER ); print "Importing user data...\n"; wfQuery( "INSERT INTO $newdb.user (user_id,user_name,user_rights, user_password,user_newpassword,user_email,user_options,user_touched) SELECT user_id,user_name,REPLACE(user_rights,'is_',''), MD5(CONCAT(user_id,'-',MD5(user_password))),'',user_email,user_options,NOW()+0 - FROM {$this->olddb}.user", DB_WRITE ); + FROM {$this->olddb}.user", DB_MASTER ); $n = mysql_affected_rows(); print "$n rows imported.\n"; } @@ -133,10 +133,10 @@ class Phase2Importer { # A little less clean... function importWatchlists() { print "Clearing watchlists from default install, if any...\n"; - wfQuery( "DELETE FROM watchlist", DB_WRITE ); + wfQuery( "DELETE FROM watchlist", DB_MASTER ); print "Importing watchlists..."; - $res = wfQuery( "SELECT user_id,user_watch FROM {$this->olddb}.user WHERE user_watch != ''", DB_WRITE ); + $res = wfQuery( "SELECT user_id,user_watch FROM {$this->olddb}.user WHERE user_watch != ''", DB_MASTER ); $total = wfNumRows( $res ); $n = 0; print " ($total total)\n"; @@ -151,7 +151,7 @@ class Phase2Importer { } else { $ns = $title->getNamespace(); $t = wfStrencode( $title->getDBkey() ); - wfQuery( "INSERT INTO watchlist(wl_user,wl_namespace,wl_title) VALUES ($id,$ns,'$t')", DB_WRITE ); + wfQuery( "INSERT INTO watchlist(wl_user,wl_namespace,wl_title) VALUES ($id,$ns,'$t')", DB_MASTER ); } } if( ++$n % 50 == 0 ) { @@ -164,14 +164,14 @@ class Phase2Importer { function importLinkData() { # MUST BE CALLED BEFORE! fixCurTitles() print "Clearing links from default install, if any...\n"; - wfQuery( "DELETE FROM links", DB_WRITE ); - wfQuery( "DELETE FROM brokenlinks", DB_WRITE ); + wfQuery( "DELETE FROM links", DB_MASTER ); + wfQuery( "DELETE FROM brokenlinks", DB_MASTER ); print "Importing live links..."; wfQuery( "INSERT INTO links (l_from, l_to) SELECT DISTINCT linked_from,cur_id FROM {$this->olddb}.linked,{$this->olddb}.cur - WHERE linked_to=cur_title", DB_WRITE ); + WHERE linked_to=cur_title", DB_MASTER ); $n = mysql_affected_rows(); print "$n rows imported.\n"; @@ -179,7 +179,7 @@ class Phase2Importer { wfQuery( "INSERT INTO brokenlinks (bl_from, bl_to) SELECT DISTINCT cur_id,unlinked_to FROM {$this->olddb}.unlinked,{$this->olddb}.cur - WHERE unlinked_from=cur_title", DB_WRITE ); + WHERE unlinked_from=cur_title", DB_MASTER ); $n = mysql_affected_rows(); print "$n rows imported.\n"; } @@ -195,7 +195,7 @@ class Phase2Importer { function fixTitles( $table ) { print "Fixing titles in $table..."; - $res = wfQuery( "SELECT DISTINCT {$table}_title AS title FROM $table", DB_WRITE ); + $res = wfQuery( "SELECT DISTINCT {$table}_title AS title FROM $table", DB_MASTER ); $total = wfNumRows( $res ); $n = 0; print " ($total total)\n"; @@ -209,7 +209,7 @@ class Phase2Importer { $ns = $title->getNamespace(); $t = wfStrencode( $title->getDBkey() ); wfQuery( "UPDATE $table SET {$table}_namespace=$ns,{$table}_title='$t' - WHERE {$table}_namespace=0 AND {$table}_title='$xt'", DB_WRITE ); + WHERE {$table}_namespace=0 AND {$table}_title='$xt'", DB_MASTER ); } if( ++$n % 50 == 0 ) { print "$n\n"; @@ -288,7 +288,7 @@ class Phase2Importer { function fixUserOptions() { print "Fixing user options..."; - $res = wfQuery( "SELECT user_id,user_options FROM user", DB_WRITE ); + $res = wfQuery( "SELECT user_id,user_options FROM user", DB_MASTER ); $total = wfNumRows( $res ); $n = 0; print " ($total total)\n"; @@ -296,7 +296,7 @@ class Phase2Importer { while( $row = wfFetchObject( $res ) ) { $id = IntVal( $row->user_id ); $option = wfStrencode( $this->rewriteUserOptions( $row->user_options ) ); - wfQuery( "UPDATE user SET user_options='$option' WHERE user_id=$id LIMIT 1", DB_WRITE ); + wfQuery( "UPDATE user SET user_options='$option' WHERE user_id=$id LIMIT 1", DB_MASTER ); if( ++$n % 50 == 0 ) { print "$n\n"; } diff --git a/maintenance/indexes.sql b/maintenance/indexes.sql index fa0359069e..64a9ce27e3 100644 --- a/maintenance/indexes.sql +++ b/maintenance/indexes.sql @@ -36,7 +36,6 @@ ALTER TABLE ipblocks ADD INDEX ipb_user (ipb_user); ALTER TABLE image - ADD INDEX img_name (img_name(10)), ADD INDEX img_size (img_size), ADD INDEX img_timestamp (img_timestamp); diff --git a/maintenance/rebuildInterwiki.inc b/maintenance/rebuildInterwiki.inc new file mode 100644 index 0000000000..22c0f7fb4c --- /dev/null +++ b/maintenance/rebuildInterwiki.inc @@ -0,0 +1,218 @@ +suffix = $s; + $this->lateral = $l; + $this->url = $u; + } + + function getURL( $lang ) { + return "http://$lang.{$this->url}/wiki/\$1"; + } +} + +function getRebuildInterwikiSQL() { + global $langlist, $languageAliases; + + # Initialise lists of wikis + $sites = array( + 'wiki' => new Site( 'wiki', 'w', 'wikipedia.org' ), + 'wiktionary' => new Site( 'wiktionary', 'wikt', 'wiktionary.org' ), + 'wikiquote' => new Site( 'wikiquote', 'wikiquote', 'wikiquote.org' ), + 'wikibooks' => new Site( 'wikibooks', 'wikibooks', 'wikibooks.org' ) + ); + $langlist = array_map( "trim", file( "/home/wikipedia/common/langlist" ) ); + $dblist = array_map( "trim", file( "/home/wikipedia/common/all.dblist" ) ); + + $specials = array( + 'sourceswiki' => 'sources.wikipedia.org', + 'quotewiki' => 'wikiquote.org', + 'textbookwiki' => 'wikibooks.org', + 'sep11wiki' => 'sep11.wikipedia.org', + 'metawiki' => 'meta.wikimedia.org', + ); + + $extraLinks = array( + array( 'm', 'http://meta.wikimedia.org/wiki/$1', 1 ), + array( 'meta', 'http://meta.wikimedia.org/wiki/$1', 1 ), + array( 'sep11', 'http://sep11.wikipedia.org/wiki/$1', 1 ), + ); + + $languageAliases = array( + 'zh-cn' => 'zh', + 'zh-tw' => 'zh', + ); + + # Construct a list of reserved prefixes + $reserved = array(); + foreach ( $langlist as $lang ) { + $reserved[$lang] = 1; + } + foreach ( $languageAliases as $alias => $lang ) { + $reserved[$alias] = 1; + } + foreach( $sites as $site ) { + $reserved[$site->lateral] = 1; + } + + # Extract the intermap from meta + $dbr =& wfGetDB( DB_WRITE ); + $row = $dbr->getArray( "metawiki.cur", array( "cur_text" ), + array( "cur_namespace" => 0, "cur_title" => "Interwiki_map" ) ); + + if ( !$row ) { + die( "m:Interwiki_map not found" ); + } + + $lines = explode( "\n", $row->cur_text ); + $iwArray = array(); + + foreach ( $lines as $line ) { + if ( preg_match( '/^\|\s*(.*?)\s*\|\|\s*(.*?)\s*$/', $line, $matches ) ) { + $prefix = strtolower( $matches[1] ); + $url = $matches[2]; + if ( preg_match( '/(wikipedia|wiktionary|wikisource|wikiquote|wikibooks)\.org/', $url ) ) { + $local = 1; + } else { + $local = 0; + } + + if ( empty( $reserved[$prefix] ) ) { + $iwArray[] = array( "iw_prefix" => $prefix, "iw_url" => $url, "iw_local" => $local ); + } + } + } + + $sql = "-- Generated by rebuildInterwiki.php"; + + + foreach ( $dblist as $db ) { + if ( isset( $specials[$db] ) ) { + # Special wiki + # Has interwiki links and interlanguage links to wikipedia + + $host = $specials[$db]; + $sql .= "\n--$host\n\n"; + $sql .= "USE $db;\n" . + "TRUNCATE TABLE interwiki;\n" . + "INSERT INTO interwiki (iw_prefix, iw_url, iw_local) VALUES \n"; + $first = true; + + # Intermap links + foreach ( $iwArray as $iwEntry ) { + $sql .= makeLink( $iwEntry, $first ); + } + + # Links to multilanguage sites + foreach ( $sites as $targetSite ) { + $sql .= makeLink( array( $targetSite->lateral, $targetSite->getURL( 'en' ), 1 ), $first ); + } + + # Interlanguage links to wikipedia + $sql .= makeLanguageLinks( $sites['wiki'], $first ); + + # Extra links + foreach ( $extraLinks as $link ) { + $sql .= makeLink( $link, $first ); + } + + $sql .= ";\n"; + } else { + # Find out which site this DB belongs to + $site = false; + foreach( $sites as $candidateSite ) { + $suffix = $candidateSite->suffix; + if ( preg_match( "/(.*)$suffix$/", $db, $matches ) ) { + $site = $candidateSite; + break; + } + } + if ( !$site ) { + print "Invalid database $db\n"; + continue; + } + $lang = $matches[1]; + $host = "$lang." . $site->url; + $sql .= "\n--$host\n\n"; + + $sql .= "USE $db;\n" . + "TRUNCATE TABLE interwiki;\n" . + "INSERT INTO interwiki (iw_prefix,iw_url,iw_local) VALUES\n"; + $first = true; + + # Intermap links + foreach ( $iwArray as $iwEntry ) { + $sql .= makeLink( $iwEntry, $first ); + } + + # Lateral links + foreach ( $sites as $targetSite ) { + # Suppress link to self + if ( $targetSite->suffix != $site->suffix ) { + $sql .= makeLink( array( $targetSite->lateral, $targetSite->getURL( $lang ), 1 ), $first ); + } + } + + # Interlanguage links + $sql .= makeLanguageLinks( $site, $first ); + + # w link within wikipedias + # Other sites already have it as a lateral link + if ( $site->suffix == "wiki" ) { + $sql .= makeLink( array("w", "http://en.wikipedia.org/wiki/$1", 1), $first ); + } + + # Extra links + foreach ( $extraLinks as $link ){ + $sql .= makeLink( $link, $first ); + } + $sql .= ";\n\n"; + } + } + return $sql; +} + +# ------------------------------------------------------------------------------------------ + +# Returns part of an INSERT statement, corresponding to all interlanguage links to a particular site +function makeLanguageLinks( &$site, &$first ) { + global $langlist, $languageAliases; + + $sql = ""; + + # Actual languages with their own databases + foreach ( $langlist as $targetLang ) { + $sql .= makeLink( array( $targetLang, $site->getURL( $targetLang ), 1 ), $first ); + } + + # Language aliases + foreach ( $languageAliases as $alias => $lang ) { + $sql .= makeLink( array( $alias, $site->getURL( $lang ), 1 ), $first ); + } + return $sql; +} + +# Make SQL for a single link from an array +function makeLink( $entry, &$first ) { + $sql = ""; + # Add comma + if ( $first ) { + $first = false; + } else { + $sql .= ",\n"; + } + $sql .= "(" . Database::makeList( $entry ) . ")"; + return $sql; +} + +?> diff --git a/maintenance/rebuildInterwiki.php b/maintenance/rebuildInterwiki.php index 328e765ea0..d2add0be7a 100644 --- a/maintenance/rebuildInterwiki.php +++ b/maintenance/rebuildInterwiki.php @@ -6,158 +6,9 @@ $oldCwd = getcwd(); $optionsWithArgs = array( "o" ); include_once( "commandLine.inc" ); +include_once( "rebuildInterwiki.inc" ); -class Site { - var $suffix, $lateral, $url; - - function Site( $s, $l, $u ) { - $this->suffix = $s; - $this->lateral = $l; - $this->url = $u; - } - - function getURL( $lang ) { - return "http://$lang.{$this->url}/wiki/\$1"; - } -} - -# Initialise lists of wikis -$sites = array( - 'wiki' => new Site( 'wiki', 'w', 'wikipedia.org' ), - 'wiktionary' => new Site( 'wiktionary', 'wikt', 'wiktionary.org' ) -); -$langlist = array_map( "trim", file( "/home/wikipedia/common/langlist" ) ); - -$specials = array( - 'sourceswiki' => 'sources.wikipedia.org', - 'quotewiki' => 'wikiquote.org', - 'textbookwiki' => 'wikibooks.org', - 'sep11wiki' => 'sep11.wikipedia.org', - 'metawiki' => 'meta.wikipedia.org', -); - -$extraLinks = array( - array( 'm', 'http://meta.wikipedia.org/wiki/$1', 1 ), - array( 'meta', 'http://meta.wikipedia.org/wiki/$1', 1 ), - array( 'sep11', 'http://sep11.wikipedia.org/wiki/$1', 1 ), -); - -$languageAliases = array( - 'zh-cn' => 'zh', - 'zh-tw' => 'zh', -); - -# Extract the intermap from meta - -$row = wfGetArray( "metawiki.cur", array( "cur_text" ), array( "cur_namespace" => 0, "cur_title" => "Interwiki_map" ) ); - -if ( !$row ) { - die( "m:Interwiki_map not found" ); -} - -$lines = explode( "\n", $row->cur_text ); -$iwArray = array(); - -foreach ( $lines as $line ) { - if ( preg_match( '/^\|\s*(.*?)\s*\|\|\s*(.*?)\s*$/', $line, $matches ) ) { - $prefix = $matches[1]; - $url = $matches[2]; - if ( preg_match( '/(wikipedia|wiktionary|wikisource|wikiquote|wikibooks)\.org/', $url ) ) { - $local = 1; - } else { - $local = 0; - } - - $iwArray[] = array( "iw_prefix" => $prefix, "iw_url" => $url, "iw_local" => $local ); - } -} - - -# Insert links into special wikis -# These have intermap links and interlanguage links pointing to wikipedia - -$sql = "-- Generated by rebuildInterwiki.php"; - -foreach ( $specials as $db => $host ) { - $sql .= "\nUSE $db;\n" . - "TRUNCATE TABLE interwiki;\n" . - "INSERT INTO interwiki (iw_prefix, iw_url, iw_local) VALUES \n"; - $first = true; - - # Intermap links - foreach ( $iwArray as $iwEntry ) { - # Suppress links to self - if ( strpos( $iwEntry['iw_url'], $host ) === false ) { - $sql .= makeLink( $iwEntry, $first ); - } - } - # w link - $sql .= makeLink( array("w", "http://en.wikipedia.org/wiki/$1", 1 ), $first ); - - # Interlanguage links to wikipedia - $sql .= makeLanguageLinks( $sites['wiki'], $first ); - - # Extra links - foreach ( $extraLinks as $link ) { - $sql .= makeLink( $link, $first ); - } - - $sql .= ";\n"; -} -$sql .= "\n"; - -# Insert links into multilanguage sites - -foreach ( $sites as $site ) { - $sql .= <<suffix} ---- - -EOS; - foreach ( $langlist as $lang ) { - $db = $lang . $site->suffix; - $db = str_replace( "-", "_", $db ); - - $sql .= "USE $db;\n" . - "TRUNCATE TABLE interwiki;\n" . - "INSERT INTO interwiki (iw_prefix,iw_url,iw_local) VALUES\n"; - $first = true; - - # Intermap links - foreach ( $iwArray as $iwEntry ) { - # Suppress links to self - if ( strpos( $iwEntry['iw_url'], $site->url ) === false || - strpos( $iwEntry['iw_url'], 'meta.wikipedia.org' ) !== false ) { - $sql .= makeLink( $iwEntry, $first ); - } - } - - # Lateral links - foreach ( $sites as $targetSite ) { - # Suppress link to self - if ( $targetSite->suffix != $site->suffix ) { - $sql .= makeLink( array( $targetSite->lateral, $targetSite->getURL( $lang ), 1 ), $first ); - } - } - - # Interlanguage links - $sql .= makeLanguageLinks( $site, $first ); - - # w link within wikipedias - # Other sites already have it as a lateral link - if ( $site->suffix == "wiki" ) { - $sql .= makeLink( array("w", "http://en.wikipedia.org/wiki/$1", 1), $first ); - } - - # Extra links - foreach ( $extraLinks as $link ){ - $sql .= makeLink( $link, $first ); - } - $sql .= ";\n\n"; - } -} +$sql = getRebuildInterwikiSQL(); # Output if ( isset( $options['o'] ) ) { @@ -171,37 +22,4 @@ if ( isset( $options['o'] ) ) { print $sql; } -# ------------------------------------------------------------------------------------------ - -# Returns part of an INSERT statement, corresponding to all interlanguage links to a particular site -function makeLanguageLinks( &$site, &$first ) { - global $langlist, $languageAliases; - - $sql = ""; - - # Actual languages with their own databases - foreach ( $langlist as $targetLang ) { - $sql .= makeLink( array( $targetLang, $site->getURL( $targetLang ), 1 ), $first ); - } - - # Language aliases - foreach ( $languageAliases as $alias => $lang ) { - $sql .= makeLink( array( $alias, $site->getURL( $lang ), 1 ), $first ); - } - return $sql; -} - -# Make SQL for a single link from an array -function makeLink( $entry, &$first ) { - $sql = ""; - # Add comma - if ( $first ) { - $first = false; - } else { - $sql .= ",\n"; - } - $sql .= "(" . Database::makeList( $entry ) . ")"; - return $sql; -} - ?> diff --git a/maintenance/rebuildMessages.php b/maintenance/rebuildMessages.php index eb549b4630..0a40f949dc 100755 --- a/maintenance/rebuildMessages.php +++ b/maintenance/rebuildMessages.php @@ -21,7 +21,8 @@ if ( isset( $args[0] ) ) { } if ( $response == 0 ) { - $row = wfGetArray( "cur", array("count(*) as c"), array("cur_namespace" => NS_MEDIAWIKI) ); + $dbr =& wfGetDB( DB_SLAVE ); + $row = $dbr->selectRow( "cur", array("count(*) as c"), array("cur_namespace" => NS_MEDIAWIKI) ); print "Current namespace size: {$row->c}\n"; print "1. Update messages to include latest additions to Language.php\n" . diff --git a/maintenance/rebuildlinks.inc b/maintenance/rebuildlinks.inc index 3aba4d00a5..83298d1add 100644 --- a/maintenance/rebuildlinks.inc +++ b/maintenance/rebuildlinks.inc @@ -27,42 +27,42 @@ function rebuildLinkTables() print "Rebuilding link tables.\n"; print "Setting AUTOCOMMIT=1\n"; - wfQuery("SET SESSION AUTOCOMMIT=1", DB_WRITE); + wfQuery("SET SESSION AUTOCOMMIT=1", DB_MASTER); print "Extracting often used data from cur (may take a few minutes)\n"; $sql = "CREATE TEMPORARY TABLE cur_fast SELECT cur_namespace, cur_title, cur_id FROM cur"; - wfQuery( $sql, DB_WRITE ); + wfQuery( $sql, DB_MASTER ); $sql = "ALTER TABLE cur_fast ADD INDEX(cur_namespace, cur_title)"; - wfQuery( $sql, DB_WRITE ); + wfQuery( $sql, DB_MASTER ); print "Locking tables\n"; $sql = "LOCK TABLES cur READ, cur_fast READ, interwiki READ, user_newtalk READ, " . "links WRITE, brokenlinks WRITE, imagelinks WRITE"; - wfQuery( $sql, DB_WRITE ); + wfQuery( $sql, DB_MASTER ); print "Deleting old data in links table.\n"; $sql = "DELETE FROM links"; - wfQuery( $sql, DB_WRITE ); + wfQuery( $sql, DB_MASTER ); print "Deleting old data in brokenlinks table.\n"; $sql = "DELETE FROM brokenlinks"; - wfQuery( $sql, DB_WRITE ); + wfQuery( $sql, DB_MASTER ); print "Deleting old data in imagelinks table.\n"; $sql = "DELETE FROM imagelinks"; - wfQuery( $sql, DB_WRITE ); + wfQuery( $sql, DB_MASTER ); print "Finding number of articles to process... "; $sql = "SELECT COUNT(*) as count FROM cur"; - $res = wfQuery( $sql, DB_READ ); + $res = wfQuery( $sql, DB_SLAVE ); $obj = wfFetchObject( $res ); $total = $obj->count; print "$total\n"; print "Finding highest article id\n"; $sql = "SELECT MIN(cur_id) AS min, MAX(cur_id) AS max FROM cur"; - $res = wfQuery( $sql, DB_READ ); + $res = wfQuery( $sql, DB_SLAVE ); $obj = wfFetchObject( $res ); $cur_pulser = new SelectPulser("SELECT cur_id,cur_namespace,cur_title,cur_text " . @@ -169,7 +169,7 @@ function rebuildLinkTables() } $sql = "SELECT cur_namespace, cur_title, cur_id FROM cur_fast WHERE " . implode(" OR ", $parts); - $res = wfQuery( $sql, DB_WRITE ); + $res = wfQuery( $sql, DB_MASTER ); while($row = wfFetchObject( $res ) ){ $pos = $titles_needing_curdata_pos[$row->cur_title . $row->cur_namespace]; $titles_needing_curdata[$pos]->mArticleID = intval($row->cur_id); @@ -226,7 +226,7 @@ function rebuildLinkTables() print "$count articles scanned.\n"; $sql = "UNLOCK TABLES"; - wfQuery( $sql, DB_WRITE ); + wfQuery( $sql, DB_MASTER ); print "Done\n"; } @@ -267,7 +267,7 @@ class InsertBuffer { function flush(){ if( $this->mBufcount > 0 ){ $sql = $this->mSql . implode(",", $this->mBuf); - wfQuery( $sql, DB_WRITE ); + wfQuery( $sql, DB_MASTER ); $this->mBuf = array(); $this->mBufcount = 0; // print "Wrote query of size " . strlen( $sql ) . "\n"; @@ -303,7 +303,7 @@ class SelectPulser { " AND " . ($this->mPos + $this->mSetsize - 1); $this->mPos += $this->mSetsize; - $res = wfQuery( $sql, DB_READ ); + $res = wfQuery( $sql, DB_SLAVE ); while ( $row = wfFetchObject( $res ) ) { $this->mSet[] = $row; } diff --git a/maintenance/rebuildrecentchanges.inc b/maintenance/rebuildrecentchanges.inc index d14a4b9f34..f4d739e66e 100644 --- a/maintenance/rebuildrecentchanges.inc +++ b/maintenance/rebuildrecentchanges.inc @@ -5,42 +5,59 @@ function rebuildRecentChangesTablePass1() { - $sql = "DELETE FROM recentchanges"; - wfQuery( $sql, DB_WRITE ); + $fname = 'rebuildRecentChangesTablePass1'; + $dbw =& wfGetDB( DB_MASTER ); + extract( $dbw->tableNames( 'recentchanges', 'cur', 'old' ); - print( "Loading from CUR table...\n" ); + $dbw->delete( 'recentchanges', '*' ); - $sql = "INSERT INTO recentchanges (rc_timestamp,rc_cur_time,rc_user," . - "rc_user_text,rc_namespace,rc_title,rc_comment,rc_minor,rc_bot,rc_new," . - "rc_cur_id,rc_this_oldid,rc_last_oldid) SELECT cur_timestamp," . - "cur_timestamp,cur_user,cur_user_text,cur_namespace,cur_title," . - "cur_comment,cur_minor_edit,0,cur_is_new,cur_id,0,0 FROM cur " . - "ORDER BY inverse_timestamp LIMIT 5000"; - wfQuery( $sql, DB_WRITE ); + print( "Loading from CUR table...\n" ); + $dbw->insertSelect( 'recentchanges', 'cur', + array( + 'rc_timestamp' => 'cur_timestamp', + 'rc_cur_time' => 'cur_timestamp', + 'rc_user' => 'cur_user', + 'rc_user_text' => 'cur_user_text', + 'rc_namespace' => 'cur_namespace', + 'rc_title' => 'cur_title', + 'rc_comment' => 'cur_comment', + 'rc_minor' => 'cur_minor_edit', + 'rc_bot' => 0, + 'rc_new' => 'cur_is_new', + 'rc_cur_id' => 'cur_id', + 'rc_this_oldid' => 0, + 'rc_last_oldid' => 0, + 'rc_type' => 'IF(cur_is_new,' . RC_NEW . ',' . RC_EDIT . ')' + ), '*', $fname, array( 'ORDER BY' => 'inverse_timestamp', 'LIMIT' => 5000 + ); + print( "Loading from OLD table...\n" ); - $sql = "INSERT INTO recentchanges (rc_timestamp,rc_cur_time,rc_user," . + $sql = "INSERT INTO $recentchanges (rc_timestamp,rc_cur_time,rc_user," . "rc_user_text,rc_namespace,rc_title,rc_comment,rc_minor,rc_bot,rc_new," . "rc_cur_id,rc_this_oldid,rc_last_oldid) SELECT old_timestamp,cur_timestamp," . "old_user,old_user_text,old_namespace,old_title,old_comment," . - "old_minor_edit,0,0,cur_id,old_id,0 FROM old,cur " . - "WHERE old_namespace=cur_namespace AND old_title=cur_title ORDER BY old.inverse_timestamp " . + "old_minor_edit,0,0,cur_id,old_id,0 FROM $old,$cur " . + "WHERE old_namespace=cur_namespace AND old_title=cur_title ORDER BY $old.inverse_timestamp " . "LIMIT 5000"; - wfQuery( $sql, DB_WRITE ); + $dbw->query( $sql ); - $sql = "SELECT rc_timestamp FROM recentchanges " . + $sql = "SELECT rc_timestamp FROM $recentchanges " . "ORDER BY rc_timestamp DESC LIMIT 5000,1"; - $res = wfQuery( $sql, DB_WRITE ); - $obj = wfFetchObject( $res ); + $res = $dbw->query( $sql ); + $obj = $dbw->fetchObject( $res ); $ts = $obj->rc_timestamp; - $sql = "DELETE FROM recentchanges WHERE rc_timestamp < '{$ts}'"; - wfQuery( $sql, DB_WRITE ); + $sql = "DELETE FROM $recentchanges WHERE rc_timestamp < '{$ts}'"; + $dbw->query( $sql ); } function rebuildRecentChangesTablePass2() { + $dbw =& wfGetDB( DB_MASTER ); + extract( $dbw->tableNames( 'recentchanges', 'cur', 'old' ); + $ns = $id = $count = 0; $title = $ct = ""; @@ -48,40 +65,41 @@ function rebuildRecentChangesTablePass2() # Fill in the rc_last_oldid field, which points to the previous edit # - $sql = "SELECT rc_cur_id,rc_this_oldid,rc_timestamp FROM recentchanges " . + $sql = "SELECT rc_cur_id,rc_this_oldid,rc_timestamp FROM $recentchanges " . "ORDER BY rc_cur_id,rc_timestamp"; - $res = wfQuery( $sql, DB_WRITE ); + $res = $dbw->query( $sql, DB_MASTER ); $lastCurId = 0; $lastOldId = 0; - while ( $obj = wfFetchObject( $res ) ) { + while ( $obj = $dbw->fetchObject( $res ) ) { $new = 0; if( $obj->rc_cur_id != $lastCurId ) { # Switch! Look up the previous last edit, if any $lastCurId = IntVal( $obj->rc_cur_id ); $emit = wfInvertTimestamp( $obj->rc_timestamp ); - $sql2 = "SELECT old_id FROM old,cur " . + $sql2 = "SELECT old_id FROM $old,$cur " . "WHERE old_namespace=cur_namespace AND old_title=cur_title AND cur_id={$lastCurId} ". - "AND old.inverse_timestamp>'{$emit}' ORDER BY old.inverse_timestamp LIMIT 1"; - $res2 = wfQuery( $sql2, DB_WRITE ); - if( $row = wfFetchObject( $res2 ) ) { + "AND $old.inverse_timestamp>'{$emit}' ORDER BY $old.inverse_timestamp LIMIT 1"; + $res2 = $dbw->query( $sql2 ); + if( $row = $dbw->fetchObject( $res2 ) ) { $lastOldId = IntVal( $row->old_id ); } else { # No previous edit $lastOldId = 0; $new = 1; } - wfFreeResult( $res2 ); + $dbw->freeResult( $res2 ); } if( $lastCurId == 0 ) { print "Uhhh, something wrong? No curid\n"; } else { - $sql3 = "UPDATE recentchanges SET rc_last_oldid=$lastOldId,rc_new=$new,rc_type=$new WHERE rc_cur_id={$lastCurId} AND rc_this_oldid={$obj->rc_this_oldid}"; - wfQuery( $sql3, DB_WRITE ); + $sql3 = "UPDATE $recentchanges SET rc_last_oldid=$lastOldId,rc_new=$new,rc_type=$new " . + "WHERE rc_cur_id={$lastCurId} AND rc_this_oldid={$obj->rc_this_oldid}"; + $dbw->query( $sql3 ); $lastOldId = IntVal( $obj->rc_this_oldid ); } } - wfFreeResult( $res ); + $dbw->freeResult( $res ); } ?> diff --git a/maintenance/rebuildtextindex.inc b/maintenance/rebuildtextindex.inc index 26082263a2..04e0eb6fca 100644 --- a/maintenance/rebuildtextindex.inc +++ b/maintenance/rebuildtextindex.inc @@ -10,29 +10,30 @@ define( "RTI_CHUNK_SIZE", 500 ); function dropTextIndex( &$database ) { - if ( wfIndexExists( "searchindex", "si_title" ) ) { + $searchindex = $database->tableName( 'searchindex' ); + if ( $database->indexExists( "searchindex", "si_title" ) ) { echo "Dropping index...\n"; - $sql = "ALTER TABLE searchindex DROP INDEX si_title, DROP INDEX si_text"; + $sql = "ALTER TABLE $searchindex DROP INDEX si_title, DROP INDEX si_text"; $database->query($sql, "dropTextIndex" ); } - # Truncate table, in an attempt to bring the slaves to a consistent state - # (zwinger was accidentally written to) - $database->query( "TRUNCATE TABLE searchindex", "dropTextIndex" ); } function createTextIndex( &$database ) { + $searchindex = $database->tableName( 'searchindex' ); echo "Rebuild the index...\n"; - $sql = "ALTER TABLE searchindex ADD FULLTEXT si_title (si_title), " . + $sql = "ALTER TABLE $searchindex ADD FULLTEXT si_title (si_title), " . "ADD FULLTEXT si_text (si_text)"; $database->query($sql, "createTextIndex" ); } function rebuildTextIndex( &$database ) { - $sql = "SELECT MAX(cur_id) AS count FROM cur"; + extract( $database->tableNames( 'cur', 'searchindex' ) ); + + $sql = "SELECT MAX(cur_id) AS count FROM $cur"; $res = $database->query($sql, "rebuildTextIndex" ); - $s = wfFetchObject($res); + $s = $database->fetchObject($res); $count = $s->count; echo "Rebuilding index fields for {$count} pages...\n"; $n = 0; @@ -40,14 +41,14 @@ function rebuildTextIndex( &$database ) while ( $n < $count ) { print "$n\n"; $end = $n + RTI_CHUNK_SIZE - 1; - $sql = "SELECT cur_id, cur_namespace, cur_title, cur_text FROM cur WHERE cur_id BETWEEN $n AND $end"; + $sql = "SELECT cur_id, cur_namespace, cur_title, cur_text FROM $cur WHERE cur_id BETWEEN $n AND $end"; $res = $database->query($sql, "rebuildTextIndex" ); - while( $s = wfFetchObject($res) ) { + while( $s = $database->fetchObject($res) ) { $u = new SearchUpdate( $s->cur_id, $s->cur_title, $s->cur_text ); $u->doUpdate(); } - wfFreeResult( $res ); + $database->freeResult( $res ); $n += RTI_CHUNK_SIZE; } } diff --git a/maintenance/refreshLinks.inc b/maintenance/refreshLinks.inc index 42e1138e0e..285aba764a 100644 --- a/maintenance/refreshLinks.inc +++ b/maintenance/refreshLinks.inc @@ -6,9 +6,9 @@ define( "PAUSE_INTERVAL", 50 ); function refreshLinks( $start ) { global $wgUser, $wgTitle, $wgArticle, $wgEnablePersistentLC, $wgLinkCache, $wgOut; - $res = wfQuery("SELECT max(cur_id) as m FROM cur", DB_READ); - $row = wfFetchObject( $res ); - $end = $row->m; + $dbw =& wfGetDB( DB_MASTER ); + + $end = $dbw->selectField( 'cur_id', 'max(cur_id)', false ); print("Refreshing link table. Starting from cur_id $start of $end.\n"); @@ -32,10 +32,11 @@ function refreshLinks( $start ) { $wgArticle = new Article( $wgTitle ); $text = $wgArticle->getContent( true ); $wgLinkCache = new LinkCache; + $wgLinkCache->forUpdate( true ); $wgOut->addWikiText( $text ); if ( $wgEnablePersistentLC ) { - $wgLinkCache->saveToLinkscc( $id, wfStrencode( $wgTitle->getPrefixedDBkey() ) ); + $wgLinkCache->saveToLinkscc( $id, $dbw->strencode( $wgTitle->getPrefixedDBkey() ) ); } $linksUpdate = new LinksUpdate( $id, $wgTitle->getPrefixedDBkey() ); diff --git a/maintenance/remove-brokenlinks.php b/maintenance/remove-brokenlinks.php index 7faecef568..8cdd9bac3c 100644 --- a/maintenance/remove-brokenlinks.php +++ b/maintenance/remove-brokenlinks.php @@ -5,19 +5,16 @@ require_once( "commandLine.inc" ); require_once( "./rebuildrecentchanges.inc" ); $wgTitle = Title::newFromText( "Rebuild brokenlinks script" ); -$wgDBuser = $wgDBadminuser; -$wgDBpassword = $wgDBadminpassword; - - -# That above is common code and should be hidden away :( - $n = 0; echo "Checking for broken brokenlinks...\n"; -$sql = "SELECT cur_namespace,cur_title,cur_id FROM cur"; -$res = wfQuery( $sql, DB_WRITE ); -while( $s = wfFetchObject( $res ) ) { +$dbw =& wfGetDB( DB_MASTER ); +extract( $dbw->tableNames( 'brokenlinks', 'cur', 'linkscc' ); + +$res = $dbw->select( 'cur', array( 'cur_namespace', 'cur_title', 'cur_id' ), false ); + +while( $s = $dbw->fetchObject( $res ) ) { $n++; if(($n % 500) == 0) { echo "$n\n"; @@ -25,21 +22,22 @@ while( $s = wfFetchObject( $res ) ) { $title = Title::makeTitle( $s->cur_namespace, $s->cur_title ); if($title) { $t = $title->getPrefixedDBKey(); - $tt = wfStrencode( $t ); + $tt = $dbw->strencode( $t ); $any = false; - $sql2 = "SELECT bl_from,cur_id,cur_namespace,cur_title FROM brokenlinks,cur WHERE bl_to='$tt' AND cur_id=bl_from"; - $res2 = wfQuery( $sql2, DB_WRITE ); - while( $s = wfFetchObject( $res2 ) ) { + $sql2 = "SELECT bl_from,cur_id,cur_namespace,cur_title FROM $brokenlinks,$cur " . + "WHERE bl_to='$tt' AND cur_id=bl_from"; + $res2 = $dbw->query( $sql2 ); + while( $s = $dbw->fetchObject( $res2 ) ) { $from = Title::makeTitle( $s->cur_namespace, $s->cur_title ); $xt = $from->getPrefixedText(); echo "Found bad brokenlink to [[$t]] from page #$s->cur_id [[$xt]]!\n"; $any = true; } - wfFreeResult( $res2 ); + $dbw->freeResult( $res2 ); if($any) { echo "Removing brokenlinks to [[$t]]...\n"; - $sql3 = "DELETE FROM brokenlinks WHERE bl_to='$tt'"; - $res3 = wfQuery( $sql3, DB_WRITE ); + $sql3 = "DELETE FROM $brokenlinks WHERE bl_to='$tt'"; + $res3 = $dbw->query( $sql3 ); #echo "-- $sql3\n"; } } else { @@ -49,7 +47,7 @@ while( $s = wfFetchObject( $res ) ) { echo "Done at $n.\n\n"; echo "Clearing linkscc table...\n"; -$sql4 = "DELETE FROM linkscc"; -wfQuery( $sql4, DB_WRITE ); +$sql4 = "DELETE FROM $linkscc"; +wfQuery( $sql4, DB_MASTER ); ?> diff --git a/maintenance/tables.sql b/maintenance/tables.sql index da269c6bb9..6d1e4d482e 100644 --- a/maintenance/tables.sql +++ b/maintenance/tables.sql @@ -160,7 +160,8 @@ CREATE TABLE image ( img_description tinyblob NOT NULL default '', img_user int(5) unsigned NOT NULL default '0', img_user_text varchar(255) binary NOT NULL default '', - img_timestamp char(14) binary NOT NULL default '' + img_timestamp char(14) binary NOT NULL default '', + UNIQUE KEY img_name (img_name) ) PACK_KEYS=1; CREATE TABLE oldimage ( diff --git a/maintenance/trivialCmdLine.php b/maintenance/trivialCmdLine.php index 4a0bb39cfa..321e86e9bb 100644 --- a/maintenance/trivialCmdLine.php +++ b/maintenance/trivialCmdLine.php @@ -4,8 +4,10 @@ print "DB name: $wgDBname\n"; print "DB user: $wgDBuser\n"; print "DB password: $wgDBpassword\n"; -$res = wfQuery( "SELECT MAX(cur_id) as m FROM cur", DB_READ ); -$row = wfFetchObject( $res ); +$dbr =& wfGetDB( DB_SLAVE ); +$cur = $dbr->tableName( 'cur' ); +$res = $dbr->query( "SELECT MAX(cur_id) as m FROM $cur" ); +$row = $dbr->fetchObject( $res ); print "Max cur_id: {$row->m}\n"; ?> diff --git a/maintenance/updateSearchIndex.inc b/maintenance/updateSearchIndex.inc index f3c3646edd..1344f51967 100644 --- a/maintenance/updateSearchIndex.inc +++ b/maintenance/updateSearchIndex.inc @@ -9,15 +9,18 @@ function updateSearchIndex( $start, $end, $maxLockTime, $quiet ) { $wgQuiet = $quiet; $wgDisableSearchUpdate = false; + $dbw =& wfGetDB( DB_MASTER ); + $recentchanges = $dbw->tableName( 'recentchanges' ); + output( "Updating searchindex between $start and $end\n" ); # Select entries from recentchanges which are on top and between the specified times - $start = wfStrencode( $start ); - $end = wfStrencode( $end ); + $start = $dbw->strencode( $start ); + $end = $dbw->strencode( $end ); - $sql = "SELECT rc_cur_id,rc_type,rc_moved_to_ns,rc_moved_to_title FROM recentchanges + $sql = "SELECT rc_cur_id,rc_type,rc_moved_to_ns,rc_moved_to_title FROM $recentchanges WHERE rc_this_oldid=0 AND rc_timestamp BETWEEN '$start' AND '$end'"; - $res = wfQuery( $sql, DB_READ, $fname ); + $res = $dbw->query( $sql, $fname ); # Lock searchindex if ( $maxLockTime ) { @@ -28,7 +31,7 @@ function updateSearchIndex( $start, $end, $maxLockTime, $quiet ) { } # Loop through the results and do a search update - while ( $row = wfFetchObject( $res ) ) { + while ( $row = $dbw->fetchObject( $res ) ) { # Allow reads to be processed if ( $maxLockTime && time() > $lockTime + $maxLockTime ) { output( " --- Relocking ---" ); @@ -47,7 +50,8 @@ function updateSearchIndex( $start, $end, $maxLockTime, $quiet ) { output( "\n" ); } else { # Get cur row - $curRow = wfGetArray( 'cur', array( 'cur_namespace', 'cur_title', 'cur_text' ), array( 'cur_id' => $row->rc_cur_id ) ); + $curRow = $dbw->selectRow( 'cur', array( 'cur_namespace', 'cur_title', 'cur_text' ), + array( 'cur_id' => $row->rc_cur_id ), $fname, 'FOR UPDATE' ); if ( $curRow ) { $titleObj = Title::makeTitle( $curRow->cur_namespace, $curRow->cur_title ); $title = $titleObj->getPrefixedDBkey(); @@ -67,12 +71,15 @@ function updateSearchIndex( $start, $end, $maxLockTime, $quiet ) { output( "Done\n" ); } -function lockSearchindex() { - wfQuery( "LOCK TABLES searchindex LOW_PRIORITY WRITE, cur READ, interwiki READ", DB_WRITE ); +function lockSearchindex( &$db ) { + $dbw =& wfGetDB( DB_MASTER ); + extract( $dbw->tableNames( 'searchindex', 'cur', 'interwiki' ) ); + $dbw->query( "LOCK TABLES $searchindex LOW_PRIORITY WRITE, $cur READ, $interwiki READ" ); } function unlockSearchindex() { - wfQuery( "UNLOCK TABLES", DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); + $dbw->query( "UNLOCK TABLES" ); } # Unlock and lock again diff --git a/maintenance/updaters.inc b/maintenance/updaters.inc index 8ed663be0c..5538107616 100644 --- a/maintenance/updaters.inc +++ b/maintenance/updaters.inc @@ -184,4 +184,15 @@ function do_categorylinks_update() { echo "ok\n"; } } + +function do_image_name_unique_update() { + global $wgDatabase; + if ( $wgDatabase->indexUnique( 'image', 'img_name' ) ) { + echo "...img_name already unique.\n"; + } else { + echo "Making the img_name index unique... "; + dbsource( "maintenance/archives/patch-image_name_unique.sql", $wgDatabase ); + echo "ok\n"; + } +} ?> diff --git a/texvc.phtml b/texvc.phtml index 7f5e1a0472..a47416ec4c 100644 --- a/texvc.phtml +++ b/texvc.phtml @@ -28,7 +28,7 @@ function xlinkToMathImage ( $tex, $outputhash ) function texvc_cgi_renderMath( $tex ) { global $wgMathDirectory, $wgTmpDirectory, $wgInputEncoding; - $dbr =& wfGetDB( DB_READ ); + $dbr =& wfGetDB( DB_SLAVE ); $mf = wfMsg( "math_failure" ); $munk = wfMsg( "math_unknown_error" ); @@ -113,7 +113,7 @@ function texvc_cgi_renderMath( $tex ) $outmd5_sql = pack("H32", $outmd5); # Someone may have inserted the same hash since the SELECT, but that's no big deal, just ignore errors - $dbw =& wfGetDB( DB_WRITE ); + $dbw =& wfGetDB( DB_MASTER ); $dbw->insertArray( 'math', array( 'math_inputhash' => $md5_sql,