OOP calling convention for database functions. DBMS abstraction implemented by means...
authorTim Starling <tstarling@users.mediawiki.org>
Sat, 10 Jul 2004 03:09:26 +0000 (03:09 +0000)
committerTim Starling <tstarling@users.mediawiki.org>
Sat, 10 Jul 2004 03:09:26 +0000 (03:09 +0000)
46 files changed:
includes/Article.php
includes/Block.php
includes/Database.php
includes/DatabaseFunctions.php
includes/DatabasePostgreSQL.php
includes/DefaultSettings.php
includes/DifferenceEngine.php
includes/EditPage.php
includes/GlobalFunctions.php
includes/Image.php
includes/ImagePage.php
includes/LinkCache.php
includes/LinksUpdate.php
includes/LoadBalancer.php
includes/LogPage.php
includes/Math.php
includes/MessageCache.php
includes/ObjectCache.php
includes/OutputPage.php
includes/PageHistory.php
includes/Parser.php
includes/Profiling.php
includes/QueryPage.php
includes/RawPage.php
includes/SearchEngine.php
includes/SearchUpdate.php
includes/Setup.php
includes/SiteStatsUpdate.php
includes/Skin.php
includes/SkinPHPTal.php
includes/SpecialAllpages.php
includes/SpecialAncientpages.php
includes/SpecialContributions.php
includes/SpecialListadmins.php
includes/SpecialListusers.php
includes/SpecialMaintenance.php
includes/SpecialNewpages.php
includes/SpecialRandompage.php
includes/SpecialStatistics.php
includes/SpecialWatchlist.php
includes/Title.php
includes/ViewCountUpdate.php
includes/WatchedItem.php
index.php
install-utils.inc
texvc.phtml

index 1af07e3..4a905e6 100644 (file)
@@ -9,6 +9,9 @@
 
 require_once( 'CacheManager.php' );
 
+$wgArticleCurContentFields = false;
+$wgArticleOldContentFields = false;
+
 class Article {
        /* private */ var $mContent, $mContentLoaded;
        /* private */ var $mUser, $mTimestamp, $mUserText;
@@ -140,7 +143,7 @@ class Article {
                                        $index = $matches[4];
                                        if ( $machineID == 0 ) {
                                                # Current connection
-                                               $db =& wfGetDB();
+                                               $db =& wfGetDB( DB_READ );
                                        } else {
                                                # Alternate connection
                                                $db =& $wgLoadBalancer->getConnection( $machineID );
@@ -153,7 +156,7 @@ class Article {
                                                }
                                        }
                                        if ( $db->isOpen() ) {
-                                               $index = wfStrencode( $index );
+                                               $index = $db->strencode( $index );
                                                $res = $db->query( "SELECT blob_data FROM $dbName.$tblName WHERE blob_index='$index'", $fname );
                                                $row = $db->fetchObject( $res );
                                                $text = $row->text_data;
@@ -309,12 +312,30 @@ class Article {
 
        }
 
+       function &getCurContentFields() {
+               global $wgArticleCurContentFields;
+               if ( !$wgArticleCurContentFields ) {
+                       $wgArticleCurContentFields = array( 'cur_text','cur_timestamp','cur_user', 'cur_user_text',
+                         'cur_comment','cur_counter','cur_restrictions','cur_touched' );
+               }
+               return $wgArticleCurContentFields;
+       }
+
+       function &getOldContentFields() {
+               global $wgArticleOldContentFields;
+               if ( !$wgArticleOldContentFields ) {
+                       $wgArticleOldContentFields = array( 'old_namespace','old_title','old_text','old_timestamp', 
+                         'old_user','old_user_text','old_comment','old_flags' );
+               }
+               return $wgArticleOldContentFields;
+       }
 
        # Load the revision (including cur_text) into this object
        function loadContent( $noredir = false )
        {
-               global $wgOut, $wgMwRedir, $wgRequest, $wgIsPg, $wgLoadBalancer;
+               global $wgOut, $wgMwRedir, $wgRequest;
 
+               $dbr =& wfGetDB( DB_READ );
                # Query variables :P
                $oldid = $wgRequest->getVal( 'oldid' );
                $redirect = $wgRequest->getVal( 'redirect' );
@@ -340,16 +361,11 @@ class Article {
                        $id = $this->getID();
                        if ( 0 == $id ) return;
 
-                       $sql = 'SELECT ' .
-                         'cur_text,cur_timestamp,cur_user,cur_user_text,cur_comment,cur_counter,cur_restrictions,cur_touched ' .
-                         "FROM cur WHERE cur_id={$id}";
-                       wfDebug( "$sql\n" );
-                       $res = wfQuery( $sql, DB_READ, $fname );
-                       if ( 0 == wfNumRows( $res ) ) {
+                       $s = $dbr->getArray( 'cur', $this->getCurContentFields(), array( 'cur_id' => $id ), $fname );
+                       if ( $s === false ) { 
                                return;
                        }
 
-                       $s = wfFetchObject( $res );
                        # If we got a redirect, follow it (unless we've been told
                        # not to by either the function parameter or the query
                        if ( ( 'no' != $redirect ) && ( false == $noredir ) &&
@@ -372,14 +388,12 @@ class Article {
                                                }
                                                $rid = $rt->getArticleID();
                                                if ( 0 != $rid ) {
-                                                       $sql = 'SELECT cur_text,cur_timestamp,cur_user,cur_user_text,cur_comment,' .
-                                                         "cur_counter,cur_restrictions,cur_touched FROM cur WHERE cur_id={$rid}";
-                                                       $res = wfQuery( $sql, DB_READ, $fname );
+                                                       $redirRow = $dbr->getArray( 'cur', $this->getContentFields(), array( 'cur_id' => $rid ), $fname );
 
-                                                       if ( 0 != wfNumRows( $res ) ) {
+                                                       if ( $redirRow !== false ) {
                                                                $this->mRedirectedFrom = $this->mTitle->getPrefixedText();
                                                                $this->mTitle = $rt;
-                                                               $s = wfFetchObject( $res );
+                                                               $s = $redirRow;
                                                        }
                                                }
                                        }
@@ -395,20 +409,12 @@ class Article {
                        $this->mTouched = $s->cur_touched;
                        $this->mTitle->mRestrictions = explode( ',', trim( $s->cur_restrictions ) );
                        $this->mTitle->mRestrictionsLoaded = true;
-                       wfFreeResult( $res );
                } else { # oldid set, retrieve historical version
-                       $wgLoadBalancer->force(-1);
-                       $oldtable=$wgIsPg?'"old"':'old';
-                       $sql = "SELECT old_namespace,old_title,old_text,old_timestamp,".
-                               "old_user,old_user_text,old_comment,old_flags FROM old ".
-                               "WHERE old_id={$oldid}";
-                       $res = wfQuery( $sql, DB_READ, $fname );
-                       $wgLoadBalancer->force(0);
-                       if ( 0 == wfNumRows( $res ) ) {
+                       $s = $dbr->getArray( 'old', $this->getOldContentFields(), array( 'old_id' => $oldid ), $fname );
+                       if ( $s === false ) {
                                return;
                        }
 
-                       $s = wfFetchObject( $res );
                        if( $this->mTitle->getNamespace() != $s->old_namespace ||
                                $this->mTitle->getDBkey() != $s->old_title ) {
                                $oldTitle = Title::makeTitle( $s->old_namesapce, $s->old_title );
@@ -421,7 +427,6 @@ class Article {
                        $this->mComment = $s->old_comment;
                        $this->mCounter = 0;
                        $this->mTimestamp = $s->old_timestamp;
-                       wfFreeResult( $res );
                }
                $this->mContentLoaded = true;
                return $this->mContent;
@@ -430,14 +435,15 @@ class Article {
        # Gets the article text without using so many damn globals
        # Returns false on error
        function getContentWithoutUsingSoManyDamnGlobals( $oldid = 0, $noredir = false ) {
-               global $wgMwRedir, $wgIsPg;
+               global $wgMwRedir;
 
                if ( $this->mContentLoaded ) {
                        return $this->mContent;
                }
                $this->mContent = false;
 
-               $fname = 'Article::loadContent';
+               $fname = 'Article::getContentWithout';
+               $dbr =& wfGetDB( DB_READ );
 
                if ( ! $oldid ) {       # Retrieve current version
                        $id = $this->getID();
@@ -445,15 +451,11 @@ class Article {
                                return false;
                        }
 
-                       $sql = 'SELECT ' .
-                         'cur_text,cur_timestamp,cur_user,cur_counter,cur_restrictions,cur_touched ' .
-                         "FROM cur WHERE cur_id={$id}";
-                       $res = wfQuery( $sql, DB_READ, $fname );
-                       if ( 0 == wfNumRows( $res ) ) {
+                       $s = $dbr->getArray( 'cur', $this->getCurContentFields(), array( 'cur_id' => $id ), $fname );
+                       if ( $s === false ) { 
                                return false;
                        }
 
-                       $s = wfFetchObject( $res );
                        # If we got a redirect, follow it (unless we've been told
                        # not to by either the function parameter or the query
                        if ( !$noredir && $wgMwRedir->matchStart( $s->cur_text ) ) {
@@ -463,14 +465,12 @@ class Article {
                                        if( $rt &&  $rt->getInterwiki() == '' && $rt->getNamespace() != Namespace::getSpecial() ) {
                                                $rid = $rt->getArticleID();
                                                if ( 0 != $rid ) {
-                                                       $sql = 'SELECT cur_text,cur_timestamp,cur_user,' .
-                                                         "cur_counter,cur_restrictions,cur_touched FROM cur WHERE cur_id={$rid}";
-                                                       $res = wfQuery( $sql, DB_READ, $fname );
+                                                       $redirRow = $dbr->getArray( 'cur', $this->getCurContentFields(), array( 'cur_id' => $rid ), $fname );
 
-                                                       if ( 0 != wfNumRows( $res ) ) {
+                                                       if ( $redirRow !== false ) {
                                                                $this->mRedirectedFrom = $this->mTitle->getPrefixedText();
                                                                $this->mTitle = $rt;
-                                                               $s = wfFetchObject( $res );
+                                                               $s = $redirRow;
                                                        }
                                                }
                                        }
@@ -479,27 +479,24 @@ class Article {
 
                        $this->mContent = $s->cur_text;
                        $this->mUser = $s->cur_user;
+                       $this->mUserText = $s->cur_user_text;
+                       $this->mComment = $s->cur_comment;
                        $this->mCounter = $s->cur_counter;
                        $this->mTimestamp = $s->cur_timestamp;
                        $this->mTouched = $s->cur_touched;
                        $this->mTitle->mRestrictions = explode( ",", trim( $s->cur_restrictions ) );
                        $this->mTitle->mRestrictionsLoaded = true;
-                       wfFreeResult( $res );
                } else { # oldid set, retrieve historical version
-                       $oldtable=$wgIsPg?'"old"':'old';
-                       $sql = "SELECT old_text,old_timestamp,old_user,old_flags FROM $oldtable " .
-                         "WHERE old_id={$oldid}";
-                       $res = wfQuery( $sql, DB_READ, $fname );
-                       if ( 0 == wfNumRows( $res ) ) {
+                       $s = $dbr->getArray( 'old', $this->getOldContentFields(), array( 'old_id' => $oldid ) );
+                       if ( $s === false ) { 
                                return false;
                        }
-
-                       $s = wfFetchObject( $res );
                        $this->mContent = Article::getRevisionText( $s );
                        $this->mUser = $s->old_user;
+                       $this->mUserText = $s->old_user_text;
+                       $this->mComment = $s->old_comment;
                        $this->mCounter = 0;
                        $this->mTimestamp = $s->old_timestamp;
-                       wfFreeResult( $res );
                }
                $this->mContentLoaded = true;
                return $this->mContent;
@@ -517,7 +514,8 @@ class Article {
        {
                if ( -1 == $this->mCounter ) {
                        $id = $this->getID();
-                       $this->mCounter = wfGetSQL( 'cur', 'cur_counter', "cur_id={$id}" );
+                       $dbr =& wfGetDB( DB_READ );
+                       $this->mCounter = $dbr->getField( 'cur', 'cur_counter', "cur_id={$id}" );
                }
                return $this->mCounter;
        }
@@ -543,14 +541,15 @@ class Article {
        {
                global $wgOut;
                if ( -1 != $this->mUser ) return;
+               
+               $fname = 'Article::loadLastEdit';
 
-               $sql = 'SELECT cur_user,cur_user_text,cur_timestamp,' .
-                 'cur_comment,cur_minor_edit FROM cur WHERE ' .
-                 'cur_id=' . $this->getID();
-               $res = wfQuery( $sql, DB_READ, 'Article::loadLastEdit' );
+               $dbr =& wfGetDB( DB_READ );
+               $s = $dbr->getArray( 'cur', 
+                 array( 'cur_user','cur_user_text','cur_timestamp', 'cur_comment','cur_minor_edit' ),
+                 array( 'cur_id' => $this->getID() ), $fname );
 
-               if ( wfNumRows( $res ) > 0 ) {
-                       $s = wfFetchObject( $res );
+               if ( $s !== false ) {
                        $this->mUser = $s->cur_user;
                        $this->mUserText = $s->cur_user_text;
                        $this->mTimestamp = $s->cur_timestamp;
@@ -596,29 +595,33 @@ class Article {
                # XXX: this is expensive; cache this info somewhere.
 
                $title = $this->mTitle;
-
                $contribs = array();
-
-                $sql = 'SELECT old_user, old_user_text, ' .
-                       '  user_real_name, MAX(old_timestamp) as timestamp' .
-                       ' FROM old LEFT JOIN user ON old.old_user = user.user_id ' .
-                      ' WHERE old.old_namespace = ' . $title->getNamespace() .
-                       ' AND old.old_title = "' . $title->getDBkey() . '"' .
-                       ' AND old.old_user != ' . $this->getUser() .
-                       ' GROUP BY old.old_user ' .
-                       ' ORDER BY timestamp DESC ';
+               $dbr = wfGetDB( DB_READ );
+               $oldTable = $dbr->tableName( 'old' );
+               $userTable = $dbr->tableName( 'user' );
+               $encDBkey = $dbr->strencode( $title->getDBkey() );
+               $ns = $title->getNamespace();
+               $user = $this->getUser();
+
+               $sql = "SELECT old_user, old_user_text, user_real_name, MAX(old_timestamp) as timestamp
+                       FROM $oldTable LEFT JOIN $userTable ON old_user = user_id 
+                       WHERE old_namespace = $user
+                       AND old_title = $encDBkey
+                       AND old_user != $user
+                       GROUP BY old_user 
+                       ORDER BY timestamp DESC";
 
                 if ($limit > 0) {
                         $sql .= ' LIMIT '.$limit;
                 }
 
-               $res = wfQuery($sql, DB_READ, $fname);
+               $res = $dbr->query($sql, $fname);
 
-               while ( $line = wfFetchObject( $res ) ) {
+               while ( $line = $dbr->fetchObject( $res ) ) {
                        $contribs[] = array($line->old_user, $line->old_user_text, $line->user_real_name);
                }
 
-               wfFreeResult($res);
+               $dbr->freeResult($res);
 
                return $contribs;
        }
@@ -738,7 +741,7 @@ class Article {
        /* private */ function insertNewArticle( $text, $summary, $isminor, $watchthis )
        {
                global $wgOut, $wgUser, $wgLinkCache, $wgMwRedir;
-               global $wgUseSquid, $wgDeferredUpdateList, $wgInternalServer, $wgIsPg, $wgIsMySQL;
+               global $wgUseSquid, $wgDeferredUpdateList, $wgInternalServer;
 
                $fname = 'Article::insertNewArticle';
 
@@ -754,30 +757,32 @@ class Article {
                $won = wfInvertTimestamp( $now );
                wfSeedRandom();
                $rand = number_format( mt_rand() / mt_getrandmax(), 12, '.', '' );
+               $dbw =& wfGetDB( DB_WRITE );
 
-               if ($wgIsPg) {
-                       $cur_id_column="cur_id,";
-                       $cur_id=wfGetSQL(""," nextval('cur_cur_id_seq')");
-                       $cur_id_value="{$cur_id},";
-               } else {
-                       $cur_id_column="";
-                       $cur_id="";
-                       $cur_id_value="";
-               }
+               $cur_id = $dbw->nextSequenceValue( 'cur_cur_id_seq' ); 
 
                $isminor = ( $isminor && $wgUser->getID() ) ? 1 : 0;
-               $sql = "INSERT INTO cur ({$cur_id_column}cur_namespace,cur_title,cur_text," .
-                 'cur_comment,cur_user,cur_timestamp,cur_minor_edit,cur_counter,' .
-                 'cur_restrictions,cur_user_text,cur_is_redirect,' .
-                 "cur_is_new,cur_random,cur_touched,inverse_timestamp) VALUES ({$cur_id_value}{$ns},'" . wfStrencode( $ttl ) . "', '" .
-                 wfStrencode( $text ) . "', '" .
-                 wfStrencode( $summary ) . "', '" .
-                 $wgUser->getID() . "', '{$now}', " .
-                 $isminor . ", 0, '', '" .
-                 wfStrencode( $wgUser->getName() ) . "', $redir, 1, $rand, '{$now}', '{$won}')";
-               $res = wfQuery( $sql, DB_WRITE, $fname );
-
-               $newid = $wgIsPg?$cur_id:wfInsertId();
+
+               $dbw->insertArray( 'cur', array(
+                       'cur_id' => $cur_id,
+                       'cur_namespace' => $ns,
+                       'cur_title' => $ttl,
+                       'cur_text' => $text,
+                       'cur_comment' => $summary,
+                       'cur_user' => $wgUser->getID(),
+                       'cur_timestamp' => $now,
+                       'cur_minor_edit' => $isminor,
+                       'cur_counter' => 0,
+                       'cur_restrictions' => '',
+                       'cur_user_text' => $wgUser->getName(),
+                       'cur_is_redirect' => $redir,
+                       'cur_is_new' => 1,
+                       'cur_random' => $rand,
+                       'cur_touched' => $now,
+                       'inverse_timestamp' => $won,
+               ), $fname );
+
+               $newid = $dbw->insertId();
                $this->mTitle->resetArticleID( $newid );
 
                Article::onArticleCreate( $this->mTitle );
@@ -793,8 +798,7 @@ class Article {
 
                # The talk page isn't in the regular link tables, so we need to update manually:
                $talkns = $ns ^ 1; # talk -> normal; normal -> talk
-               $sql = "UPDATE cur set cur_touched='$now' WHERE cur_namespace=$talkns AND cur_title='" . wfStrencode( $ttl ) . "'";
-               wfQuery( $sql, DB_WRITE );
+               $dbw->updateArray( 'cur', array( 'cur_touched' => $now ), array( 'cur_namespace' => $talkns, 'cur_title' => $ttl ), $fname );
 
                # standard deferred updates
                $this->editUpdates( $text );
@@ -884,9 +888,10 @@ class Article {
                global $wgOut, $wgUser, $wgLinkCache;
                global $wgDBtransactions, $wgMwRedir;
                global $wgUseSquid, $wgInternalServer;
-               global $wgIsPg;
+               
                $fname = 'Article::updateArticle';
-
+               $good = true;
+               
                if ( $this->mMinorEdit ) { $me1 = 1; } else { $me1 = 0; }
                if ( $minor && $wgUser->getID() ) { $me2 = 1; } else { $me2 = 0; }
                if ( preg_match( "/^((" . $wgMwRedir->getBaseRegex() . ')[^\\n]+)/i', $text, $m ) ) {
@@ -896,78 +901,87 @@ class Article {
                else { $redir = 0; }
 
                $text = $this->preSaveTransform( $text );
+               $dbw =& wfGetDB( DB_WRITE );
 
                # Update article, but only if changed.
 
+               # It's important that we either rollback or complete, otherwise an attacker could 
+               # overwrite cur entries by sending precisely timed user aborts. Random bored users 
+               # could conceivably have the same effect, especially if cur is locked for long periods.
                if( $wgDBtransactions ) {
-                       $sql = 'BEGIN';
-                       wfQuery( $sql, DB_WRITE );
+                       $dbw->query( 'BEGIN', $fname );
+               } else {
+                       $userAbort = ignore_user_abort( true );
                }
+               
                $oldtext = $this->getContent( true );
 
                if ( 0 != strcmp( $text, $oldtext ) ) {
                        $this->mCountAdjustment = $this->isCountable( $text )
                          - $this->isCountable( $oldtext );
-
                        $now = wfTimestampNow();
                        $won = wfInvertTimestamp( $now );
-                       $sql = "UPDATE cur SET cur_text='" . wfStrencode( $text ) .
-                         "',cur_comment='" .  wfStrencode( $summary ) .
-                         "',cur_minor_edit={$me2}, cur_user=" . $wgUser->getID() .
-                         ",cur_timestamp='{$now}',cur_user_text='" .
-                         wfStrencode( $wgUser->getName() ) .
-                         "',cur_is_redirect={$redir}, cur_is_new=0, cur_touched='{$now}', inverse_timestamp='{$won}' " .
-                         "WHERE cur_id=" . $this->getID() .
-                         " AND cur_timestamp='" . $this->getTimestamp() . "'";
-                       $res = wfQuery( $sql, DB_WRITE, $fname );
-
-                       if( wfAffectedRows() == 0 ) {
-                               /* Belated edit conflict! Run away!! */
-                               return false;
-                       }
 
-                       # This overwrites $oldtext if revision compression is on
-                       $flags = Article::compressRevisionText( $oldtext );
-
-                       $oldtable=$wgIsPg?'"old"':'old';
-                       if ($wgIsPg) {
-                               $oldtable='"old"';
-                               $old_id_column='old_id,';
-                               $old_id=wfGetSQL(""," nextval('old_old_id_seq')");
-                               $old_id_value=$old_id.',';
+                       # First update the cur row
+                       $dbw->updateArray( 'cur', 
+                               array( /* SET */ 
+                                       'cur_text' => $text,
+                                       'cur_comment' => $summary,
+                                       'cur_minor_edit' => $me2, 
+                                       'cur_user' => $wgUser->getID(),
+                                       'cur_timestamp' => $now,
+                                       'cur_user_text' => $wgUser->getName(),
+                                       'cur_is_redirect' => $redir, 
+                                       'cur_is_new' => 0,
+                                       'cur_touched' => $now, 
+                                       'inverse_timestamp' => $won
+                               ), array( /* WHERE */
+                                       'cur_id' => $this->getID(), 
+                                       'cur_timestamp' => $this->getTimestamp() 
+                               ), $fname 
+                       );
+                       
+                       if( $dbw->affectedRows() == 0 ) {
+                               /* Belated edit conflict! Run away!! */
+                               $good = false;
                        } else {
-                               $oldtable='old';
-                               $old_id_column='';
-                               $old_id_value='';
+                               # Now insert the previous revision into old
+
+                               # This overwrites $oldtext if revision compression is on
+                               $flags = Article::compressRevisionText( $oldtext );
+                               
+                               $dbw->insertArray( 'old', 
+                                       array(
+                                               'old_id' => $dbw->nextSequenceValue( 'old_old_id_seq' ),
+                                               'old_namespace' => $this->mTitle->getNamespace(),
+                                               'old_title' => $this->mTitle->getDBkey(),
+                                               'old_text' => $oldtext,
+                                               'old_comment' => $this->getComment(),
+                                               'old_user' => $this->getUser(),
+                                               'old_user_text' => $this->getUserText(),
+                                               'old_timestamp' => $this->getTimestamp(),
+                                               'old_minor_edit' => $me1,
+                                               'inverse_timestamp' => wfInvertTimestamp( $this->getTimestamp() ),
+                                               'old_flags' => $flags,
+                                       ), $fname 
+                               );
+                               
+                               $oldid = $dbw->insertId();
+
+                               $bot = (int)($wgUser->isBot() || $forceBot);
+                               RecentChange::notifyEdit( $now, $this->mTitle, $me2, $wgUser, $summary, 
+                                       $oldid, $this->getTimestamp(), $bot );
+                               Article::onArticleEdit( $this->mTitle );
                        }
-
-                       $sql = "INSERT INTO $oldtable ({$old_id_column}old_namespace,old_title,old_text," .
-                         'old_comment,old_user,old_user_text,old_timestamp,' .
-                         'old_minor_edit,inverse_timestamp,old_flags) VALUES (' .
-                         $old_id_value.
-                         $this->mTitle->getNamespace() . ", '" .
-                         wfStrencode( $this->mTitle->getDBkey() ) . "', '" .
-                         wfStrencode( $oldtext ) . "', '" .
-                         wfStrencode( $this->getComment() ) . "', " .
-                         $this->getUser() . ", '" .
-                         wfStrencode( $this->getUserText() ) . "', '" .
-                         $this->getTimestamp() . "', " . $me1 . ", '" .
-                         wfInvertTimestamp( $this->getTimestamp() ) . "','$flags')";
-                       $res = wfQuery( $sql, DB_WRITE, $fname );
-
-                       $oldid = $wgIsPg?$old_id:wfInsertId( $res );
-
-                       $bot = (int)($wgUser->isBot() || $forceBot);
-                       RecentChange::notifyEdit( $now, $this->mTitle, $me2, $wgUser, $summary,
-                               $oldid, $this->getTimestamp(), $bot );
-                       Article::onArticleEdit( $this->mTitle );
                }
 
                if( $wgDBtransactions ) {
-                       $sql = 'COMMIT';
-                       wfQuery( $sql, DB_WRITE );
+                       $dbw->query( 'COMMIT', $fname );
+               } else {
+                       ignore_user_abort( $userAbort );
                }
 
+               if ( $good ) {
                if ($watchthis) {
                        if (!$this->mTitle->userIsWatching()) $this->watch();
                } else {
@@ -986,9 +1000,9 @@ class Article {
                        $titles = $this->mTitle->getLinksTo();
                        Title::touchArray( $titles );
                        if ( $wgUseSquid ) {
-                               foreach ( $titles as $title ) {
-                                       $urls[] = $title->getInternalURL();
-                               }
+                                       foreach ( $titles as $title ) {
+                                               $urls[] = $title->getInternalURL();
+                                       }
                        }
                }
 
@@ -1000,7 +1014,8 @@ class Article {
                }
 
                $this->showArticle( $text, wfMsg( 'updated' ), $sectionanchor );
-               return true;
+               }
+               return $good;
        }
 
        # After we've either updated or inserted the article, update
@@ -1093,10 +1108,15 @@ class Article {
                $reason = $wgRequest->getText( 'wpReasonProtect' );
 
                if ( $confirm ) {
-
-                       $sql = "UPDATE cur SET cur_touched='" . wfTimestampNow() . "'," .
-                               "cur_restrictions='{$limit}' WHERE cur_id={$id}";
-                       wfQuery( $sql, DB_WRITE, 'Article::protect' );
+                       $dbw =& wfGetDB( DB_WRITE );
+                       $dbw->updateArray( 'cur', 
+                               array( /* SET */
+                                       'cur_touched' => wfTimestampNow(),
+                                       'cur_restrictions' => (string)$limit
+                               ), array( /* WHERE */
+                                       'cur_id' => $id 
+                               ), 'Article::protect' 
+                       );
 
                        $log = new LogPage( wfMsg( 'protectlogpage' ), wfMsg( 'protectlogtext' ) );
                        if ( $limit === "" ) {
@@ -1185,7 +1205,7 @@ class Article {
        # UI entry point for page deletion
        function delete()
        {
-               global $wgUser, $wgOut, $wgMessageCache, $wgRequest, $wgIsPg;
+               global $wgUser, $wgOut, $wgMessageCache, $wgRequest;
                $fname = 'Article::delete';
                $confirm = $wgRequest->getBool( 'wpConfirm' ) && $wgRequest->wasPosted();
                $reason = $wgRequest->getText( 'wpReason' );
@@ -1218,22 +1238,33 @@ 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 );
                $ns = $this->mTitle->getNamespace();
                $title = $this->mTitle->getDBkey();
-               $etitle = wfStrencode( $title );
-               $oldtable=$wgIsPg?'"old"':'old';
-               $sql = "SELECT old_text,old_flags FROM $oldtable WHERE old_namespace=$ns and old_title='$etitle' ORDER BY inverse_timestamp LIMIT 1";
-               $res = wfQuery( $sql, DB_READ, $fname );
-               if( ($old=wfFetchObject($res)) && !$confirm ) {
+               $old = $dbr->getArray( 'old', 
+                       array( 'old_text', 'old_flags' ), 
+                       array(
+                               'old_namespace' => $ns,
+                               'old_title' => $title,
+                       ), $fname, array( 'ORDER BY' => 'inverse_timestamp' ) 
+               );
+               
+               if( $old !== false && !$confirm ) {
                        $skin=$wgUser->getSkin();
                        $wgOut->addHTML('<b>'.wfMsg('historywarning'));
                        $wgOut->addHTML( $skin->historyLink() .'</b>');
                }
-
-               $sql="SELECT cur_text FROM cur WHERE cur_namespace=$ns and cur_title='$etitle'";
-               $res=wfQuery($sql, DB_READ, $fname);
-               if( ($s=wfFetchObject($res))) {
-
+               
+               # Fetch cur_text
+               $s = $dbr->getArray( 'cur', 
+                       array( 'cur_text' ), 
+                       array( 
+                               'cur_namespace' => $ns, 
+                               'cur_title' => $title,
+                       ), $fname
+               );
+               
+               if( $s !== false ) {
                        # if this is a mini-text, we can paste part of it into the deletion reason
 
                        #if this is empty, an earlier revision may contain "useful" text
@@ -1368,9 +1399,10 @@ class Article {
 
                $fname = 'Article::doDeleteArticle';
                wfDebug( $fname."\n" );
-
+               
+               $dbw =& wfGetDB( DB_WRITE );
                $ns = $this->mTitle->getNamespace();
-               $t = wfStrencode( $this->mTitle->getDBkey() );
+               $t = $this->mTitle->getDBkey();
                $id = $this->mTitle->getArticleID();
 
                if ( '' == $t || $id == 0 ) {
@@ -1401,68 +1433,75 @@ class Article {
                Title::touchArray( $linksTo );
 
                # Move article and history to the "archive" table
-               $sql = 'INSERT INTO archive (ar_namespace,ar_title,ar_text,' .
-                 'ar_comment,ar_user,ar_user_text,ar_timestamp,ar_minor_edit,' .
-                 'ar_flags) SELECT cur_namespace,cur_title,cur_text,cur_comment,' .
-                 'cur_user,cur_user_text,cur_timestamp,cur_minor_edit,0 FROM cur ' .
-                 "WHERE cur_namespace={$ns} AND cur_title='{$t}'";
-               wfQuery( $sql, DB_WRITE, $fname );
-
-               $sql = 'INSERT INTO archive (ar_namespace,ar_title,ar_text,' .
-                 'ar_comment,ar_user,ar_user_text,ar_timestamp,ar_minor_edit,' .
-                 'ar_flags) SELECT old_namespace,old_title,old_text,old_comment,' .
-                 'old_user,old_user_text,old_timestamp,old_minor_edit,old_flags ' .
-                 "FROM old WHERE old_namespace={$ns} AND old_title='{$t}'";
-               wfQuery( $sql, DB_WRITE, $fname );
-
+               $archiveTable = $dbw->tableName( 'archive' );
+               $oldTable = $dbw->tableName( 'old' );
+               $curTable = $dbw->tableName( 'cur' );
+               $recentchangesTable = $dbw->tableName( 'recentchanges' );
+               $linksTable = $dbw->tableName( 'links' );
+               $brokenlinksTable = $dbw->tableName( 'brokenlinks' );
+               
+               $dbw->insertSelect( 'archive', 'cur', 
+                       array(
+                               'ar_namespace' => 'cur_namespace',
+                               'ar_title' => 'cur_title',
+                               'ar_text' => 'cur_text',
+                               'ar_comment' => 'cur_comment',
+                               'ar_user' => 'cur_user',
+                               'ar_user_text' => 'cur_user_text',
+                               'ar_timestamp' => 'cur_timestamp',
+                               'ar_minor_edit' => 'cur_minor_edit',
+                               'ar_flags' => 0,
+                       ), array(
+                               'cur_namespace' => $ns,
+                               'cur_title' => $t,
+                       ), $fname 
+               );
+               
+               $dbw->insertSelect( 'archive', 'old',
+                       array(
+                               'ar_namespace' => 'old_namespace',
+                               'ar_title' => 'old_title',
+                               'ar_text' => 'old_text',
+                               'ar_comment' => 'old_comment',
+                               'ar_user' => 'old_user',
+                               'ar_user_text' => 'old_user_text',
+                               'ar_timestamp' => 'old_timestamp',
+                               'ar_minor_edit' => 'old_minor_edit',
+                               'ar_flags' => 'old_flags'
+                       ), array(
+                               'old_namespace' => $ns,
+                               'old_title' => $t,
+                       ), $fname
+               );
+               
                # Now that it's safely backed up, delete it
 
-               $sql = "DELETE FROM cur WHERE cur_namespace={$ns} AND " .
-                 "cur_title='{$t}'";
-               wfQuery( $sql, DB_WRITE, $fname );
-
-               $sql = "DELETE FROM old WHERE old_namespace={$ns} AND " .
-                 "old_title='{$t}'";
-               wfQuery( $sql, DB_WRITE, $fname );
-
-               $sql = "DELETE FROM recentchanges WHERE rc_namespace={$ns} AND " .
-                 "rc_title='{$t}'";
-                       wfQuery( $sql, DB_WRITE, $fname );
+               $dbw->delete( 'cur', array( 'cur_namespace' => $ns, 'cur_title' => $t ), $fname );
+               $dbw->delete( 'old', array( 'old_namespace' => $ns, 'old_title' => $t ), $fname );
+               $dbw->delete( 'recentchanges', array( 'rc_namespace' => $ns, 'rc_title' => $t ), $fname );
 
                # Finally, clean up the link tables
-               $t = wfStrencode( $this->mTitle->getPrefixedDBkey() );
+               $t = $this->mTitle->getPrefixedDBkey();
 
                Article::onArticleDelete( $this->mTitle );
 
-               $sql = 'INSERT INTO brokenlinks (bl_from,bl_to) VALUES ';
-               $first = true;
-
+               # Insert broken links
+               $brokenLinks = array();
                foreach ( $linksTo as $titleObj ) {
-                       if ( ! $first ) { $sql .= ','; }
-                       $first = false;
                        # Get article ID. Efficient because it was loaded into the cache by getLinksTo().
                        $linkID = $titleObj->getArticleID();
-                       $sql .= "({$linkID},'{$t}')";
-               }
-               if ( ! $first ) {
-                       wfQuery( $sql, DB_WRITE, $fname );
-               }
-
-               $sql = "DELETE FROM links WHERE l_to={$id}";
-               wfQuery( $sql, DB_WRITE, $fname );
-
-               $sql = "DELETE FROM links WHERE l_from={$id}";
-               wfQuery( $sql, DB_WRITE, $fname );
-
-               $sql = "DELETE FROM imagelinks WHERE il_from={$id}";
-               wfQuery( $sql, DB_WRITE, $fname );
-
-               $sql = "DELETE FROM brokenlinks WHERE bl_from={$id}";
-               wfQuery( $sql, DB_WRITE, $fname );
-
-               $sql = "DELETE FROM categorylinks WHERE cl_from={$id}";
-               wfQuery( $sql, DB_WRITE, $fname );
-
+                       $brokenLinks[] = array( 'bl_from' => $linkID, 'bl_to' => $t );
+               }
+               $dbw->insertArray( 'brokenlinks', $brokenLinks, $fname );
+               
+               # Delete live links
+               $dbw->delete( 'links', array( 'l_to' => $id ) );
+               $dbw->delete( 'links', array( 'l_from' => $id ) );
+               $dbw->delete( 'imagelinks', array( 'il_from' => $id ) );
+               $dbw->delete( 'brokenlinks', array( 'bl_from' => $id ) );
+               $dbw->delete( 'categorylinks', array( 'cl_from' => $id ) );
+
+               # Log the deletion
                $log = new LogPage( wfMsg( 'dellogpage' ), wfMsg( 'dellogpagetext' ) );
                $art = $this->mTitle->getPrefixedText();
                $log->addEntry( wfMsg( 'deletedarticle', $art ), $reason );
@@ -1475,8 +1514,9 @@ class Article {
 
        function rollback()
        {
-               global $wgUser, $wgLang, $wgOut, $wgRequest, $wgIsMySQL, $wgIsPg;
-
+               global $wgUser, $wgLang, $wgOut, $wgRequest;
+               $fname = "Article::rollback";
+               
                if ( ! $wgUser->isSysop() ) {
                        $wgOut->sysopRequired();
                        return;
@@ -1485,25 +1525,27 @@ class Article {
                        $wgOut->readOnlyPage( $this->getContent( true ) );
                        return;
                }
+               $dbw =& wfGetDB( DB_WRITE );
 
                # Enhanced rollback, marks edits rc_bot=1
                $bot = $wgRequest->getBool( 'bot' );
 
                # Replace all this user's current edits with the next one down
-               $tt = wfStrencode( $this->mTitle->getDBKey() );
+               $tt = $this->mTitle->getDBKey();
                $n = $this->mTitle->getNamespace();
 
-               # Get the last editor
-               $sql = 'SELECT cur_id,cur_user,cur_user_text,cur_comment ' .
-                      "FROM cur WHERE cur_title='{$tt}' AND cur_namespace={$n}";
-               $res = wfQuery( $sql, DB_READ );
-               if( ($x = wfNumRows( $res )) != 1 ) {
+               # Get the last editor, lock table exclusively
+               $s = $dbw->getArray( 'cur', 
+                       array( 'cur_id','cur_user','cur_user_text','cur_comment' ),
+                       array( 'cur_title' => $tt, 'cur_namespace' => $n ),
+                       $fname, 'FOR UPDATE'
+               );
+               if( $s === false ) {
                        # Something wrong
                        $wgOut->addHTML( wfMsg( 'notanarticle' ) );
                        return;
                }
-               $s = wfFetchObject( $res );
-               $ut = wfStrencode( $s->cur_user_text );
+               $ut = $dbw->strencode( $s->cur_user_text );
                $uid = $s->cur_user;
                $pid = $s->cur_id;
 
@@ -1523,28 +1565,31 @@ class Article {
                }
 
                # Get the last edit not by this guy
-
-               $use_index=$wgIsMySQL?"USE INDEX (name_title_timestamp)":"";
-               $oldtable=$wgIsPg?'"old"':'old';
-               $sql = 'SELECT old_text,old_user,old_user_text,old_timestamp,old_flags ' .
-               "FROM $oldtable {$use_index} " .
-               "WHERE old_namespace={$n} AND old_title='{$tt}' " .
-               "AND (old_user <> {$uid} OR old_user_text <> '{$ut}') " .
-               'ORDER BY inverse_timestamp LIMIT 1';
-               $res = wfQuery( $sql, DB_READ );
-               if( wfNumRows( $res ) != 1 ) {
+               $s = $dbw->getArray( 'old', 
+                       array( 'old_text','old_user','old_user_text','old_timestamp','old_flags' ),
+                       array( 
+                               'old_namespace' => $n, 
+                               'old_title' => $tt,
+                               "old_user <> {$uid} OR old_user_text <> '{$ut}'"
+                       ), $fname, array( 'FOR UPDATE', 'USE INDEX' => 'name_title_timestamp' )
+               );
+               if( $s === false ) {
                        # Something wrong
                        $wgOut->setPageTitle(wfMsg('rollbackfailed'));
                        $wgOut->addHTML( wfMsg( 'cantrollback' ) );
                        return;
                }
-               $s = wfFetchObject( $res );
 
                if ( $bot ) {
                        # Mark all reverted edits as bot
-                       $sql = 'UPDATE recentchanges SET rc_bot=1 WHERE ' .
-                               "rc_cur_id=$pid AND rc_user=$uid AND rc_timestamp > '{$s->old_timestamp}'";
-                       wfQuery( $sql, DB_WRITE, $fname );
+                       $dbw->updateArray( 'recentchanges', 
+                               array( /* SET */ 
+                                       'rc_bot' => 1 
+                               ), array( /* WHERE */
+                                       'rc_user' => $uid,
+                                       "rc_timestamp > '{$s->old_timestamp}'",
+                               ), $fname 
+                       );
                }
 
                # Save it!
@@ -1583,12 +1628,13 @@ class Article {
        {
                global $wgDeferredUpdateList, $wgDBname, $wgMemc;
                global $wgMessageCache;
-
+               
                wfSeedRandom();
                if ( 0 == mt_rand( 0, 999 ) ) {
+                       $dbw =& wfGetDB( DB_WRITE );
                        $cutoff = wfUnix2Timestamp( time() - ( 7 * 86400 ) );
                        $sql = "DELETE FROM recentchanges WHERE rc_timestamp < '{$cutoff}'";
-                       wfQuery( $sql, DB_WRITE );
+                       $dbw->query( $sql );
                }
                $id = $this->getID();
                $title = $this->mTitle->getPrefixedDBkey();
@@ -1686,9 +1732,10 @@ class Article {
        # Loads cur_touched and returns a value indicating if it should be used
        function checkTouched() {
                $id = $this->getID();
-               $sql = 'SELECT cur_touched,cur_is_redirect FROM cur WHERE cur_id='.$id;
-               $res = wfQuery( $sql, DB_READ, 'Article::checkTouched' );
-               if( $s = wfFetchObject( $res ) ) {
+               $dbr =& wfGetDB( DB_READ );
+               $s = $dbr->getArray( 'cur', array( 'cur_touched', 'cur_is_redirect' ), 
+                       array( 'cur_id' => $id ), $fname );
+               if( $s !== false ) {
                        $this->mTouched = $s->cur_touched;
                        return !$s->cur_is_redirect;
                } else {
@@ -1698,24 +1745,35 @@ class Article {
 
        # Edit an article without doing all that other stuff
        function quickEdit( $text, $comment = '', $minor = 0 ) {
-               global $wgUser, $wgMwRedir, $wgIsPg;
+               global $wgUser, $wgMwRedir;
                $fname = 'Article::quickEdit';
                wfProfileIn( $fname );
 
+               $dbw =& wfGetDB( DB_WRITE );
                $ns = $this->mTitle->getNamespace();
                $dbkey = $this->mTitle->getDBkey();
-               $encDbKey = wfStrencode( $dbkey );
+               $encDbKey = $dbw->strencode( $dbkey );
                $timestamp = wfTimestampNow();
 
                # Save to history
-                $oldtable=$wgIsPg?'"old"':'old';
-               $sql = "INSERT INTO $oldtable (old_namespace,old_title,old_text,old_comment,old_user,old_user_text,old_timestamp,inverse_timestamp)
-                 SELECT cur_namespace,cur_title,cur_text,cur_comment,cur_user,cur_user_text,cur_timestamp,99999999999999-cur_timestamp
-                 FROM cur WHERE cur_namespace=$ns AND cur_title='$encDbKey'";
-               wfQuery( $sql, DB_WRITE );
+               $dbw->insertSelect( 'old', 'cur',
+                       array(
+                               'old_namespace' => 'cur_namespace',
+                               'old_title' => 'cur_title',
+                               'old_text' => 'cur_text',
+                               'old_comment' => 'cur_comment',
+                               'old_user' => 'cur_user',
+                               'old_user_text' => 'cur_user_text',
+                               'old_timestamp' => 'cur_timestamp',
+                               'inverse_timestamp' => '99999999999999-cur_timestamp',
+                       ), array(
+                               'cur_namespace' => $ns,
+                               'cur_title' => $dbkey,
+                       ), $fname 
+               );
 
                # Use the affected row count to determine if the article is new
-               $numRows = wfAffectedRows();
+               $numRows = $dbw->affectedRows();
 
                # Make an array of fields to be inserted
                $fields = array(
@@ -1733,14 +1791,14 @@ class Article {
                if ( $numRows ) {
                        # Update article
                        $fields['cur_is_new'] = 0;
-                       wfUpdateArray( 'cur', $fields, array( 'cur_namespace' => $ns, 'cur_title' => $dbkey ), $fname );
+                       $dbw->updateArray( 'cur', $fields, array( 'cur_namespace' => $ns, 'cur_title' => $dbkey ), $fname );
                } else {
                        # Insert new article
                        $fields['cur_is_new'] = 1;
                        $fields['cur_namespace'] = $ns;
                        $fields['cur_title'] = $dbkey;
                        $fields['cur_random'] = $rand = number_format( mt_rand() / mt_getrandmax(), 12, '.', '' );
-                       wfInsertArray( 'cur', $fields, $fname );
+                       $dbw->insertArray( 'cur', $fields, $fname );
                }
                wfProfileOut( $fname );
        }
@@ -1750,45 +1808,49 @@ class Article {
                $id = intval( $id );
                global $wgHitcounterUpdateFreq;
 
+               $dbw =& wfGetDB( DB_WRITE );
+               $curTable = $dbw->tableName( 'cur' );
+               $hitcounterTable = $dbw->tableName( 'hitcounter' );
+               $acchitsTable = $dbw->tableName( 'acchits' );
+               
                if( $wgHitcounterUpdateFreq <= 1 ){ //
-                       wfQuery('UPDATE cur SET cur_counter = cur_counter + 1 ' .
-                               'WHERE cur_id = '.$id, DB_WRITE);
+                       $dbw->query( "UPDATE $curTable SET cur_counter = cur_counter + 1 WHERE cur_id = $id" );
                        return;
                }
 
                # Not important enough to warrant an error page in case of failure
-               $oldignore = wfIgnoreSQLErrors( true );
+               $oldignore = $dbw->setIgnoreErrors( true ); 
 
-               wfQuery("INSERT INTO hitcounter (hc_id) VALUES ({$id})", DB_WRITE);
+               $dbw->query( "INSERT INTO $hitcounterTable (hc_id) VALUES ({$id})" );
 
                $checkfreq = intval( $wgHitcounterUpdateFreq/25 + 1 );
-               if( (rand() % $checkfreq != 0) or (wfLastErrno() != 0) ){
+               if( (rand() % $checkfreq != 0) or ($dbw->lastErrno() != 0) ){
                        # Most of the time (or on SQL errors), skip row count check
-                       wfIgnoreSQLErrors( $oldignore );
+                       $dbw->setIgnoreErrors( $oldignore );
                        return;
                }
 
-               $res = wfQuery('SELECT COUNT(*) as n FROM hitcounter', DB_WRITE);
-               $row = wfFetchObject( $res );
+               $res = $dbw->query("SELECT COUNT(*) as n FROM $hitcounterTable");
+               $row = $dbw->fetchObject( $res );
                $rown = intval( $row->n );
                if( $rown >= $wgHitcounterUpdateFreq ){
                        wfProfileIn( 'Article::incViewCount-collect' );
                        $old_user_abort = ignore_user_abort( true );
 
-                       wfQuery('LOCK TABLES hitcounter WRITE', DB_WRITE);
-                       wfQuery('CREATE TEMPORARY TABLE acchits TYPE=HEAP '.
-                               'SELECT hc_id,COUNT(*) AS hc_n FROM hitcounter '.
-                               'GROUP BY hc_id', DB_WRITE);
-                       wfQuery('DELETE FROM hitcounter', DB_WRITE);
-                       wfQuery('UNLOCK TABLES', DB_WRITE);
-                       wfQuery('UPDATE cur,acchits SET cur_counter=cur_counter + hc_n '.
-                               'WHERE cur_id = hc_id', DB_WRITE);
-                       wfQuery('DROP TABLE acchits', DB_WRITE);
+                       $dbw->query("LOCK TABLES $hitcounterTable WRITE");
+                       $dbw->query("CREATE TEMPORARY TABLE $acchitsTable TYPE=HEAP ".
+                               "SELECT hc_id,COUNT(*) AS hc_n FROM $hitcounterTable ".
+                               'GROUP BY hc_id');
+                       $dbw->query("DELETE FROM $hitcounterTable");
+                       $dbw->query('UNLOCK TABLES');
+                       $dbw->query("UPDATE $curTable,$acchitsTable SET cur_counter=cur_counter + hc_n ".
+                               'WHERE cur_id = hc_id');
+                       $dbw->query("DROP TABLE $acchitsTable");
 
                        ignore_user_abort( $old_user_abort );
                        wfProfileOut( 'Article::incViewCount-collect' );
                }
-               wfIgnoreSQLErrors( $oldignore );
+               $dbw->setIgnoreErrors( $oldignore );
        }
 
        # The onArticle*() functions are supposed to be a kind of hooks
index e5df262..80b102a 100644 (file)
@@ -45,31 +45,31 @@ class Block
        # Get a ban from the DB, with either the given address or the given username
        function load( $address = "", $user = 0, $killExpired = true ) 
        {
-               global $wgLoadBalancer;
-                $fname = 'Block::load';
+               $fname = 'Block::load';
+
                $ret = false;
                $killed = false;
-               
+               $dbr =& wfGetDB( DB_READ );
+               $ipblocks = $dbr->tableName( 'ipblocks' );
+
                if ( 0 == $user && $address=="" ) {
-                       $sql = "SELECT * from ipblocks";
+                       $sql = "SELECT * from $ipblocks";
                } elseif ($address=="") {
-                       $sql = "SELECT * FROM ipblocks WHERE ipb_user={$user}";
+                       $sql = "SELECT * FROM $ipblocks WHERE ipb_user={$user}";
                } elseif ($user=="") {
-                       $sql = "SELECT * FROM ipblocks WHERE ipb_address='" . wfStrencode( $address ) . "'";
+                       $sql = "SELECT * FROM $ipblocks WHERE ipb_address='" . $dbr->strencode( $address ) . "'";
                } else {
-                       $sql = "SELECT * FROM ipblocks WHERE (ipb_address='" . wfStrencode( $address ) . 
+                       $sql = "SELECT * FROM $ipblocks WHERE (ipb_address='" . $dbr->strencode( $address ) . 
                                "' OR ipb_user={$user})";
                }
 
-               $wgLoadBalancer->force(-1);
-                $res = wfQuery( $sql, DB_READ, $fname );
-               $wgLoadBalancer->force(0);
-                if ( 0 == wfNumRows( $res ) ) {
+               $res = $dbr->query( $sql, $fname );
+               if ( 0 == $dbr->numRows( $res ) ) {
                        # User is not blocked
                        $this->clear();
                } else {
                        # Get first block
-                       $row = wfFetchObject( $res );
+                       $row = $dbr->fetchObject( $res );
                        $this->initFromRow( $row );
 
                        if ( $killExpired ) {
@@ -77,7 +77,7 @@ class Block
                                do {
                                        $killed = $this->deleteIfExpired();
                                        if ( $killed ) {
-                                               $row = wfFetchObject( $res );
+                                               $row = $dbr->fetchObject( $res );
                                                if ( $row ) {
                                                        $this->initFromRow( $row );
                                                }
@@ -95,7 +95,7 @@ class Block
                                $ret = true;
                        }
                }
-               wfFreeResult( $res );
+               $dbr->freeResult( $res );
                return $ret;
        }
        
@@ -132,8 +132,11 @@ class Block
        # Callback with a Block object for every block
        /*static*/ function enumBlocks( $callback, $tag, $killExpired = true ) 
        {
-               $sql = 'SELECT * FROM ipblocks ORDER BY ipb_timestamp DESC';
-               $res = wfQuery( $sql, DB_READ, 'Block::enumBans' );
+               $dbr =& wfGetDB( DB_READ );
+               $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 ) ) {
@@ -152,24 +155,31 @@ class Block
        function delete() 
        {
                $fname = 'Block::delete';
+               $dbw =& wfGetDB( DB_WRITE );
+
                if ( $this->mAddress == "" ) {
-                       $sql = "DELETE FROM ipblocks WHERE ipb_id={$this->mId}";
+                       $condition = array( 'ipb_id' => $this->mId );
                } else {
-                       $sql = "DELETE FROM ipblocks WHERE ipb_address='" .
-                               wfStrencode( $this->mAddress ) . "'";
+                       $condition = array( 'ipb_address' => $this->mAddress );
                }
-               wfQuery( $sql, DB_WRITE, 'Block::delete' );
-
+               $dbw->delete( 'ipblocks', $condition, $fname );
                $this->clearCache();
        }
 
        function insert() 
        {
-               $sql = 'INSERT INTO ipblocks ' .
-                 '(ipb_address, ipb_user, ipb_by, ipb_reason, ipb_timestamp, ipb_auto, ipb_expiry )' . 
-                 "VALUES ('" . wfStrencode( $this->mAddress ) . "', {$this->mUser}, {$this->mBy}, '" . 
-                 wfStrencode( $this->mReason ) . "','{$this->mTimestamp}', {$this->mAuto}, '{$this->mExpiry}')";
-               wfQuery( $sql, DB_WRITE, 'Block::insert' );
+               $dbw =& wfGetDB( DB_WRITE );
+               $dbw->insertArray( 'ipblocks',
+                       array(
+                               'ipb_address' => $this->mAddress,
+                               'ipb_user' => $this->mUser,
+                               'ipb_by' => $this->mBy,
+                               'ipb_reason' => $this->mReason,
+                               'ipb_timestamp' => $this->mTimestamp,
+                               'ipb_auto' => $this->mAuto,
+                               'ipb_expiry' => $this->mExpiry,
+                       ), 'Block::insert' 
+               );
 
                $this->clearCache();
        }
@@ -204,10 +214,15 @@ class Block
                        $this->mTimestamp = wfTimestampNow();
                        $this->mExpiry = Block::getAutoblockExpiry( $this->mTimestamp );
 
-                       wfQuery( 'UPDATE ipblocks SET ' .
-                               "ipb_timestamp='" . $this->mTimestamp . "', " .
-                               "ipb_expiry='" . $this->mExpiry . "' " .
-                               "WHERE ipb_address='" . wfStrencode( $this->mAddress ) . "'", DB_WRITE, 'Block::updateTimestamp' );
+                       $dbw =& wfGetDB( DB_WRITE );
+                       $dbw->updateArray( 'ipblocks', 
+                               array( /* SET */ 
+                                       'ipb_timestamp' => $this->mTimestamp,
+                                       'ipb_expiry' => $this->mExpiry,
+                               ), array( /* WHERE */
+                                       'ipb_address' => $this->mAddress
+                               ), 'Block::updateTimestamp' 
+                       );
                        
                        $this->clearCache();
                }
index bab6cd8..c1ba5cc 100644 (file)
@@ -60,7 +60,8 @@ class Database {
 # Other functions
 #------------------------------------------------------------------------------
 
-       function Database()
+       function Database( $server = false, $user = false, $password = false, $dbName = false, 
+               $failFunction = false, $debug = false, $bufferResults = true, $ignoreErrors = false )
        {
                global $wgOut;
                # Can't get a reference if it hasn't been set yet
@@ -68,27 +69,27 @@ class Database {
                        $wgOut = NULL;
                }
                $this->mOut =& $wgOut;
-       
+
+               $this->mFailFunction = $failFunction;
+               $this->mIgnoreErrors = $ignoreErrors;
+               $this->mDebug = $debug;
+               $this->mBufferResults = $bufferResults;
+               if ( $server ) {
+                       $this->open( $server, $user, $password, $dbName );
+               }
        }
        
        /* static */ function newFromParams( $server, $user, $password, $dbName, 
                $failFunction = false, $debug = false, $bufferResults = true, $ignoreErrors = false )
        {
-               $db = new Database;
-               $db->mFailFunction = $failFunction;
-               $db->mIgnoreErrors = $ignoreErrors;
-               $db->mDebug = $debug;
-               $db->mBufferResults = $bufferResults;
-               $db->open( $server, $user, $password, $dbName );
-               return $db;
+               return new Database( $server, $user, $password, $dbName, $failFunction, $debug, 
+                 $bufferResults, $ignoreErrors );
        }
        
        # Usually aborts on failure
        # If the failFunction is set to a non-zero integer, returns success
        function open( $server, $user, $password, $dbName )
        {
-               global $wgEmergencyContact;
-               
                # Test for missing mysql.so
                # Otherwise we get a suppressed fatal error, which is very hard to track down
                if ( !function_exists( 'mysql_connect' ) ) {
@@ -155,7 +156,7 @@ class Database {
        
        # Usually aborts on failure
        # If errors are explicitly ignored, returns success
-       function query( $sql, $fname = "" )
+       function query( $sql, $fname = "", $tempIgnore = false )
        {
                global $wgProfiling, $wgCommandLineMode;
                
@@ -173,16 +174,26 @@ class Database {
                        $sqlx = wordwrap(strtr($sqlx,"\t\n","  "));
                        wfDebug( "SQL: $sqlx\n" );
                }
+               # Add a comment for easy SHOW PROCESSLIST interpretation
+               if ( $fname ) {
+                       $commentedSql = "/* $fname */ $sql";
+               } else {
+                       $commentedSql = $sql;
+               }
+               
                if( $this->mBufferResults ) {
-                       $ret = mysql_query( $sql, $this->mConn );
+                       $ret = mysql_query( $commentedSql, $this->mConn );
                } else {
-                       $ret = mysql_unbuffered_query( $sql, $this->mConn );
+                       $ret = mysql_unbuffered_query( $commentedSql, $this->mConn );
                }
        
                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( $this->mIgnoreErrors ) {
+                       if( $ignore || $tempIgnore ) {
                                wfDebug("SQL ERROR (ignored): " . $error . "\n");
                        } else {
                                $sql1line = str_replace( "\n", "\\n", $sql );
@@ -199,6 +210,7 @@ class Database {
                                        $this->mOut->databaseError( $fname, $sql, $error, $errno );                             
                                }
                        }
+                       $this->setIgnoreErrors( $ignore );
                }
                
                if ( $wgProfiling ) {
@@ -216,7 +228,7 @@ class Database {
                @$row = mysql_fetch_object( $res );
                # FIXME: HACK HACK HACK HACK debug
                if( mysql_errno() ) {
-                       wfDebugDieBacktrace( "SQL error: " . htmlspecialchars( mysql_error() ) );
+                       wfDebugDieBacktrace( "Error in fetchObject(): " . htmlspecialchars( mysql_error() ) );
                }
                return $row;
        }
@@ -224,7 +236,7 @@ class Database {
        function fetchRow( $res ) {
                @$row = mysql_fetch_array( $res );
                if (mysql_errno() ) {
-                       wfDebugDieBacktrace( "SQL error: " . htmlspecialchars( mysql_error() ) );
+                       wfDebugDieBacktrace( "Error in fetchRow(): " . htmlspecialchars( mysql_error() ) );
                }
                return $row;
        }       
@@ -232,7 +244,7 @@ class Database {
        function numRows( $res ) {
                @$n = mysql_num_rows( $res ); 
                if( mysql_errno() ) {
-                       wfDebugDieBacktrace( "SQL error: " . htmlspecialchars( mysql_error() ) );
+                       wfDebugDieBacktrace( "Error in numRows(): " . htmlspecialchars( mysql_error() ) );
                }
                return $n;
        }
@@ -249,6 +261,7 @@ class Database {
        # If errors are explicitly ignored, returns success
        function set( $table, $var, $value, $cond, $fname = "Database::set" )
        {
+               $table = $this->tableName( $table );
                $sql = "UPDATE $table SET $var = '" .
                  wfStrencode( $value ) . "' WHERE ($cond)";
                return !!$this->query( $sql, DB_WRITE, $fname );
@@ -257,41 +270,89 @@ class Database {
        # 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 get( $table, $var, $cond, $fname = "Database::get" )
+       function getField( $table, $var, $cond, $fname = "Database::get" )
        {
-               $sql = "SELECT $var FROM $table WHERE ($cond)";
-               $result = $this->query( $sql, DB_READ, $fname );
-       
-               $ret = "";
-               if ( mysql_num_rows( $result ) > 0 ) {
-                       $s = mysql_fetch_object( $result );
-                       $ret = $s->$var;
-                       mysql_free_result( $result );
+               $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 = '';
+               }
+               $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 );
                }
                return $ret;
        }
        
-       # More complex SELECT wrapper, single row only
-       # Aborts or returns FALSE on error
-       # 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" ) )
-       #   would return an object where $obj->cur_id is the ID of the Astronomy article
-       function getArray( $table, $vars, $conds, $fname = "Database::getArray" )
+       # SELECT wrapper
+       function select( $table, $vars, $conds, $fname = "Database::select", $options = array() )
        {
                $vars = implode( ",", $vars );
+               $table = $this->tableName( $table );
+               if ( !is_array( $options ) ) {
+                       $options = array( $options );
+               }
+
+               $tailOpts = '';
+
+               if ( isset( $options['ORDER BY'] ) ) {
+                       $tailOpts .= " ORDER BY {$options['ORDER BY']}";
+               } 
+               if ( isset( $options['LIMIT'] ) ) {
+                       $tailOpts .= " LIMIT {$options['LIMIT']}";
+               }
+
+               if ( is_numeric( array_search( 'FOR UPDATE', $options ) ) ) {
+                       $tailOpts .= ' FOR UPDATE';
+               }
+               
+               if ( is_numeric( array_search( 'LOCK IN SHARE MODE', $options ) ) ) {
+                       $tailOpts .= ' LOCK IN SHARE MODE';
+               }
+
+               if ( isset( $options['USE INDEX'] ) ) {
+                       $useIndex = $this->useIndexClause( $options['USE INDEX'] );
+               } else {
+                       $useIndex = '';
+               }
+
                if ( $conds !== false ) {
-                       $where = Database::makeList( $conds, LIST_AND );
-                       $sql = "SELECT $vars FROM $table WHERE $where LIMIT 1";
+                       $where = $this->makeList( $conds, LIST_AND );
+                       $sql = "SELECT $vars FROM $table $useIndex WHERE $where $tailOpts";
                } else {
-                       $sql = "SELECT $vars FROM $table LIMIT 1";
+                       $sql = "SELECT $vars FROM $table $useIndex $tailOpts";
                }
-               $res = $this->query( $sql, $fname );
+               return $this->query( $sql, $fname );
+       }
+       
+       # Single row SELECT wrapper
+       # Aborts or returns FALSE on error
+       #
+       # $vars: the selected variables
+       # $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" ) )
+       #   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() ) {
+               $options['LIMIT'] = 1;
+               $res = $this->select( $table, $vars, $conds, $fname, $options );
                if ( $res === false || !$this->numRows( $res ) ) {
                        return false;
                }
                $obj = $this->fetchObject( $res );
                $this->freeResult( $res );
                return $obj;
+               
        }
        
        # Removes most variables from an SQL query and replaces them with X or N for numbers.
@@ -322,6 +383,7 @@ class Database {
        # If errors are explicitly ignored, returns NULL on failure
        function fieldExists( $table, $field, $fname = "Database::fieldExists" )
        {
+               $table = $this->tableName( $table );
                $res = $this->query( "DESCRIBE $table", DB_READ, $fname );
                if ( !$res ) {
                        return NULL;
@@ -343,28 +405,35 @@ class Database {
        # If errors are explicitly ignored, returns NULL on failure
        function indexExists( $table, $index, $fname = "Database::indexExists" ) 
        {
+               $info = $this->indexInfo( $table, $index, $fname );
+               if ( is_null( $info ) ) {
+                       return NULL;
+               } else {
+                       return $info !== false;
+               }
+       }
+       
+       function indexInfo( $table, $index, $fname = "Database::indexInfo" ) {
                # SHOW INDEX works in MySQL 3.23.58, but SHOW INDEXES does not.
                # SHOW INDEX should work for 3.x and up:
                # http://dev.mysql.com/doc/mysql/en/SHOW_INDEX.html
+               $table = $this->tableName( $table );
                $sql = "SHOW INDEX FROM $table";
-               $res = $this->query( $sql, DB_READ, $fname );
+               $res = $this->query( $sql, $fname );
                if ( !$res ) {
                        return NULL;
                }
                
-               $found = false;
-               
                while ( $row = $this->fetchObject( $res ) ) {
                        if ( $row->Key_name == $index ) {
-                               $found = true;
-                               break;
+                               return $row;
                        }
                }
-               return $found;
+               return false;
        }
-       
        function tableExists( $table )
        {
+               $table = $this->tableName( $table );
                $old = $this->mIgnoreErrors;
                $this->mIgnoreErrors = true;
                $res = $this->query( "SELECT 1 FROM $table LIMIT 1" );
@@ -379,6 +448,7 @@ class Database {
 
        function fieldInfo( $table, $field )
        {
+               $table = $this->tableName( $table );
                $res = $this->query( "SELECT * FROM $table LIMIT 1" );
                $n = mysql_num_fields( $res );
                for( $i = 0; $i < $n; $i++ ) {
@@ -391,39 +461,61 @@ class Database {
        }
 
        # INSERT wrapper, inserts an array into a table
-       # Keys are field names, values are values
+       #
+       # $a may be a single associative array, or an array of these with numeric keys, for 
+       # multi-row insert.
+       #
        # Usually aborts on failure
        # If errors are explicitly ignored, returns success
-       function insertArray( $table, $a, $fname = "Database::insertArray" )
+       function insertArray( $table, $a, $fname = "Database::insertArray", $options = array() )
        {
-               $sql1 = "INSERT INTO $table (";
-               $sql2 = "VALUES (" . Database::makeList( $a );
-               $first = true;
-               foreach ( $a as $field => $value ) {
-                       if ( !$first ) {
-                               $sql1 .= ",";
+               $table = $this->tableName( $table );
+               if ( isset( $a[0] ) && is_array( $a[0] ) ) {
+                       $multi = true;
+                       $keys = array_keys( $a[0] );
+               } else {
+                       $multi = false;
+                       $keys = array_keys( $a );
+               }
+               
+               $sql = 'INSERT ' . implode( ' ', $options ) . 
+                       " INTO $table (" . implode( ',', $keys ) . ') VALUES ';
+
+               if ( $multi ) {
+                       $first = true;
+                       foreach ( $a as $row ) {
+                               if ( $first ) {
+                                       $first = false;
+                               } else {
+                                       $sql .= ",";
+                               }
+                               $sql .= '(' . $this->makeList( $row ) . ')';
                        }
-                       $first = false;
-                       $sql1 .= $field;
+               } else {
+                       $sql .= '(' . $this->makeList( $a ) . ')';
                }
-               $sql = "$sql1) $sql2)";
                return !!$this->query( $sql, $fname );
        }
        
-       # A cross between insertArray and getArray, takes a condition array and a SET array
+       # UPDATE wrapper, takes a condition array and a SET array
        function updateArray( $table, $values, $conds, $fname = "Database::updateArray" )
        {
+               $table = $this->tableName( $table );
                $sql = "UPDATE $table SET " . $this->makeList( $values, LIST_SET );
                $sql .= " WHERE " . $this->makeList( $conds, LIST_AND );
                $this->query( $sql, $fname );
        }
        
        # Makes a wfStrencoded list from an array
-       # $mode: LIST_COMMA - comma separated, no field names
-       #        LIST_AND   - ANDed WHERE clause (without the WHERE)
-       #        LIST_SET   - comma separated with field names, like a SET clause
-       /* static */ function makeList( $a, $mode = LIST_COMMA )
+       # $mode: LIST_COMMA         - comma separated, no field names
+       #        LIST_AND           - ANDed WHERE clause (without the WHERE)
+       #        LIST_SET           - comma separated with field names, like a SET clause
+       function makeList( $a, $mode = LIST_COMMA )
        {
+               if ( !is_array( $a ) ) {
+                       wfDebugDieBacktrace( 'Database::makeList called with incorrect parameters' );
+               }
+
                $first = true;
                $list = "";
                foreach ( $a as $field => $value ) {
@@ -436,13 +528,13 @@ class Database {
                        } else {
                                $first = false;
                        }
-                       if ( $mode == LIST_AND || $mode == LIST_SET ) {
-                               $list .= "$field=";
-                       }
-                       if ( !is_numeric( $value ) ) {
-                               $list .= "'" . wfStrencode( $value ) . "'";
+                       if ( $mode == LIST_AND && is_numeric( $field ) ) {
+                               $list .= "($value)";
                        } else {
-                               $list .= $value;
+                               if ( $mode == LIST_AND || $mode == LIST_SET ) {
+                                       $list .= "$field=";
+                               }
+                               $list .= $this->addQuotes( $value );
                        }
                }
                return $list;
@@ -465,8 +557,151 @@ class Database {
        function stopTimer()
        {
        }
+
+       function tableName( $name ) {
+               return $name;
+       }
+
+       function strencode( $s ) {
+               return addslashes( $s );
+       }
+
+       # If it's a string, adds quotes and backslashes
+       # Otherwise returns as-is
+       function addQuotes( $s ) {
+               if ( !is_numeric( $s ) ) {
+                       $s = "'" . $this->strencode( $s ) . "'";
+               } else if ( is_null( $s ) ) {
+                       $s = 'NULL';
+               }
+               return $s;
+       }
+               
+       # Returns an appropriately quoted sequence value for inserting a new row.
+       # MySQL has autoincrement fields, so this is just NULL. But the PostgreSQL
+       # subclass will return an integer, and save the value for insertId()
+       function nextSequenceValue( $seqName ) {
+               return NULL;
+       }
+
+       # USE INDEX clause
+       # PostgreSQL doesn't have them and returns ""
+       function useIndexClause( $index ) {
+               return "USE INDEX ($index)";
+       }
+
+       # REPLACE query wrapper
+       # PostgreSQL simulates this with a DELETE followed by INSERT
+       # $row is the row to insert, an associative array
+       # $uniqueIndexes is an array of indexes. Each element may be either a 
+       # field name or an array of field names
+       #
+       # It may be more efficient to leave off unique indexes which are unlikely to collide. 
+       # However if you do this, you run the risk of encountering errors which wouldn't have 
+       # occurred in MySQL
+       function replace( $table, $uniqueIndexes, $rows, $fname = "Database::replace" ) {
+               $table = $this->tableName( $table );
+
+               # Single row case
+               if ( !is_array( reset( $rows ) ) ) {
+                       $rows = array( $rows );
+               }
+
+               $sql = "REPLACE INTO $table (" . implode( ',', array_flip( $rows[0] ) ) .") VALUES ";
+               $first = true;
+               foreach ( $rows as $row ) {
+                       if ( $first ) {
+                               $first = false;
+                       } else {
+                               $sql .= ",";
+                       }
+                       $sql .= "(" . $this->makeList( $row ) . ")";
+               }
+               return $this->query( $sql, $fname );
+       }
+
+       # DELETE where the condition is a join
+       # MySQL does this with a multi-table DELETE syntax, PostgreSQL does it with sub-selects
+       #
+       # $delTable is the table to delete from
+       # $joinTable is the other table
+       # $delVar is the variable to join on, in the first table
+       # $joinVar is the variable to join on, in the second table
+       # $conds is a condition array of field names mapped to variables, ANDed together in the WHERE clause
+       #
+       # For safety, an empty $conds will not delete everything. If you want to delete all rows where the 
+       # join condition matches, set $conds='*'
+       #
+       # DO NOT put the join condition in $conds
+       function deleteJoin( $delTable, $joinTable, $delVar, $joinVar, $conds, $fname = "Database::deleteJoin" ) {
+               if ( !$conds ) {
+                       wfDebugDieBacktrace( 'Database::deleteJoin() called with empty $conds' );
+               }
+
+               $delTable = $this->tableName( $delTable );
+               $joinTable = $this->tableName( $joinTable );
+               $sql = "DELETE $delTable FROM $delTable, $joinTable WHERE $delVar=$joinVar ";
+               if ( $conds != '*' ) {
+                       $sql .= " AND " . $this->makeList( $conds, LIST_AND );
+               }
+               
+               return $this->query( $sql, $fname );
+       }
+
+       # Returns the size of a text field, or -1 for "unlimited"
+       function textFieldSize( $table, $field ) {
+               $table = $this->tableName( $table );
+               $sql = "SHOW COLUMNS FROM $table LIKE \"$field\";";
+               $res = $this->query( $sql, "Database::textFieldSize" );
+               $row = wfFetchObject( $res );
+               $this->freeResult( $res );
+
+               if ( preg_match( "/\((.*)\)/", $row->Type, $m ) ) {
+                       $size = $m[1];
+               } else {
+                       $size = -1;
+               }
+               return $size;
+       }
+
+       function lowPriorityOption() {
+               return 'LOW_PRIORITY';
+       }
+
+       # Use $conds == "*" to delete all rows
+       function delete( $table, $conds, $fname = "Database::delete" ) {
+               if ( !$conds ) {
+                       wfDebugDieBacktrace( "Database::delete() called with no conditions" );
+               }
+               $table = $this->tableName( $table );
+               $sql = "DELETE FROM $table ";
+               if ( $conds != '*' ) {
+                       $sql .= "WHERE " . $this->makeList( $conds, LIST_AND );
+               }
+               return $this->query( $sql, $fname );
+       }
+
+       # INSERT SELECT wrapper
+       # $varMap must be an associative array of the form array( 'dest1' => 'source1', ...)
+       # Source items may be literals rather than field names, but strings should be quoted with Database::addQuotes()
+       # $conds may be "*" to copy the whole table
+       function insertSelect( $destTable, $srcTable, $varMap, $conds, $fname = 'Database::insertSelect' ) {
+               $destTable = $this->tableName( $destTable );
+               $srcTable = $this->tableName( $srcTable );
+               $sql = "INSERT INTO $destTable (" . implode( ',', array_keys( $varMap ) ) . ")" .
+                       " SELECT " . implode( ',', $varMap ) . 
+                       " FROM $srcTable";
+               if ( $conds != '*' ) {
+                       $sql .= " WHERE " . $this->makeList( $conds, LIST_AND );
+               }
+               return $this->query( $sql, $fname );
+       }
 } 
 
+class DatabaseMysql extends Database {
+       # Inherit all
+}
+
 #------------------------------------------------------------------------------
 # Global functions
 #------------------------------------------------------------------------------
@@ -520,11 +755,6 @@ function wfEmergencyAbort( &$conn, $error ) {
        wfAbruptExit();
 }
 
-function wfStrencode( $s )
-{
-       return addslashes( $s );
-}
-
 function wfLimitResult( $limit, $offset ) {
        return " LIMIT ".(is_numeric($offset)?"{$offset},":"")."{$limit} ";
 }
index 3fde31b..c5f1b6d 100644 (file)
 
 # Note: $wgDatabase has ceased to exist. Destroy all references.
 
-$wgIsMySQL=false;
-$wgIsPg=false;
-
-if ($wgDBtype=="mysql") {
-    require_once( "Database.php" );
-    $wgIsMySQL=true;
-} elseif ($wgDBtype=="pgsql") {
-    require_once( "DatabasePostgreSQL.php" );
-    $wgIsPg=true;
-} 
-
-
 # Usually aborts on failure
 # If errors are explicitly ignored, returns success
 function wfQuery( $sql, $db, $fname = "" )
@@ -220,7 +208,7 @@ function wfGetSQL( $table, $var, $cond="", $dbi = DB_LAST )
 {
        $db =& wfGetDB( $dbi );
        if ( $db !== false ) {
-               return $db->get( $table, $var, $cond );
+               return $db->getField( $table, $var, $cond );
        } else {        
                return false;
        }
@@ -277,4 +265,40 @@ function wfUpdateArray( $table, $values, $conds, $fname = "wfUpdateArray", $dbi
        }
 }
 
+function wfTableName( $name, $dbi = DB_LAST ) {
+       $db =& wfGetDB( $dbi );
+       if ( $db !== false ) {
+               return $db->tableName( $name );
+       } else {
+               return false;
+       }
+}
+
+function wfStrencode( $s, $dbi = DB_LAST )
+{
+       $db =& wfGetDB( $dbi );
+       if ( $db !== false ) {
+               return $db->strencode( $s );
+       } else {
+               return false;
+       }
+}
+
+function wfNextSequenceValue( $seqName, $dbi = DB_WRITE ) {
+       $db =& wfGetDB( $dbi );
+       if ( $db !== false ) {
+               return $db->nextSequenceValue( $seqName );
+       } else {
+               return false;
+       }
+}
+
+function wfUseIndexClause( $index, $dbi = DB_READ ) {
+       $db =& wfGetDB( $dbi );
+       if ( $db !== false ) {
+               return $db->useIndexClause( $index );
+       } else {
+               return false;
+       }
+}
 ?>
index 2b3ba25..1b22a8e 100644 (file)
 #
 # Hashar
 
-require_once( "FulltextStoplist.php" );
-require_once( "CacheManager.php" );
+class DatabasePgsql extends Database {
+       var $mInsertId = NULL;
 
-define( "DB_READ", -1 );
-define( "DB_WRITE", -2 );
-define( "DB_LAST", -3 );
-
-define( "LIST_COMMA", 0 );
-define( "LIST_AND", 1 );
-define( "LIST_SET", 2 );
-
-class Database {
-
-#------------------------------------------------------------------------------
-# Variables
-#------------------------------------------------------------------------------        
-       /* private */ var $mLastQuery = "";
-       /* private */ var $mBufferResults = true;
-       /* private */ var $mIgnoreErrors = false;
-       
-       /* private */ var $mServer, $mUser, $mPassword, $mConn, $mDBname;
-       /* private */ var $mOut, $mDebug, $mOpened = false;
-       
-       /* private */ var $mFailFunction; 
-       /* private */ var $mLastResult;
-
-#------------------------------------------------------------------------------
-# Accessors
-#------------------------------------------------------------------------------
-       # Set functions
-       # These set a variable and return the previous state
-       
-       # Fail function, takes a Database as a parameter
-       # Set to false for default, 1 for ignore errors
-       function setFailFunction( $function ) { return wfSetVar( $this->mFailFunction, $function ); }
-       
-       # Output page, used for reporting errors
-       # FALSE means discard output
-       function &setOutputPage( &$out ) { $this->mOut =& $out; }
-       
-       # Boolean, controls output of large amounts of debug information 
-       function setDebug( $debug ) { return wfSetVar( $this->mDebug, $debug ); }
-       
-       # Turns buffering of SQL result sets on (true) or off (false). Default is
-       # "on" and it should not be changed without good reasons. 
-       function setBufferResults( $buffer ) { return wfSetVar( $this->mBufferResults, $buffer ); }
-
-       # Turns on (false) or off (true) the automatic generation and sending
-       # of a "we're sorry, but there has been a database error" page on
-       # database errors. Default is on (false). When turned off, the
-       # code should use wfLastErrno() and wfLastError() to handle the
-       # situation as appropriate.
-       function setIgnoreErrors( $ignoreErrors ) { return wfSetVar( $this->mIgnoreErrors, $ignoreErrors ); }
-       
-       # Get functions
-       
-       function lastQuery() { return $this->mLastQuery; }
-       function isOpen() { return $this->mOpened; }
-
-#------------------------------------------------------------------------------
-# Other functions
-#------------------------------------------------------------------------------
-
-       function Database()
+       function DatabasePgsql($server = false, $user = false, $password = false, $dbName = false, 
+               $failFunction = false, $debug = false, $bufferResults = true, $ignoreErrors = false)
        {
-               global $wgOut;
-               # Can't get a reference if it hasn't been set yet
-               if ( !isset( $wgOut ) ) {
-                       $wgOut = NULL;
-               }
-               $this->mOut =& $wgOut;
-       
+               Database::Database( $server, $user, $password, $dbName, $failFunction, $debug, 
+                 $bufferResults, $ignoreErrors );
        }
-       
+
        /* static */ function newFromParams( $server, $user, $password, $dbName, 
                $failFunction = false, $debug = false, $bufferResults = true, $ignoreErrors = false )
        {
-               $db = new Database;
-               $db->mFailFunction = $failFunction;
-               $db->mIgnoreErrors = $ignoreErrors;
-               $db->mDebug = $debug;
-               $db->mBufferResults = $bufferResults;
-               $db->open( $server, $user, $password, $dbName );
-               return $db;
+               return new DatabasePgsql( $server, $user, $password, $dbName, $failFunction, $debug, 
+                 $bufferResults, $ignoreErrors );
        }
-       
+
        # Usually aborts on failure
        # If the failFunction is set to a non-zero integer, returns success
        function open( $server, $user, $password, $dbName )
        {
-               global $wgEmergencyContact;
-               
+               # Test for PostgreSQL support, to avoid suppressed fatal error
+               if ( !function_exists( 'pg_connect' ) ) {
+                       die( "PostgreSQL functions missing, have you compiled PHP with the --with-pgsql option?\n" );
+               }
+
                $this->close();
                $this->mServer = $server;
                $this->mUser = $user;
@@ -114,7 +48,6 @@ class Database {
                
                $success = false;
                
-               
                if ( "" != $dbName ) {
                        # start a database connection
                        @$this->mConn = pg_connect("host=$server dbname=$dbName user=$user password=$password");
@@ -141,20 +74,9 @@ class Database {
                }
        }
        
-       /* private */ function reportConnectionError( $msg = "")
-       {
-               if ( $this->mFailFunction ) {
-                       if ( !is_int( $this->mFailFunction ) ) {
-                               $this->$mFailFunction( $this );
-                       }
-               } else {
-                       wfEmergencyAbort( $this );
-               }
-       }
-       
        # Usually aborts on failure
        # If errors are explicitly ignored, returns success
-       function query( $sql, $fname = "" )
+       function query( $sql, $fname = "", $tempIgnore = false )
        {
                global $wgProfiling;
                
@@ -176,10 +98,12 @@ class Database {
                $ret = pg_query( $this->mConn , $sql);
                $this->mLastResult = $ret;
                if ( false == $ret ) {
+                       // Ignore errors during error handling to prevent infinite recursion
+                       $ignore = $this->setIgnoreErrors( true );
                        $error = pg_last_error( $this->mConn );
                        // TODO FIXME : no error number function in postgre
                        // $errno = mysql_errno( $this->mConn );
-                       if( $this->mIgnoreErrors ) {
+                       if( $ignore || $tempIgnore ) {
                                wfDebug("SQL ERROR (ignored): " . $error . "\n");
                        } else {
                                wfDebug("SQL ERROR: " . $error . "\n");
@@ -188,6 +112,7 @@ class Database {
                                        $this->mOut->databaseError( $fname, $sql, $error, 0 );                          
                                }
                        }
+                       $this->setIgnoreErrors( $ignore );
                }
                
                if ( $wgProfiling ) {
@@ -196,6 +121,10 @@ class Database {
                return $ret;
        }
        
+       function queryIgnore( $sql, $fname = "" ) {
+               return $this->query( $sql, $fname, true );
+       }
+       
        function freeResult( $res ) {
                if ( !@pg_free_result( $res ) ) {
                        wfDebugDieBacktrace( "Unable to free PostgreSQL result\n" );
@@ -231,150 +160,40 @@ class Database {
        }
        function numFields( $res ) { return pg_num_fields( $res ); }
        function fieldName( $res, $n ) { return pg_field_name( $res, $n ); }
-       // TODO FIXME: need to implement something here
+       
+       # This must be called after nextSequenceVal
        function insertId() { 
-               //return mysql_insert_id( $this->mConn );
-               wfDebugDieBacktrace( "Database::insertId() error : not implemented for postgre, use sequences" );
+               return $this->mInsertId;
        }
+
        function dataSeek( $res, $row ) { return pg_result_seek( $res, $row ); }
-       function lastErrno() { return $this->lastError(); }
        function lastError() { return pg_last_error(); }
        function affectedRows() { 
                return pg_affected_rows( $this->mLastResult ); 
        }
        
-       # Simple UPDATE wrapper
-       # Usually aborts on failure
-       # If errors are explicitly ignored, returns success
-       function set( $table, $var, $value, $cond, $fname = "Database::set" )
-       {
-               $sql = "UPDATE \"$table\" SET \"$var\" = '" .
-                 wfStrencode( $value ) . "' WHERE ($cond)";
-               return !!$this->query( $sql, DB_WRITE, $fname );
-       }
-       
-       # 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 get( $table, $var, $cond, $fname = "Database::get" )
-       {
-               $from=$table?" FROM \"$table\" ":"";
-               $where=$cond?" WHERE ($cond)":"";
-
-               $sql = "SELECT $var $from $where";
-
-               $result = $this->query( $sql, DB_READ, $fname );
-       
-               $ret = "";
-               if ( pg_num_rows( $result ) > 0 ) {
-                       $s = pg_fetch_array( $result );
-                       $ret = $s[0];
-                       pg_free_result( $result );
-               }
-               return $ret;
-       }
-       
-       # More complex SELECT wrapper, single row only
-       # Aborts or returns FALSE on error
-       # 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" ) )
-       #   would return an object where $obj->cur_id is the ID of the Astronomy article
-       function getArray( $table, $vars, $conds, $fname = "Database::getArray" )
-       {
-               $vars = implode( ",", $vars );
-               $where = Database::makeList( $conds, LIST_AND );
-               $sql = "SELECT \"$vars\" FROM \"$table\" WHERE $where LIMIT 1";
-               $res = $this->query( $sql, $fname );
-               if ( $res === false || !$this->numRows( $res ) ) {
-                       return false;
-               }
-               $obj = $this->fetchObject( $res );
-               $this->freeResult( $res );
-               return $obj;
-       }
-       
-       # Removes most variables from an SQL query and replaces them with X or N for numbers.
-       # It's only slightly flawed. Don't use for anything important.
-       /* static */ function generalizeSQL( $sql )
-       {       
-               # This does the same as the regexp below would do, but in such a way
-               # as to avoid crashing php on some large strings.
-               # $sql = preg_replace ( "/'([^\\\\']|\\\\.)*'|\"([^\\\\\"]|\\\\.)*\"/", "'X'", $sql);
-       
-               $sql = str_replace ( "\\\\", "", $sql);
-               $sql = str_replace ( "\\'", "", $sql);
-               $sql = str_replace ( "\\\"", "", $sql);
-               $sql = preg_replace ("/'.*'/s", "'X'", $sql);
-               $sql = preg_replace ('/".*"/s', "'X'", $sql);
-       
-               # All newlines, tabs, etc replaced by single space
-               $sql = preg_replace ( "/\s+/", " ", $sql);
-       
-               # All numbers => N      
-               $sql = preg_replace ('/-?[0-9]+/s', "N", $sql);
-       
-               return $sql;
-       }
-       
-       # Determines whether a field exists in a table
-       # Usually aborts on failure
-       # If errors are explicitly ignored, returns NULL on failure
-       function fieldExists( $table, $field, $fname = "Database::fieldExists" )
-       {
-               $res = $this->query( "DESCRIBE '$table'", DB_READ, $fname );
-               if ( !$res ) {
-                       return NULL;
-               }
-               
-               $found = false;
-               
-               while ( $row = $this->fetchObject( $res ) ) {
-                       if ( $row->Field == $field ) {
-                               $found = true;
-                               break;
-                       }
-               }
-               return $found;
-       }
-       
-       # Determines whether an index exists
-       # Usually aborts on failure
+       # Returns information about an index
        # If errors are explicitly ignored, returns NULL on failure
-       function indexExists( $table, $index, $fname = "Database::indexExists" ) 
+       function indexInfo( $table, $index, $fname = "Database::indexExists" ) 
        {
                $sql = "SELECT indexname FROM pg_indexes WHERE tablename='$table'";
-               $res = $this->query( $sql, DB_READ, $fname );
+               $res = $this->query( $sql, $fname );
                if ( !$res ) {
                        return NULL;
                }
                
-               $found = false;
-               
                while ( $row = $this->fetchObject( $res ) ) {
                        if ( $row->Key_name == $index ) {
-                               $found = true;
-                               break;
+                               return $row;
                        }
                }
-               return $found;
-       }
-       
-       function tableExists( $table )
-       {
-               $old = $this->mIgnoreErrors;
-               $this->mIgnoreErrors = true;
-               $res = $this->query( "SELECT 1 FROM '$table' LIMIT 1" );
-               $this->mIgnoreErrors = $old;
-               if( $res ) {
-                       $this->freeResult( $res );
-                       return true;
-               } else {
-                       return false;
-               }
+               return false;
        }
 
        function fieldInfo( $table, $field )
        {
+               wfDebugDieBacktrace( "Database::fieldInfo() error : mysql_fetch_field() not implemented for postgre" );
+               /*
                $res = $this->query( "SELECT * FROM '$table' LIMIT 1" );
                $n = pg_num_fields( $res );
                for( $i = 0; $i < $n; $i++ ) {
@@ -385,134 +204,154 @@ class Database {
                                return $meta;
                        }
                }
-               return false;
+               return false;*/
        }
 
-       # INSERT wrapper, inserts an array into a table
-       # Keys are field names, values are values
-       # Usually aborts on failure
-       # If errors are explicitly ignored, returns success
-       function insertArray( $table, $a, $fname = "Database::insertArray" )
-       {
-               $sql1 = "INSERT INTO \"$table\" (";
-               $sql2 = "VALUES (" . Database::makeList( $a );
-               $first = true;
-               foreach ( $a as $field => $value ) {
-                       if ( !$first ) {
-                               $sql1 .= ",";
-                       }
-                       $first = false;
-                       $sql1 .= $field;
+       function insertArray( $table, $a, $fname = "Database::insertArray", $options = array() ) {
+               # PostgreSQL doesn't support options
+               # We have a go at faking some of them
+               if ( in_array( 'IGNORE', $options ) ) {
+                       $ignore = true;
+                       $oldIgnore = $this->setIgnoreErrors( true );
                }
-               $sql = "$sql1) $sql2)";
-               return !!$this->query( $sql, $fname );
-       }
-       
-       # A cross between insertArray and getArray, takes a condition array and a SET array
-       function updateArray( $table, $values, $conds, $fname = "Database::updateArray" )
-       {
-               $sql = "UPDATE '$table' SET " . $this->makeList( $values, LIST_SET );
-               $sql .= " WHERE " . $this->makeList( $conds, LIST_AND );
-               $this->query( $sql, $fname );
-       }
-       
-       # Makes a wfStrencoded list from an array
-       # $mode: LIST_COMMA - comma separated, no field names
-       #        LIST_AND   - ANDed WHERE clause (without the WHERE)
-       #        LIST_SET   - comma separated with field names, like a SET clause
-       /* static */ function makeList( $a, $mode = LIST_COMMA )
-       {
-               $first = true;
-               $list = "";
-               foreach ( $a as $field => $value ) {
-                       if ( !$first ) {
-                               if ( $mode == LIST_AND ) {
-                                       $list .= " AND ";
-                               } else {
-                                       $list .= ",";
-                               }
-                       } else {
-                               $first = false;
-                       }
-                       if ( $mode == LIST_AND || $mode == LIST_SET ) {
-                               $list .= "$field=";
-                       }
-                       if ( !is_numeric( $value ) ) {
-                               $list .= "'" . wfStrencode( $value ) . "'";
-                       } else {
-                               $list .= $value;
-                       }
+               $retVal = parent::insertArray( $table, $a, $fname, array() );
+               if ( $ignore ) {
+                       $this->setIgnoreErrors( $oldIgnore );
                }
-               return $list;
+               return $retVal;
        }
        
        function startTimer( $timeout )
        {
                global $IP;
                wfDebugDieBacktrace( "Database::startTimer() error : mysql_thread_id() not implemented for postgre" );
-               $tid = mysql_thread_id( $this->mConn );
-               exec( "php $IP/killthread.php $timeout $tid &>/dev/null &" );
+               /*$tid = mysql_thread_id( $this->mConn );
+               exec( "php $IP/killthread.php $timeout $tid &>/dev/null &" );*/
        }
 
-       function stopTimer()
-       {
+       function tableName( $name ) {
+               # First run any transformations from the parent object
+               $name = parent::tableName( $name );
+
+               # Now quote PG reserved keywords
+               switch( $name ) {
+                       case 'user':
+                               return '"user"';
+                       case 'old':
+                               return '"old"';
+                       default:
+                               return $name;
+               }
        }
 
-}
+       function strencode( $s ) {
+               return pg_escape_string( $s );
+       }
 
-#------------------------------------------------------------------------------
-# Global functions
-#------------------------------------------------------------------------------
+       # Return the next in a sequence, save the value for retrieval via insertId()
+       function nextSequenceValue( $seqName ) {
+               $value = $this->getField(""," nextval('" . $seqName . "')");
+               $this->mInsertId = $value;
+               return $value;
+       }
 
-/* Standard fail function, called by default when a connection cannot be established
-   Displays the file cache if possible */
-function wfEmergencyAbort( &$conn ) {
-       global $wgTitle, $wgUseFileCache, $title, $wgInputEncoding, $wgSiteNotice, $wgOutputEncoding;
-       
-       header( "Content-type: text/html; charset=$wgOutputEncoding" );
-       $msg = $wgSiteNotice;
-       if($msg == "") $msg = wfMsgNoDB( "noconnect" );
-       $text = $msg;
+       # USE INDEX clause
+       # PostgreSQL doesn't have them and returns ""
+       function useIndexClause( $index ) {
+               return '';
+       }
 
-       if($wgUseFileCache) {
-               if($wgTitle) {
-                       $t =& $wgTitle;
-               } else {
-                       if($title) {
-                               $t = Title::newFromURL( $title );
-                       } elseif (@$_REQUEST['search']) {
-                               $search = $_REQUEST['search'];
-                               echo wfMsgNoDB( "searchdisabled" );
-                               echo wfMsgNoDB( "googlesearch", htmlspecialchars( $search ), $wgInputEncoding );
-                               wfAbruptExit();
+       # REPLACE query wrapper
+       # PostgreSQL simulates this with a DELETE followed by INSERT
+       # $row is the row to insert, an associative array
+       # $uniqueIndexes is an array of indexes. Each element may be either a 
+       # field name or an array of field names
+       #
+       # It may be more efficient to leave off unique indexes which are unlikely to collide. 
+       # However if you do this, you run the risk of encountering errors which wouldn't have 
+       # occurred in MySQL
+       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 ";
+                                               }
+                                               $sql .= "$col = " $this->strencode
+                                               
+                               if ( $first ) {
+                                       $first = false;
+                               } else {
+                                       $sql .= "OR ";
+                               }
+                               $sql .= "$col IN (";
+                               $indexValues = array();
+                               foreach ( $rows as $row ) {
+                                       $indexValues[] = $row[$col];
+                               }
+                               $sql .= $this->makeList( $indexValues, LIST_COMMA ) . ") ";
+                       }
+                       $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 {
-                               $t = Title::newFromText( wfMsgNoDB( "mainpage" ) );
+                               $sql .= ",";
                        }
+                       $sql .= "(" . $this->makeList( $row, LIST_COMMA ) . ")";
+               }
+               $this->query( $sql, $fname );
+       }
+
+       # DELETE where the condition is a join
+       function deleteJoin( $delTable, $joinTable, $delVar, $joinVar, $conds, $fname = "Database::deleteJoin" ) {
+               if ( !$conds ) {
+                       wfDebugDieBacktrace( 'Database::deleteJoin() called with empty $conds' );
                }
 
-               $cache = new CacheManager( $t );
-               if( $cache->isFileCached() ) {
-                       $msg = "<p style='color: red'><b>$msg<br />\n" .
-                               wfMsgNoDB( "cachederror" ) . "</b></p>\n";
-                       
-                       $tag = "<div id='article'>";
-                       $text = str_replace(
-                               $tag,
-                               $tag . $msg,
-                               $cache->fetchPageText() );
+               $delTable = $this->tableName( $delTable );
+               $joinTable = $this->tableName( $joinTable );
+               $sql = "DELETE FROM $delTable WHERE $delVar IN (SELECT $joinVar FROM $joinTable ";
+               if ( $conds != '*' ) {
+                       $sql .= "WHERE " . $this->makeList( $conds, LIST_AND );
                }
+               $sql .= ")";
+
+               $this->query( $sql, $fname );
        }
-       
-       /* Don't cache error pages!  They cause no end of trouble... */
-       header( "Cache-control: none" );
-       header( "Pragma: nocache" );
-       echo $text;
-       wfAbruptExit();
-}
 
-function wfStrencode( $s )
-{
-       return pg_escape_string( $s );
+       # Returns the size of a text field, or -1 for "unlimited"
+       function textFieldSize( $table, $field ) {
+               $table = $this->tableName( $table );
+               $res = $this->query( "SELECT $field FROM $table LIMIT 1", "Database::textFieldLength" );
+               $size = pg_field_size( $res, 0 );
+               $this->freeResult( $res );
+               return $size;
+       }
+       
+       function lowPriorityOption() {
+               return '';
+       }
 }
 
 function wfLimitResult( $limit, $offset ) {
index 4471294..100a1e2 100644 (file)
@@ -61,8 +61,16 @@ $wgDBuser           = 'wikiuser';
 $wgDBtype           = "mysql"; # "mysql" for working code and "pgsql" for development/broken code
 
 # Database load balancer
-$wgDBservers           = false; # e.g. array(0 => "larousse", 1 => "pliny")
-$wgDBloads                     = false; # e.g. array(0 => 0.6, 1 => 0.4);
+# This is a two-dimensional array, an array of server info structures
+# Fields are: 
+#   host:      Host name
+#   dbname:    Default database name
+#   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
+# Leave at false to use the single-server variables above
+$wgDBservers           = false; 
 
 # Sysop SQL queries
 $wgAllowSysopQueries = false; # Dangerous if not configured properly.
index 2e3937e..30d369e 100644 (file)
@@ -118,32 +118,33 @@ cellpadding='0' cellspacing='4px' class='diff'><tr>
        #
        function loadText()
        {
-               global $wgTitle, $wgOut, $wgLang, $wgIsMySQL, $wgIsPg;
+               global $wgTitle, $wgOut, $wgLang;
                $fname = "DifferenceEngine::loadText";
                
-               $oldtable=$wgIsPg?'"old"':'old';
+               $dbr =& wfGetDB( DB_READ );
                if ( 0 == $this->mNewid || 0 == $this->mOldid ) {
                        $wgOut->setArticleFlag( true );
                        $this->mNewtitle = wfMsg( "currentrev" );
                        $id = $wgTitle->getArticleID();
                        
-                       $sql = "SELECT cur_text, cur_user_text, cur_comment FROM cur WHERE cur_id={$id}";
-                       $res = wfQuery( $sql, DB_READ, $fname );
-                       if ( 0 == wfNumRows( $res ) ) { return false; }
+                       $s = $dbr->getArray( 'cur', array( 'cur_text', 'cur_user_text', 'cur_comment' ), 
+                               array( 'cur_id' => $id ), $fname );
+                       if ( $s === false ) { 
+                               return false; 
+                       }
 
-                       $s = wfFetchObject( $res );
                        $this->mNewPage = &$wgTitle;
                        $this->mNewtext = $s->cur_text;
                        $this->mNewUser = $s->cur_user_text;
                        $this->mNewComment = $s->cur_comment;
                } else {
-                       $sql = "SELECT old_namespace,old_title,old_timestamp,old_text,old_flags,old_user_text,old_comment FROM $oldtable WHERE " .
-                         "old_id={$this->mNewid}";
+                       $s = $dbr->getArray( 'old', array( 'old_namespace','old_title','old_timestamp', 'old_text',
+                               'old_flags','old_user_text','old_comment' ), array( 'old_id' => $this->mNewid ), $fname );
 
-                       $res = wfQuery( $sql, DB_READ, $fname );
-                       if ( 0 == wfNumRows( $res ) ) { return false; }
+                       if ( $s === false ) { 
+                               return false; 
+                       }
 
-                       $s = wfFetchObject( $res );
                        $this->mNewtext = Article::getRevisionText( $s );
 
                        $t = $wgLang->timeanddate( $s->old_timestamp, true );
@@ -153,21 +154,23 @@ cellpadding='0' cellspacing='4px' class='diff'><tr>
                        $this->mNewComment = $s->old_comment;
                }
                if ( 0 == $this->mOldid ) {
-                       $use_index=$wgIsMySQL?"USE INDEX (name_title_timestamp)":"";
-                       $sql = "SELECT old_namespace,old_title,old_timestamp,old_text,old_flags,old_user_text,old_comment " .
-                         "FROM $oldtable $use_index WHERE " .
-                         "old_namespace=" . $this->mNewPage->getNamespace() . " AND " .
-                         "old_title='" . wfStrencode( $this->mNewPage->getDBkey() ) .
-                         "' ORDER BY inverse_timestamp LIMIT 1";
-                       $res = wfQuery( $sql, DB_READ, $fname );
+                       $s = $dbr->getArray( 'old', 
+                               array( 'old_namespace','old_title','old_timestamp','old_text', 'old_flags','old_user_text','old_comment' ), 
+                               array( /* WHERE */
+                                       'old_namespace' => $this->mNewPage->getNamespace(), 
+                                       'old_title' => $this->mNewPage->getDBkey() 
+                               ), $fname, array( 'ORDER BY' => 'inverse_timestamp', 'USE INDEX' => 'name_title_timestamp' )
+                       );
                } else {
-                       $sql = "SELECT old_namespace,old_title,old_timestamp,old_text,old_flags,old_user_text,old_comment FROM $oldtable WHERE " .
-                         "old_id={$this->mOldid}";
-                       $res = wfQuery( $sql, DB_READ, $fname );
+                       $s = $dbr->getArray( 'old', 
+                               array( 'old_namespace','old_title','old_timestamp','old_text','old_flags','old_user_text','old_comment'),
+                               array( 'old_id' => $this->mOldid ), 
+                               $fname
+                       );
+               }
+               if ( $s === false ) { 
+                       return false; 
                }
-               if ( 0 == wfNumRows( $res ) ) { return false; }
-
-               $s = wfFetchObject( $res );
                $this->mOldPage = Title::MakeTitle( $s->old_namespace, $s->old_title );
                $this->mOldtext = Article::getRevisionText( $s );
 
index 04ff9c1..cb2be1b 100644 (file)
@@ -541,19 +541,19 @@ htmlspecialchars( $wgLang->recodeForEdit( $this->textbox1 ) ) .
        }
 
        /* private */ function mergeChangesInto( &$text ){
-               global $wgIsPg;
+               $fname = 'EditPage::mergeChangesInto';
                $oldDate = $this->edittime;
-               $res = wfQuery("SELECT cur_text FROM cur WHERE cur_id=" .
-                       $this->mTitle->getArticleID() . " FOR UPDATE", DB_WRITE);
-               $obj = wfFetchObject($res);
+               $dbw =& wfGetDB( DB_WRITE );
+               $obj = $dbr->getArray( 'cur', array( 'cur_text' ), array( 'cur_id' => $this->mTitle->getArticleID() ), 
+                       $fname, 'FOR UPDATE' );
 
                $yourtext = $obj->cur_text;
                $ns = $this->mTitle->getNamespace();
-               $title = wfStrencode( $this->mTitle->getDBkey() );
-               $oldtable=$wgIsPg?'"old"':'old';
-               $res = wfQuery("SELECT old_text,old_flags FROM $oldtable WHERE old_namespace = $ns AND ".
-                 "old_title = '{$title}' AND old_timestamp = '{$oldDate}'", DB_WRITE);
-               $obj = wfFetchObject($res);
+               $title = $this->mTitle->getDBkey();
+               $obj = $dbw->getArray( 'old', 
+                       array( 'old_text','old_flags'), 
+                       array( 'old_namespace' => $ns, 'old_title' => $title, 'old_timestamp' => $oldDate ),
+                       $fname );
                $oldText = Article::getRevisionText( $obj );
                
                if(wfMerge($oldText, $text, $yourtext, $result)){
index a37e1dc..a72e849 100644 (file)
@@ -392,9 +392,9 @@ function wfDebugDieBacktrace( $msg = '' ) {
                        $f = explode( DIRECTORY_SEPARATOR, $call['file'] );
                        $file = $f[count($f)-1];
                        if ( $wgCommandLineMode ) {
-                               $msg .= "$file line {$call['line']}, in ";
+                               $msg .= "$file line {$call['line']} calls ";
                        } else {
-                               $msg .= '<li>' . $file . " line " . $call['line'] . ', in ';
+                               $msg .= '<li>' . $file . " line " . $call['line'] . ' calls ';
                        }
                        if( !empty( $call['class'] ) ) $msg .= $call['class'] . '::';
                        $msg .= $call['function'] . "()";
@@ -420,15 +420,18 @@ function wfNumberOfArticles()
 /* private */ function wfLoadSiteStats()
 {
        global $wgNumberOfArticles, $wgTotalViews, $wgTotalEdits;
-       if ( -1 != $wgNumberOfArticles ) return;
+       $fname = 'wfLoadSiteStats';
 
-       $sql = 'SELECT ss_total_views, ss_total_edits, ss_good_articles ' .
-         'FROM site_stats WHERE ss_row_id=1';
-       $res = wfQuery( $sql, DB_READ, 'wfLoadSiteStats' );
+       if ( -1 != $wgNumberOfArticles ) return;
+       $dbr =& wfGetDB( DB_READ );
+       $s = $dbr->getArray( 'site_stats', 
+               array( 'ss_total_views', 'ss_total_edits', 'ss_good_articles' ),
+               array( 'ss_row_id' => 1 ), $fname
+       );
 
-       if ( 0 == wfNumRows( $res ) ) { return; }
-       else {
-               $s = wfFetchObject( $res );
+       if ( $s === false ) { 
+               return; 
+       } else {
                $wgTotalViews = $s->ss_total_views;
                $wgTotalEdits = $s->ss_total_edits;
                $wgNumberOfArticles = $s->ss_good_articles;
@@ -505,10 +508,14 @@ function wfRecordUpload( $name, $oldver, $size, $desc, $copyStatus = "", $source
        global $wgUseCopyrightUpload; 
        
        $fname = 'wfRecordUpload';
-
-       $sql = 'SELECT img_name,img_size,img_timestamp,img_description,img_user,' .
-         "img_user_text FROM image WHERE img_name='" . wfStrencode( $name ) . "'";
-       $res = wfQuery( $sql, DB_READ, $fname );
+       $dbw =& wfGetDB( DB_WRITE );
+       
+       # img_name must be unique
+       $indexInfo = $dbw->indexInfo( 'image', 'img_name' );
+       if ( $indexInfo && $indexInfo->Non_unique ) {
+               wfDebugDieBacktrace( 'Database schema not up to date, please run maintenance/archives/patch-img_name_unique.sql' );
+       }
+                       
 
        $now = wfTimestampNow();
        $won = wfInvertTimestamp( $now );
@@ -524,15 +531,24 @@ function wfRecordUpload( $name, $oldver, $size, $desc, $copyStatus = "", $source
 
        $now = wfTimestampNow();
        $won = wfInvertTimestamp( $now );
-       
-       if ( 0 == wfNumRows( $res ) ) {
-               $sql = 'INSERT INTO image (img_name,img_size,img_timestamp,' .
-                 "img_description,img_user,img_user_text) VALUES ('" .
-                 wfStrencode( $name ) . "',$size,'{$now}','" .
-                 wfStrencode( $desc ) . "', '" . $wgUser->getID() .
-                 "', '" . wfStrencode( $wgUser->getName() ) . "')";
-               wfQuery( $sql, DB_WRITE, $fname );
 
+       # 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', 
+               array(
+                       'img_name' => $name,
+                       'img_size'=> $size,
+                       'img_timestamp' => $now,
+                       'img_description' => $desc,
+                       'img_user' => $wgUser->getID(),
+                       'img_user_text' => $wgUser->getName(),
+               ), $fname, 'IGNORE'
+       );
+
+       if ( $dbw->affectedRows() ) {
+               # Successfully inserted, this is a new image
+               
                $sql = 'SELECT cur_id,cur_text FROM cur WHERE cur_namespace=' .
                  Namespace::getImage() . " AND cur_title='" .
                  wfStrencode( $name ) . "'";
@@ -559,6 +575,9 @@ function wfRecordUpload( $name, $oldver, $size, $desc, $copyStatus = "", $source
                        $u->doUpdate();
                }
        } else {
+               # Collision, this is an update of an image
+               $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,' .
@@ -999,5 +1018,29 @@ function wfInvertTimestamp( $ts ) {
        );
 }
 
+# Reference-counted warning suppression
+function wfSuppressWarnings( $end = false ) {
+       static $suppressCount = 0;
+       static $originalLevel = false;
+
+       if ( $end ) {
+               if ( $suppressCount ) {
+                       $suppressCount --;
+                       if ( !$suppressCount ) {
+                               error_reporting( $originalLevel );
+                       }
+               }
+       } else {
+               if ( !$suppressCount ) {
+                       $originalLevel = error_reporting( E_ALL & ~( E_WARNING | E_NOTICE ) );
+               }
+               $suppressCount++;
+       }
+}
+
+# Restore error level to previous value
+function wfRestoreWarnings() {
+       wfSuppressWarnings( true );
+}
 
 ?>
index 27eeb9d..eb9dd8e 100644 (file)
@@ -253,32 +253,31 @@ class Image
 
        //**********************************************************************
        // Return the image history of this image, line by line.
-       // start with current version, than old versions.
-       // use $this->historyLine to check which line to return:
+       // starts with current version, then old versions.
+       // uses $this->historyLine to check which line to return:
        //  0      return line for current version
        //  1      query for old versions, return first one
        //  2, ... return next old version from above query
        function nextHistoryLine()
        {
                $fname = "Image::nextHistoryLine()";
-               
-               if ( $this->historyLine == 0 ) // called for the first time, return line from cur
-               { 
-                       $sql = "SELECT img_size,img_description,img_user," .
-                         "img_user_text,img_timestamp, '' AS oi_archive_name FROM image WHERE " .
-                         "img_name='" . wfStrencode( $this->title->getDBkey() ) . "'";
-                       $this->historyRes = wfQuery( $sql, DB_READ, $fname );
-
-                       if ( 0 == wfNumRows( $this->historyRes ) ) { return FALSE; }
-
-               } else if ( $this->historyLine == 1 )
-               {
-                       $sql = "SELECT 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 FROM oldimage WHERE " .
-                         "oi_name='" . wfStrencode( $this->title->getDBkey() ) . "' " .
-                         "ORDER BY oi_timestamp DESC";
-                       $this->historyRes = wfQuery( $sql, DB_READ, $fname );
+               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() ),
+                               $fname
+                       );
+                       if ( 0 == wfNumRows( $this->historyRes ) ) { 
+                               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'
+                               ), array( 'oi_name' => $this->title->getDBkey() ), $fname, array( 'ORDER BY' => 'oi_timestamp DESC' ) 
+                       );
                }
                $this->historyLine ++;
 
index 6e8d72b..8073cdd 100644 (file)
@@ -85,18 +85,22 @@ class ImagePage extends Article {
 
                $wgOut->addHTML( "<h2>" . wfMsg( "imagelinks" ) . "</h2>\n" );
 
-               $sql = "SELECT cur_namespace,cur_title FROM imagelinks,cur WHERE il_to='" .
-                 wfStrencode( $this->mTitle->getDBkey() ) . "' AND il_from=cur_id";
-               $res = wfQuery( $sql, DB_READ, "Article::imageLinks" );
+               $dbr =& wfGetDB( DB_READ );
+               $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" );
 
-               if ( 0 == wfNumRows( $res ) ) {
+               if ( 0 == $dbr->numRows( $res ) ) {
                        $wgOut->addHtml( "<p>" . wfMsg( "nolinkstoimage" ) . "</p>\n" );
                        return;
                }
                $wgOut->addHTML( "<p>" . wfMsg( "linkstoimage" ) .  "</p>\n<ul>" );
 
                $sk = $wgUser->getSkin();
-               while ( $s = wfFetchObject( $res ) ) {
+               while ( $s = $dbr->fetchObject( $res ) ) {
                        $name = Title::MakeTitle( $s->cur_namespace, $s->cur_title );
                        $link = $sk->makeKnownLinkObj( $name, "" );
                        $wgOut->addHTML( "<li>{$link}</li>\n" );
@@ -157,6 +161,8 @@ class ImagePage extends Article {
                $reason = $wgRequest->getVal( 'wpReason' );
                $image = $wgRequest->getVal( 'image' );
                $oldimage = $wgRequest->getVal( 'oldimage' );
+               
+               $dbw =& wfGetDB( DB_WRITE );
 
                if ( !is_null( $image ) ) {
                        $dest = wfImageDir( $image );
@@ -165,14 +171,9 @@ class ImagePage extends Article {
                                $wgOut->fileDeleteError( "{$dest}/{$image}" );
                                return;
                        }
-                       $sql = "DELETE FROM image WHERE img_name='" .
-                         wfStrencode( $image ) . "'";
-                       wfQuery( $sql, DB_WRITE, $fname );
-
-                       $sql = "SELECT oi_archive_name FROM oldimage WHERE oi_name='" .
-                         wfStrencode( $image ) . "'";
-                       $res = wfQuery( $sql, DB_READ, $fname );
-                       
+                       $dbw->delete( 'image', array( 'img_name' => $image ) );
+                       $res = $dbw->select( 'oldimage', array( 'oi_archive_name' ), array( 'oi_name' => $image ) );
+                                               
                        # Squid purging
                        if ( $wgUseSquid ) {
                                $urlArr = Array(
@@ -183,7 +184,7 @@ class ImagePage extends Article {
                        
 
                        $urlArr = Array();
-                       while ( $s = wfFetchObject( $res ) ) {
+                       while ( $s = $dbr->fetchObject( $res ) ) {
                                $this->doDeleteOldImage( $s->oi_archive_name );
                                $urlArr[] = $wgInternalServer.wfImageArchiveUrl( $s->oi_archive_name );
                        }       
@@ -195,9 +196,7 @@ class ImagePage extends Article {
                                array_push( $wgDeferredUpdateList, $u );
                        }
                        
-                       $sql = "DELETE FROM oldimage WHERE oi_name='" .
-                         wfStrencode( $image ) . "'";
-                       wfQuery( $sql, DB_WRITE, $fname );
+                       $dbw->delete( 'oldimage', array( 'oi_name' => $image ) );
 
                        # Image itself is now gone, and database is cleaned.
                        # Now we remove the image description page.
@@ -216,10 +215,7 @@ class ImagePage extends Article {
                                wfPurgeSquidServers($urlArr);
                        }
                        $this->doDeleteOldImage( $oldimage );
-                       $sql = "DELETE FROM oldimage WHERE oi_archive_name='" .
-                         wfStrencode( $oldimage ) . "'";
-                       wfQuery( $sql, DB_WRITE, $fname );
-
+                       $dbw->delete( 'oldimage', array( 'oi_archive_name' => $oldimage ) );
                        $deleted = $oldimage;
                } else {
                        $this->doDeleteArticle( $reason ); # ignore errors
@@ -276,8 +272,10 @@ class ImagePage extends Article {
                        return;
                }
                $oldver = wfTimestampNow() . "!{$name}";
-               $size = wfGetSQL( "oldimage", "oi_size", "oi_archive_name='" .
-                 wfStrencode( $oldimage ) . "'" );
+               
+               $dbr =& wfGetDB( DB_READ );
+               $size = $dbr->getField( "oldimage", "oi_size", "oi_archive_name='" .
+                 $dbr->strencode( $oldimage ) . "'" );
 
                if ( ! rename( $curfile, "${archive}/{$oldver}" ) ) {
                        $wgOut->fileRenameError( $curfile, "${archive}/{$oldver}" );
index cd0c087..8dcba6f 100644 (file)
@@ -131,15 +131,10 @@ class LinkCache {
                if( $wgLinkCacheMemcached )
                        $id = $wgMemc->get( $key = $this->getKey( $title ) );
                if( ! is_integer( $id ) ) {
-                       $sql = "SELECT cur_id FROM cur WHERE cur_namespace=" .
-                         "{$ns} AND cur_title='" . wfStrencode( $t ) . "'";
-                       $res = wfQuery( $sql, DB_READ, "LinkCache::addLink" );
-
-                       if ( 0 == wfNumRows( $res ) ) {
+                       $dbr =& wfGetDB( DB_READ );
+                       $id = $dbr->getField( 'cur', 'cur_id', array( 'cur_namespace' => $ns, 'cur_title' => $t ), $fname );
+                       if ( !$id ) {
                                $id = 0;
-                       } else {
-                               $s = wfFetchObject( $res );
-                               $id = $s->cur_id;
                        }
                        if( $wgLinkCacheMemcached )
                                $wgMemc->add( $key, $id, 3600*24 );
@@ -176,20 +171,21 @@ class LinkCache {
                        }
                }
 
+               $dbr =& wfGetDB( DB_READ );
+               $cur = $dbr->tableName( 'cur' );
+               $links = $dbr->tableName( 'links' );
+
                $sql = "SELECT cur_id,cur_namespace,cur_title
-                       FROM cur,links
+                       FROM $cur,$links
                        WHERE cur_id=l_to AND l_from=$id";
-               $res = wfQuery( $sql, DB_READ, $fname );
-               while( $s = wfFetchObject( $res ) ) {
+               $res = $dbr->query( $sql, $fname );
+               while( $s = $dbr->fetchObject( $res ) ) {
                        $this->addGoodLink( $s->cur_id,
                                Title::makeName( $s->cur_namespace, $s->cur_title )
                                );
                }
                
-               $sql = "SELECT bl_to
-                       FROM brokenlinks
-                       WHERE bl_from='{$id}'";
-               $res = wfQuery( $sql, DB_READ, "LinkCache::preFill" );
+               $res = $dbr->select( 'brokenlinks', array( 'bl_to' ), array( 'bl_from' => $id ), $fname );
                while( $s = wfFetchObject( $res ) ) {
                        $this->addBadLink( $s->bl_to );
                }
@@ -276,18 +272,18 @@ class LinkCache {
 
        /* private */ function fillFromLinkscc( $id ){ 
                $id = IntVal( $id );
-               $res = wfQuery("SELECT lcc_cacheobj FROM linkscc WHERE lcc_pageid = $id", 
-                       DB_READ);
-               $row = wfFetchObject( $res );
-               if( $row == FALSE)
-                       return false;   
-
+               $dbr =& wfGetDB( DB_READ );
+               $raw = $dbr->getField( 'linkscc', 'lcc_cacheobj', array( 'lcc_pageid' => $id ) );
+               if ( $raw === false ) {
+                       return false;
+               }
+               
                $cacheobj = false;
                if( function_exists( "gzuncompress" ) )
-                       $cacheobj = @gzuncompress( $row->lcc_cacheobj );
+                       $cacheobj = @gzuncompress( $raw );
 
                if($cacheobj == FALSE){
-                       $cacheobj = $row->lcc_cacheobj;
+                       $cacheobj = $raw;
                }
                $cc = @unserialize( $cacheobj );
                if( isset( $cc->mClassVer ) and ($cc->mClassVer == $this->mClassVer ) ){
@@ -302,51 +298,41 @@ class LinkCache {
        }
 
        /* private */ function saveToLinkscc( $pid ){
-               global $wgCompressedPersistentLC, $wgIsMySQL;
+               global $wgCompressedPersistentLC;
                if( $wgCompressedPersistentLC and function_exists( "gzcompress" ) ) {
-                       $ser = wfStrencode( gzcompress( serialize( $this ), 3 ));
+                       $ser = gzcompress( serialize( $this ), 3 );
                } else {
-                       $ser = wfStrencode( serialize( $this ) );
-               }
-               if ($wgIsMySQL) {
-                       wfQuery("REPLACE INTO linkscc(lcc_pageid,lcc_cacheobj) " .
-                               "VALUES({$pid}, '{$ser}')", DB_WRITE);
-               } else {
-                       wfQuery("DELETE FROM linkscc WHERE lcc_pageid={$pid}",DB_WRITE);
-                       wfQuery("INSERT INTO linkscc(lcc_pageid,lcc_cacheobj) " .
-                               "VALUES({$pid}, '{$ser}')", DB_WRITE);
+                       $ser = serialize( $this );
                }
+               $db =& wfGetDB( DB_WRITE );
+               $db->replace( 'linkscc', array( 'lcc_pageid' ), array( 'lcc_pageid' => $pid, 'lcc_cacheobj' => $ser ) );
        }
 
+       # Delete linkscc rows which link to here
        # $pid is a page id
        /* static */ function linksccClearLinksTo( $pid ){
-               global $wgEnablePersistentLC, $wgIsMySQL;
+               global $wgEnablePersistentLC;
                if ( $wgEnablePersistentLC ) {
+                       $fname = "LinkCache::linksccClearLinksTo";
                        $pid = intval( $pid );
-                       if ($wgIsMySQL) {
-                               wfQuery("DELETE linkscc FROM linkscc,links ".
-                                       "WHERE lcc_pageid=links.l_from AND l_to={$pid}", DB_WRITE);
-                       } else {
-                               wfQuery("DELETE FROM linkscc WHERE lcc_pageid IN ".
-                                       "(SELECT l_from FROM links WHERE l_to={$pid})", DB_WRITE);
-                       }
-                       wfQuery("DELETE FROM linkscc WHERE lcc_pageid='{$pid}'", DB_WRITE);
+                       $dbw =& wfGetDB( DB_WRITE );
+                       # 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
+                       $dbw->delete( 'linkscc', array( 'lcc_pageid' => $pid ), $fname);
                }
+
        }
 
+       # Delete linkscc rows with broken links to here
        # $title is a prefixed db title, for example like Title->getPrefixedDBkey() returns.
        /* static */ function linksccClearBrokenLinksTo( $title ){
-               global $wgEnablePersistentLC,$wgIsMySQL;
+               global $wgEnablePersistentLC;
+               $fname = 'LinkCache::linksccClearBrokenLinksTo';
+
                if ( $wgEnablePersistentLC ) {
-                       $title = wfStrencode( $title );
-                       if ($wgIsMySQL) {
-                               wfQuery("DELETE linkscc FROM linkscc,brokenlinks ".
-                                       "WHERE lcc_pageid=bl_from AND bl_to='{$title}'", DB_WRITE);
-                       } else {
-                               wfQuery("DELETE FROM linkscc WHERE lcc_pageid IN ".
-                                       "(SELECT bl_from FROM brokenlinks ".
-                                       "WHERE bl_to='{$title}')",DB_WRITE);
-                       }
+                       $dbw =& wfGetDB( DB_WRITE );
+                       $dbw->deleteJoin( 'linkscc', 'brokenlinks', 'lcc_pageid', 'bl_from', array( 'bl_to' => $title ), $fname );
                }
        }
 
@@ -355,7 +341,8 @@ class LinkCache {
                global $wgEnablePersistentLC;
                if ( $wgEnablePersistentLC ) {
                        $pid = intval( $pid );
-                       wfQuery("DELETE FROM linkscc WHERE lcc_pageid='{$pid}'", DB_WRITE);
+                       $dbw =& wfGetDB( DB_WRITE );
+                       $dbw->delete( 'linkscc', array( 'lcc_pageid' => $pid ) );
                }
        }
 }
index da4f47c..64b9aaf 100644 (file)
@@ -9,7 +9,6 @@ class LinksUpdate {
        {
                $this->mId = $id;
                $this->mTitle = $title;
-               $this->mTitleEnc = wfStrencode( $title );
        }
 
        
@@ -27,10 +26,11 @@ class LinksUpdate {
                $del = array();
                $add = array();
 
-               if( $wgDBtransactions ) {
-                       $sql = "BEGIN";
-                       wfQuery( $sql, DB_WRITE, $fname );
-               }
+               $dbw =& wfGetDB( DB_WRITE );
+               $links = $dbw->tableName( 'links' );
+               $brokenlinks = $dbw->tableName( 'brokenlinks' );
+               $imagelinks = $dbw->tableName( 'imagelinks' );
+               $categorylinks = $dbw->tableName( 'categorylinks' );
                
                #------------------------------------------------------------------------------
                # Good links
@@ -38,15 +38,14 @@ class LinksUpdate {
                if ( $wgLinkCache->incrementalSetup( LINKCACHE_GOOD, $del, $add ) ) {
                        # Delete where necessary
                        if ( count( $del ) ) {
-                               $sql = "DELETE FROM links WHERE l_from={$this->mId} AND l_to IN(".
+                               $sql = "DELETE FROM $links WHERE l_from={$this->mId} AND l_to IN(".
                                        implode( ",", $del ) . ")";
-                               wfQuery( $sql, DB_WRITE, $fname );
+                               $dbw->query( $sql, $fname );
                        }
                } else {
                        # Delete everything
-                       $sql = "DELETE FROM links WHERE l_from={$this->mId}";
-                       wfQuery( $sql, DB_WRITE, $fname );
-                       
+                       $dbw->delete( 'links', array( 'l_from' => $this->mId ), $fname );
+                                               
                        # Get the addition list
                        $add = $wgLinkCache->getGoodLinks();
                }
@@ -57,10 +56,9 @@ class LinksUpdate {
                        # The link cache was constructed without FOR UPDATE, so there may be collisions
                        # Ignoring for now, I'm not sure if that causes problems or not, but I'm fairly
                        # sure it's better than without IGNORE
-                       $sql = "INSERT IGNORE INTO links (l_from,l_to) VALUES ";
+                       $sql = "INSERT IGNORE INTO $links (l_from,l_to) VALUES ";
                        $first = true;
                        foreach( $add as $lt => $lid ) {
-                               
                                if ( ! $first ) { $sql .= ","; }
                                $first = false;
 
@@ -68,7 +66,7 @@ class LinksUpdate {
                        }
                }
                if ( "" != $sql ) { 
-                       wfQuery( $sql, DB_WRITE, $fname ); 
+                       $dbw->query( $sql, $fname ); 
                }
 
                #------------------------------------------------------------------------------
@@ -77,14 +75,21 @@ class LinksUpdate {
                if ( $wgLinkCache->incrementalSetup( LINKCACHE_BAD, $del, $add ) ) {
                        # Delete where necessary
                        if ( count( $del ) ) {
-                               $sql = "DELETE FROM brokenlinks WHERE bl_from={$this->mId} AND bl_to IN('" .    
-                                       implode( "','", array_map( "wfStrencode", $del ) ) . "')";
-                               wfQuery( $sql, DB_WRITE, $fname );
+                               $sql = "DELETE FROM $brokenlinks WHERE bl_from={$this->mId} AND bl_to IN(";
+                               $first = true;
+                               foreach( $del as $badTitle ) {
+                                       if ( $first ) {
+                                               $first = false;
+                                       } else {
+                                               $sql .= ",";
+                                       }
+                                       $sql .= $dbw->addQuotes( $badTitle );
+                               }
+                               $dbw->query( $sql, $fname );
                        }
                } else {
                        # Delete all
-                       $sql = "DELETE FROM brokenlinks WHERE bl_from={$this->mId}";
-                       wfQuery( $sql, DB_WRITE, $fname );
+                       $dbw->delete( 'brokenlinks', array( 'bl_from' => $this->mId ) );
                        
                        # Get addition list
                        $add = $wgLinkCache->getBadLinks();
@@ -93,10 +98,10 @@ class LinksUpdate {
                # Do additions
                $sql = "";
                if ( 0 != count ( $add ) ) {
-                       $sql = "INSERT IGNORE INTO brokenlinks (bl_from,bl_to) VALUES ";
+                       $sql = "INSERT IGNORE INTO $brokenlinks (bl_from,bl_to) VALUES ";
                        $first = true;
                        foreach( $add as $blt ) {
-                               $blt = wfStrencode( $blt );
+                               $blt = $dbw->strencode( $blt );
                                if ( ! $first ) { $sql .= ","; }
                                $first = false;
 
@@ -104,13 +109,13 @@ class LinksUpdate {
                        }
                }
                if ( "" != $sql ) { 
-                       wfQuery( $sql, DB_WRITE, $fname );
+                       $dbw->query( $sql, $fname );
                }
 
                #------------------------------------------------------------------------------
                # Image links
-               $sql = "DELETE FROM imagelinks WHERE il_from='{$this->mId}'";
-               wfQuery( $sql, DB_WRITE, $fname );
+               $sql = "DELETE FROM $imagelinks WHERE il_from='{$this->mId}'";
+               $dbw->query( $sql, $fname );
                
                # Get addition list
                $add = $wgLinkCache->getImageLinks();
@@ -119,7 +124,7 @@ class LinksUpdate {
                $sql = "";
                $image = Namespace::getImage();
                if ( 0 != count ( $add ) ) {
-                       $sql = "INSERT IGNORE INTO imagelinks (il_from,il_to) VALUES ";
+                       $sql = "INSERT IGNORE INTO $imagelinks (il_from,il_to) VALUES ";
                        $first = true;
                        foreach( $add as $iname => $val ) {
                                # FIXME: Change all this to avoid unnecessary duplication
@@ -127,20 +132,22 @@ class LinksUpdate {
                                if( !$nt ) continue;
                                $nt->invalidateCache();
 
-                               $iname = wfStrencode( $iname );
+                               $iname = $dbw->strencode( $iname );
                                if ( ! $first ) { $sql .= ","; }
                                $first = false;
 
                                $sql .= "({$this->mId},'{$iname}')";
                        }
                }
-               if ( "" != $sql ) { wfQuery( $sql, DB_WRITE, $fname ); }
+               if ( "" != $sql ) { 
+                       $dbw->query( $sql, $fname ); 
+               }
 
                #------------------------------------------------------------------------------
                # Category links
                if( $wgUseCategoryMagic ) {
-                       $sql = "DELETE FROM categorylinks WHERE cl_from='{$this->mId}'";
-                       wfQuery( $sql, DB_WRITE, $fname );
+                       $sql = "DELETE FROM $categorylinks WHERE cl_from='{$this->mId}'";
+                       $dbw->query( $sql, $fname );
                        
                        # Get addition list
                        $add = $wgLinkCache->getCategoryLinks();
@@ -148,7 +155,7 @@ class LinksUpdate {
                        # Do the insertion
                        $sql = "";
                        if ( 0 != count ( $add ) ) {
-                               $sql = "INSERT IGNORE INTO categorylinks (cl_from,cl_to,cl_sortkey) VALUES ";
+                               $sql = "INSERT IGNORE INTO $categorylinks (cl_from,cl_to,cl_sortkey) VALUES ";
                                $first = true;
                                foreach( $add as $cname => $sortkey ) {
                                        # FIXME: Change all this to avoid unnecessary duplication
@@ -159,19 +166,17 @@ class LinksUpdate {
                                        if ( ! $first ) { $sql .= ","; }
                                        $first = false;
        
-                                       $sql .= "({$this->mId},'" . wfStrencode( $cname ) .
-                                               "','" . wfStrencode( $sortkey ) . "')";
+                                       $sql .= "({$this->mId},'" . $dbw->strencode( $cname ) .
+                                               "','" . $dbw->strencode( $sortkey ) . "')";
                                }
                        }
-                       if ( "" != $sql ) { wfQuery( $sql, DB_WRITE, $fname ); }
+                       if ( "" != $sql ) { 
+                               $dbw->query( $sql, $fname ); 
+                       }
                }
                
                $this->fixBrokenLinks();
 
-               if( $wgDBtransactions ) {
-                       $sql = "COMMIT";
-                       wfQuery( $sql, DB_WRITE, $fname );
-               }
                wfProfileOut( $fname );
        }
        
@@ -179,23 +184,24 @@ class LinksUpdate {
        {
                # Old inefficient update function
                # Used for rebuilding the link table
-               
                global $wgLinkCache, $wgDBtransactions, $wgUseCategoryMagic;
                $fname = "LinksUpdate::doDumbUpdate";
                wfProfileIn( $fname );
-
-               if( $wgDBtransactions ) {
-                       $sql = "BEGIN";
-                       wfQuery( $sql, DB_WRITE, $fname );
-               }
                
-               $sql = "DELETE FROM links WHERE l_from={$this->mId}";
-               wfQuery( $sql, DB_WRITE, $fname );
+               
+               $dbw =& wfGetDB( DB_WRITE );
+               $links = $dbw->tableName( 'links' );
+               $brokenlinks = $dbw->tableName( 'brokenlinks' );
+               $imagelinks = $dbw->tableName( 'imagelinks' );
+               $categorylinks = $dbw->tableName( 'categorylinks' );
+               
+               $sql = "DELETE FROM $links WHERE l_from={$this->mId}";
+               $dbw->query( $sql, $fname );
 
                $a = $wgLinkCache->getGoodLinks();
                $sql = "";
                if ( 0 != count( $a ) ) {
-                       $sql = "INSERT IGNORE INTO links (l_from,l_to) VALUES ";
+                       $sql = "INSERT IGNORE INTO $links (l_from,l_to) VALUES ";
                        $first = true;
                        foreach( $a as $lt => $lid ) {
                                if ( ! $first ) { $sql .= ","; }
@@ -204,47 +210,53 @@ class LinksUpdate {
                                $sql .= "({$this->mId},{$lid})";
                        }
                }
-               if ( "" != $sql ) { wfQuery( $sql, DB_WRITE, $fname ); }
+               if ( "" != $sql ) { 
+                       $dbw->query( $sql, $fname ); 
+               }
 
-               $sql = "DELETE FROM brokenlinks WHERE bl_from={$this->mId}";
-               wfQuery( $sql, DB_WRITE, $fname );
+               $sql = "DELETE FROM $brokenlinks WHERE bl_from={$this->mId}";
+               $dbw->query( $sql, $fname );
 
                $a = $wgLinkCache->getBadLinks();
                $sql = "";
                if ( 0 != count ( $a ) ) {
-                       $sql = "INSERT IGNORE INTO brokenlinks (bl_from,bl_to) VALUES ";
+                       $sql = "INSERT IGNORE INTO $brokenlinks (bl_from,bl_to) VALUES ";
                        $first = true;
                        foreach( $a as $blt ) {
-                               $blt = wfStrencode( $blt );
+                               $blt = $dbw->strencode( $blt );
                                if ( ! $first ) { $sql .= ","; }
                                $first = false;
 
                                $sql .= "({$this->mId},'{$blt}')";
                        }
                }
-               if ( "" != $sql ) { wfQuery( $sql, DB_WRITE, $fname ); }
+               if ( "" != $sql ) { 
+                       $dbw->query( $sql, $fname ); 
+               }
                
-               $sql = "DELETE FROM imagelinks WHERE il_from={$this->mId}";
-               wfQuery( $sql, DB_WRITE, $fname );
+               $sql = "DELETE FROM $imagelinks WHERE il_from={$this->mId}";
+               $dbw->query( $sql, $fname );
 
                $a = $wgLinkCache->getImageLinks();
                $sql = "";
                if ( 0 != count ( $a ) ) {
-                       $sql = "INSERT IGNORE INTO imagelinks (il_from,il_to) VALUES ";
+                       $sql = "INSERT IGNORE INTO $imagelinks (il_from,il_to) VALUES ";
                        $first = true;
                        foreach( $a as $iname => $val ) {
-                               $iname = wfStrencode( $iname );
+                               $iname = $dbw->strencode( $iname );
                                if ( ! $first ) { $sql .= ","; }
                                $first = false;
 
                                $sql .= "({$this->mId},'{$iname}')";
                        }
                }
-               if ( "" != $sql ) { wfQuery( $sql, DB_WRITE, $fname ); }
+               if ( "" != $sql ) { 
+                       $dbw->query( $sql, $fname ); 
+               }
 
                if( $wgUseCategoryMagic ) {
-                       $sql = "DELETE FROM categorylinks WHERE cl_from='{$this->mId}'";
-                       wfQuery( $sql, DB_WRITE, $fname );
+                       $sql = "DELETE FROM $categorylinks WHERE cl_from='{$this->mId}'";
+                       $dbw->query( $sql, $fname );
                        
                        # Get addition list
                        $add = $wgLinkCache->getCategoryLinks();
@@ -252,7 +264,7 @@ class LinksUpdate {
                        # Do the insertion
                        $sql = "";
                        if ( 0 != count ( $add ) ) {
-                               $sql = "INSERT IGNORE INTO categorylinks (cl_from,cl_to,cl_sortkey) VALUES ";
+                               $sql = "INSERT IGNORE INTO $categorylinks (cl_from,cl_to,cl_sortkey) VALUES ";
                                $first = true;
                                foreach( $add as $cname => $sortkey ) {
                                        # FIXME: Change all this to avoid unnecessary duplication
@@ -263,18 +275,15 @@ class LinksUpdate {
                                        if ( ! $first ) { $sql .= ","; }
                                        $first = false;
        
-                                       $sql .= "({$this->mId},'" . wfStrencode( $cname ) .
-                                               "','" . wfStrencode( $sortkey ) . "')";
+                                       $sql .= "({$this->mId},'" . $dbw->strencode( $cname ) .
+                                               "','" . $dbw->strencode( $sortkey ) . "')";
                                }
                        }
-                       if ( "" != $sql ) { wfQuery( $sql, DB_WRITE, $fname ); }
+                       if ( "" != $sql ) { 
+                               $dbw->query( $sql, $fname ); 
+                       }
                }
                $this->fixBrokenLinks();
-
-               if( $wgDBtransactions ) {
-                       $sql = "COMMIT";
-                       wfQuery( $sql, DB_WRITE, $fname );
-               }
                wfProfileOut( $fname );
        }
        
@@ -282,18 +291,22 @@ class LinksUpdate {
                /* Update any brokenlinks *to* this page */
                /* Call for a newly created page, or just to make sure state is consistent */
                $fname = "LinksUpdate::fixBrokenLinks";
+
+               $dbw =& wfGetDB( DB_WRITE );
+               $cur = $dbw->tableName( 'cur' );
+               $links = $dbw->tableName( 'links' );
                
-               $sql = "SELECT bl_from FROM brokenlinks WHERE bl_to='{$this->mTitleEnc}'";
-               $res = wfQuery( $sql, DB_READ, $fname );
-               if ( 0 == wfNumRows( $res ) ) { return; }
+               $res = $dbw->select( 'brokenlinks', array( 'bl_from' ), array( 'bl_to' => $this->mTitle ), 
+                 $fname, 'FOR UPDATE' );
+               if ( 0 == $dbw->numRows( $res ) ) { return; }
 
                # Ignore errors. If a link existed in both the brokenlinks table and the links 
                # table, that's an error which can be fixed at this stage by simply ignoring collisions
-               $sql = "INSERT IGNORE INTO links (l_from,l_to) VALUES ";
+               $sql = "INSERT IGNORE INTO $links (l_from,l_to) VALUES ";
                $now = wfTimestampNow();
-               $sql2 = "UPDATE cur SET cur_touched='{$now}' WHERE cur_id IN (";
+               $sql2 = "UPDATE $cur SET cur_touched='{$now}' WHERE cur_id IN (";
                $first = true;
-               while ( $row = wfFetchObject( $res ) ) {
+               while ( $row = $dbw->fetchObject( $res ) ) {
                        if ( ! $first ) { $sql .= ","; $sql2 .= ","; }
                        $first = false;
 
@@ -301,13 +314,11 @@ class LinksUpdate {
                        $sql2 .= $row->bl_from;
                }
                $sql2 .= ")";
-               wfQuery( $sql, DB_WRITE, $fname );
-               wfQuery( $sql2, DB_WRITE, $fname );
+               $dbw->query( $sql, $fname );
+               $dbw->query( $sql2, $fname );
 
-               $sql = "DELETE FROM brokenlinks WHERE bl_to='{$this->mTitleEnc}'";
-               wfQuery( $sql, DB_WRITE, $fname );
+               $dbw->delete( 'brokenlinks', array( 'bl_to' => $this->mTitle ), $fname );
        }
-       
 }
 
 ?>
index 94f4f55..cfc3894 100644 (file)
@@ -1,6 +1,8 @@
 <?php
 # Database load balancing object
 
+require_once( "Database.php" );
+
 # Valid database indexes
 # Operation-based indexes
 define( "DB_READ", -1 );     # Read from the slave (or only server)
@@ -20,43 +22,41 @@ define( "DB_TASK_LAST", 1004) ;   # Last in list
 
 class LoadBalancer {
        /* private */ var $mServers, $mConnections, $mLoads;
-       /* private */ var $mUser, $mPassword, $mDbName, $mFailFunction;
+       /* private */ var $mFailFunction;
        /* private */ var $mForce, $mReadIndex, $mLastConn;
 
        function LoadBalancer()
        {
                $this->mServers = array();
-               $this->mLoads = array();
                $this->mConnections = array();
-               $this->mUser = false;
-               $this->mPassword = false;
-               $this->mDbName = false;
                $this->mFailFunction = false;
                $this->mReadIndex = -1;
                $this->mForce = -1;
                $this->mLastConn = false;
        }
 
-       function newFromParams( $servers, $loads, $user, $password, $dbName, $failFunction = false )
+       function newFromParams( $servers, $failFunction = false )
        {
                $lb = new LoadBalancer;
-               $lb->initialise( $servers, $loads, $user, $password, $dbName, $failFunction = false );
+               $lb->initialise( $servers, $failFunction = false );
                return $lb;
        }
 
-       function initialise( $servers, $loads, $user, $password, $dbName, $failFunction = false )
+       function initialise( $servers, $failFunction = false )
        {
                $this->mServers = $servers;
-               $this->mLoads = $loads;
-               $this->mUser = $user;
-               $this->mPassword = $password;
-               $this->mDbName = $dbName;
                $this->mFailFunction = $failFunction;
                $this->mReadIndex = -1;
                $this->mWriteIndex = -1;
                $this->mForce = -1;
                $this->mConnections = array();
                $this->mLastConn = false;
+               $this->mLoads = array();
+
+               foreach( $servers as $i => $server ) {
+                       $this->mLoads[$i] = $server['load'];
+               }
+
                wfSeedRandom();
        }
        
@@ -99,7 +99,7 @@ class LoadBalancer {
                                do {
                                        $i = $this->pickRandom( $loads );
                                        if ( $i !== false ) {
-                                               wfDebug( "Using reader #$i: {$this->mServers[$i]}\n" );
+                                               wfDebug( "Using reader #$i: {$this->mServers[$i]['host']}\n" );
 
                                                $conn =& $this->getConnection( $i );
                                                if ( !$conn->isOpen() ) {
@@ -148,11 +148,10 @@ class LoadBalancer {
                } else {
                        # Explicit index
                        if ( !array_key_exists( $i, $this->mConnections) || !$this->mConnections[$i]->isOpen() ) {
-                               $this->mConnections[$i] = Database::newFromParams( $this->mServers[$i], $this->mUser, 
-                                 $this->mPassword, $this->mDbName, 1 );
+                               $this->mConnections[$i] = $this->makeConnection( $this->mServers[$i] );
                        }
                        if ( !$this->mConnections[$i]->isOpen() ) {
-                               wfDebug( "Failed to connect to database $i at {$this->mServers[$i]}\n" );
+                               wfDebug( "Failed to connect to database $i at {$this->mServers[$i]['host']}\n" );
                                if ( $fail ) {
                                        $this->reportConnectionError( $this->mConnections[$i] );
                                }
@@ -163,6 +162,18 @@ class LoadBalancer {
                return $this->mLastConn;
        }
 
+       /* private */ function makeConnection( &$server ) {
+                       extract( $server );
+                       # Get class for this database type
+                       $class = 'Database' . ucfirst( $type );
+                       if ( !class_exists( $class ) ) {
+                               require_once( "$class.php" );
+                       }
+
+                       # Create object
+                       return new $class( $host, $user, $password, $dbname, 1 );
+       }
+       
        function reportConnectionError( &$conn )
        {
                if ( !is_object( $conn ) ) {
index 6be15fe..31f598c 100644 (file)
@@ -18,13 +18,16 @@ class LogPage {
 
        function getContent( $defaulttext = "<ul>\n</ul>" )
        {
-               $sql = "SELECT cur_id,cur_text,cur_timestamp FROM cur " .
-                       "WHERE cur_namespace=" . Namespace::getWikipedia() . " AND " .
-                       "cur_title='" . wfStrencode($this->mTitle ) . "'";
-               $res = wfQuery( $sql, DB_READ, "LogPage::getContent" );
+               $fname = 'LogPage::getContent';
 
-               if( wfNumRows( $res ) > 0 ) {
-                       $s = wfFetchObject( $res );
+               $dbw =& wfGetDB( DB_WRITE );
+               $s = $dbw->getArray( 'cur', 
+                       array( 'cur_id','cur_text','cur_timestamp' ),
+                       array( 'cur_namespace' => Namespace::getWikipedia(), 'cur_title' => $this->mTitle ), 
+                       $fname, 'FOR UPDATE' 
+               );
+
+               if( $s !== false ) {
                        $this->mId = $s->cur_id;
                        $this->mContent = $s->cur_text;
                        $this->mTimestamp = $s->cur_timestamp;
@@ -52,31 +55,49 @@ class LogPage {
 
                global $wgUser;
                $fname = "LogPage::saveContent";
+
+               $dbw =& wfGetDB( DB_WRITE );
                $uid = $wgUser->getID();
-               $ut = wfStrencode( $wgUser->getName() );
 
                if( !$this->mContentLoaded ) return false;
                $this->mTimestamp = $now = wfTimestampNow();
                $won = wfInvertTimestamp( $now );
                if($this->mId == 0) {
-                       $sql = "INSERT INTO cur (cur_timestamp,cur_user,cur_user_text,
-                               cur_namespace,cur_title,cur_text,cur_comment,cur_restrictions,
-                               inverse_timestamp,cur_touched)
-                               VALUES ('{$now}', {$uid}, '{$ut}', " .
-                               Namespace::getWikipedia() . ", '" .
-                               wfStrencode( $this->mTitle ) . "', '" .
-                               wfStrencode( $this->mContent ) . "', '" .
-                               wfStrencode( $this->mComment ) . "', 'sysop', '{$won}','{$now}')";
-                       wfQuery( $sql, DB_WRITE, $fname );
-                       $this->mId = wfInsertId();
+                       $seqVal = $dbw->nextSequenceValue( 'cur_cur_id_seq' );
+
+                       # Note: this query will deadlock if another thread has called getContent(), 
+                       # at least in MySQL 4.0.17 InnoDB
+                       $dbw->insertArray( 'cur',
+                               array(
+                                       'cur_id' => $seqVal,
+                                       'cur_timestamp' => $now,
+                                       'cur_user' => $uid,
+                                       'cur_user_text' => $wgUser->getName(),
+                                       'cur_namespace' => NS_WIKIPEDIA,
+                                       'cur_title' => $this->mTitle, 
+                                       'cur_text' => $this->mContent,
+                                       'cur_comment' => $this->mComment,
+                                       'cur_restrictions' => 'sysop',
+                                       'inverse_timestamp' => $won,
+                                       'cur_touched' => $now,
+                               ), $fname
+                       );
+                       $this->mId = $dbw->insertId();
                } else {
-                       $sql = "UPDATE cur SET cur_timestamp='{$now}', " .
-                         "cur_user={$uid}, cur_user_text='{$ut}', " .
-                         "cur_text='" . wfStrencode( $this->mContent ) . "', " .
-                         "cur_comment='" . wfStrencode( $this->mComment ) . "', " .
-                         "cur_restrictions='sysop', inverse_timestamp='{$won}', cur_touched='{$now}' " .
-                         "WHERE cur_id={$this->mId}";
-                       wfQuery( $sql, DB_WRITE, $fname );
+                       $dbw->updateArray( 'cur',
+                               array( /* SET */ 
+                                       'cur_timestamp' => $now,
+                                       'cur_user' => $uid, 
+                                       'cur_user_text' => $wgUser->getName(),
+                                       'cur_text' => $this->mContent,
+                                       'cur_comment' => $this->mComment,
+                                       'cur_restrictions' => 'sysop', 
+                                       'inverse_timestamp' => $won,
+                                       'cur_touched' => $now,
+                               ), array( /* WHERE */
+                                       'cur_id' => $this->mId
+                               ), $fname
+                       );
                }
                
                # And update recentchanges
index 8b03af6..827c116 100644 (file)
@@ -54,10 +54,10 @@ class MathRenderer {
                                return $this->_error( "math_notexvc" );
                        }
                        $cmd = $wgTexvc." ".
-                               escapeshellarg($wgTmpDirectory)." ".
-                               escapeshellarg($wgMathDirectory)." ".
-                               escapeshellarg($this->tex)." ".
-                               escapeshellarg($wgInputEncoding);
+                               wfEscapeShellArg($wgTmpDirectory)." ".
+                               wfEscapeShellArg($wgMathDirectory)." ".
+                               wfEscapeShellArg($this->tex)." ".
+                               wfEscapeShellArg($wgInputEncoding);
                        wfDebug( "TeX: $cmd" );
                        $contents = `$cmd`;
                
@@ -79,9 +79,6 @@ class MathRenderer {
                
                                $this->html = substr($outdata, 0, $i);
                                $this->mathml = substr($outdata, $i+1);
-               
-                               $sql_html = "'".wfStrencode($this->html)."'";
-                               $sql_mathml = "'".wfStrencode($this->mathml)."'";
                        } else if (($retval == "c") || ($retval == "m") || ($retval == "l"))  {
                                $this->html = substr ($contents, 33);
                                if ($retval == "c")
@@ -90,20 +87,14 @@ class MathRenderer {
                                        $this->conservativeness = 1;
                                else
                                        $this->conservativeness = 0;
-                               $sql_html = "'".wfStrencode($this->html)."'";
-                               $this->mathml = '';
-                               $sql_mathml = 'NULL';
+                               $this->mathml = NULL;
                        } else if ($retval == "X") {
-                               $outhtml = '';
+                               $outhtml = NULL;
                                $this->mathml = substr ($contents, 33);
-                               $sql_html = 'NULL';
-                               $sql_mathml = "'".wfStrencode($this->mathml)."'";
                                $this->conservativeness = 0;
                        } else if ($retval == "+") {
-                               $this->outhtml = '';
-                               $this->mathml = '';
-                               $sql_html = 'NULL';
-                               $sql_mathml = 'NULL';
+                               $this->outhtml = NULL;
+                               $this->mathml = NULL;
                                $this->conservativeness = 0;
                        } else {
                                $errbit = htmlspecialchars( substr($contents, 1) );
@@ -125,13 +116,21 @@ class MathRenderer {
                        }
                        
                        # Now save it back to the DB:
-                       $outmd5_sql = wfStrencode(pack("H32", $this->hash));
+                       $outmd5_sql = pack("H32", $this->hash);
                
-                       $md5_sql = wfStrencode( pack("H32", $this->md5) ); # Binary packed, not hex
-                       $sql = "REPLACE INTO math VALUES ('".$md5_sql."', '".$outmd5_sql."', ".$this->conservativeness.", ".$sql_html.", ".$sql_mathml.")";
+                       $md5_sql = pack("H32", $this->md5); # Binary packed, not hex
+                       
+                       $dbw =& wfGetDB( DB_WRITE );
+                       $dbw->replace( 'math', array( 'math_inputhash' ),
+                         array( 
+                               'math_inputhash' => $md5_sql, 
+                               'math_outputhash' => $outmd5_sql,
+                               'math_html_conservativeness' => $this->conservativeness,
+                               'math_html' => $outhtml,
+                               'math_mathml' => $mathml,
+                         ), $fname, array( 'IGNORE' ) 
+                       );
                        
-                       $res = wfQuery( $sql, DB_WRITE, "MathRenderer::render" );
-                       # we don't really care if it fails
                }
                
                return $this->_doRender();
@@ -147,14 +146,17 @@ class MathRenderer {
        
        function _recall() {
                global $wgMathDirectory;
-               
+               $fname = 'MathRenderer::_recall';
+
                $this->md5 = md5( $this->tex );
-               
-               $md5_sql = wfStrencode( pack("H32", $this->md5) ); # Binary packed, not hex
-               $sql = "SELECT math_outputhash,math_html_conservativeness,math_html,math_mathml FROM math WHERE math_inputhash = '$md5_sql'";
-               $res = wfQuery( $sql, DB_READ, "MathRenderer::_recall" );
-               
-               if( $rpage = wfFetchObject ( $res ) ) {
+               $dbr =& wfGetDB( DB_READ );
+               $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
+                       $fname
+               );
+
+               if( $rpage !== false ) {
                        # Tailing 0x20s can get dropped by the database, add it back on if necessary:
                        $xhash = unpack( "H32md5", $rpage->math_outputhash . "                " );
                        $this->hash = $xhash ['md5'];
index 9462a52..a6f00f5 100755 (executable)
@@ -37,6 +37,7 @@ class MessageCache
                global $wgAllMessagesEn;
                
                if ( $this->mDisable ) {
+                       wfDebug( "MessageCache::load(): disabled\n" );
                        return true;
                }
                
@@ -47,6 +48,7 @@ class MessageCache
                        
                        # If there's nothing in memcached, load all the messages from the database
                        if ( !$this->mCache ) {
+                               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 );
@@ -64,6 +66,7 @@ class MessageCache
                        }
                        
                        if ( !is_array( $this->mCache ) ) {
+                               wfMsg( "MessageCache::load(): individual message mode\n" );
                                # If it is 'loading' or 'error', switch to individual message mode, otherwise disable
                                # Causing too much DB load, disabling -- TS 
                                $this->mDisable = true;
@@ -86,18 +89,20 @@ class MessageCache
        # Loads all cacheable messages from the database
        function loadFromDB()
        {
-               global $wgLoadBalancer;
                $fname = "MessageCache::loadFromDB";
-               $wgLoadBalancer->force(-1);
-               $sql = "SELECT cur_title,cur_text FROM cur WHERE cur_is_redirect=0 AND cur_namespace=" . NS_MEDIAWIKI;
-               $res = wfQuery( $sql, DB_READ, $fname );
-               $wgLoadBalancer->force(0);
+               $dbr =& wfGetDB( DB_READ );
+               $res = $dbr->select( 'cur', 
+                       array( 'cur_title', 'cur_text' ), 
+                       array( 'cur_is_redirect' => 0, 'cur_namespace' => NS_MEDIAWIKI ),
+                       $fname
+               );
+               
                $this->mCache = array();
-               for ( $row = wfFetchObject( $res ); $row; $row = wfFetchObject( $res ) ) {
+               for ( $row = $dbr->fetchObject( $res ); $row; $row = $dbr->fetchObject( $res ) ) {
                        $this->mCache[$row->cur_title] = $row->cur_text;
                }
 
-               wfFreeResult( $res );
+               $dbr->freeResult( $res );
        }
        
        # Not really needed anymore
@@ -176,7 +181,8 @@ class MessageCache
                        
                        # If it wasn't in the cache, load each message from the DB individually
                        if ( !$message && $useDB) {
-                               $result = wfGetArray( "cur", array("cur_text"), 
+                               $dbr =& wfGetDB( DB_READ );
+                               $result = $dbr->getArray( "cur", array("cur_text"), 
                                  array( "cur_namespace" => NS_MEDIAWIKI, "cur_title" => $title ),
                                  "MessageCache::get" );
                                if ( $result ) {
index ce511ff..5bcfde7 100644 (file)
@@ -285,16 +285,20 @@ class /* abstract */ SqlBagOStuff extends BagOStuff {
 
 class MediaWikiBagOStuff extends SqlBagOStuff {
        function _doquery($sql) {
-               return wfQuery($sql, DB_READ, "MediaWikiBagOStuff:_doquery");
+               $dbw = wfGetDB( DB_WRITE );
+               return $dbw->query($sql, "MediaWikiBagOStuff:_doquery");
        }
        function _fetchobject($result) {
-               return wfFetchObject($result);
+               $dbw = wfGetDB( DB_WRITE );
+               return $dbw->fetchObject($result);
        }
        function _freeresult($result) {
-               return wfFreeResult($result);
+               $dbw = wfGetDB( DB_WRITE );
+               return $dbw->freeResult($result);
        }
        function _dberror($result) {
-               return wfLastError();
+               $dbw = wfGetDB( DB_WRITE );
+               return $dbw->lastError();
        }
        function _maxdatetime() {
                return "9999-12-31 12:59:59";
@@ -303,7 +307,8 @@ class MediaWikiBagOStuff extends SqlBagOStuff {
                return gmdate( "Y-m-d H:i:s", $ts );
        }
        function _strencode($s) {
-               return wfStrEncode($s);
+               $dbw = wfGetDB( DB_WRITE );
+               return $dbw->strencode($s);
        }
 }
 
index ac75966..5e17bbf 100644 (file)
@@ -307,7 +307,7 @@ class OutputPage {
        {
                global $wgUser, $wgLang, $wgDebugComments, $wgCookieExpiration;
                global $wgInputEncoding, $wgOutputEncoding, $wgLanguageCode;
-               global $wgDebugRedirects, $wgMimeType, $wgProfiling;
+               global $wgDebugRedirects, $wgMimeType, $wgProfiler;
                if( $this->mDoNothing ){
                        return;
                }
index 3eeaa9d..adc4790 100644 (file)
@@ -17,7 +17,7 @@ class PageHistory {
 
        function history()
        {
-               global $wgUser, $wgOut, $wgLang, $wgIsMySQL, $wgIsPg;
+               global $wgUser, $wgOut, $wgLang;
 
                # If page hasn't changed, client can cache this
                
@@ -54,17 +54,20 @@ class PageHistory {
                
                $namespace = $this->mTitle->getNamespace();
                $title = $this->mTitle->getText();
-               $use_index=$wgIsMySQL?"USE INDEX (name_title_timestamp)":"";
-               $oldtable=$wgIsPg?'"old"':'old';
+               
+               $db =& wfGetDB( DB_READ );
+               $use_index = $db->useIndexClause( 'name_title_timestamp' );
+               $oldtable = $db->tableName( 'old' );
+
                $sql = "SELECT old_id,old_user," .
                  "old_comment,old_user_text,old_timestamp,old_minor_edit ".
                  "FROM $oldtable $use_index " .
                  "WHERE old_namespace={$namespace} AND " .
-                 "old_title='" . wfStrencode( $this->mTitle->getDBkey() ) . "' " .
+                 "old_title='" . $db->strencode( $this->mTitle->getDBkey() ) . "' " .
                  "ORDER BY inverse_timestamp".wfLimitResult($limitplus,$rawoffset);
-               $res = wfQuery( $sql, DB_READ, $fname );
+               $res = $db->query( $sql, $fname );
 
-               $revs = wfNumRows( $res );
+               $revs = $db->numRows( $res );
                
                if( $revs < $limitplus ) // the sql above tries to fetch one extra
                        $this->linesonpage = $revs;
@@ -98,7 +101,7 @@ class PageHistory {
                                $counter++
                        );
                }
-               while ( $line = wfFetchObject( $res ) ) {
+               while ( $line = $db->fetchObject( $res ) ) {
                        $s .= $this->historyLine( 
                                $line->old_timestamp, $line->old_user,
                                $line->old_user_text, $namespace,
index 8a24bf1..53a5bcd 100644 (file)
@@ -343,6 +343,8 @@ class Parser
        # This method generates the list of subcategories and pages for a category
        function oldCategoryMagic () {
                global $wgLang , $wgUser ;
+               $fname = 'Parser::oldCategoryMagic';
+
                if ( !$this->mOptions->getUseCategoryMagic() ) return ; # Doesn't use categories at all
 
                $cns = Namespace::getCategory() ;
@@ -359,10 +361,15 @@ class Parser
                $id = $this->mTitle->getArticleID() ;
 
                # FIXME: add limits
-               $t = wfStrencode( $this->mTitle->getDBKey() );
-               $sql = "SELECT DISTINCT cur_title,cur_namespace FROM cur,categorylinks WHERE cl_to='$t' AND cl_from=cur_id ORDER BY cl_sortkey" ;
-               $res = wfQuery ( $sql, DB_READ ) ;
-               while ( $x = wfFetchObject ( $res ) ) $data[] = $x ;
+               $dbr =& wfGetDB( DB_READ );
+               $cur = $dbr->tableName( 'cur' );
+               $categorylinks = $dbr->tableName( 'categorylinks' );
+
+               $t = $dbr->strencode( $this->mTitle->getDBKey() );
+               $sql = "SELECT DISTINCT cur_title,cur_namespace FROM $cur,$categorylinks " .
+                       "WHERE cl_to='$t' AND cl_from=cur_id ORDER BY cl_sortkey" ;
+               $res = $dbr->query( $sql, $fname ) ;
+               while ( $x = $dbr->fetchObject ( $res ) ) $data[] = $x ;
 
                # For all pages that link to this category
                foreach ( $data AS $x )
@@ -377,7 +384,7 @@ class Parser
                                array_push ( $articles , $sk->makeLink ( $t ) ) ; # Page in this category
                        }
                }
-               wfFreeResult ( $res ) ;
+               $dbr->freeResult ( $res ) ;
 
                # Showing subcategories
                if ( count ( $children ) > 0 ) {
@@ -393,7 +400,6 @@ class Parser
                        $r .= implode ( ', ' , $articles ) ;
                }
 
-
                return $r ;
        }
 
@@ -419,12 +425,15 @@ class Parser
                $id = $this->mTitle->getArticleID() ;
 
                # FIXME: add limits
-               $t = wfStrencode( $this->mTitle->getDBKey() );
-               $sql = "SELECT DISTINCT cur_title,cur_namespace,cl_sortkey FROM 
-cur,categorylinks WHERE cl_to='$t' AND cl_from=cur_id ORDER BY 
-cl_sortkey" ;
-               $res = wfQuery ( $sql, DB_READ ) ;
-               while ( $x = wfFetchObject ( $res ) )
+               $dbr =& wfGetDB( DB_READ );
+               $cur = $dbr->tableName( 'cur' );
+               $categorylinks = $dbr->tableName( 'categorylinks' );
+               
+               $t = $dbr->strencode( $this->mTitle->getDBKey() );
+               $sql = "SELECT DISTINCT cur_title,cur_namespace,cl_sortkey FROM " .
+                       "$cur,$categorylinks WHERE cl_to='$t' AND cl_from=cur_id ORDER BY cl_sortkey" ;
+               $res = $dbr->query ( $sql ) ;
+               while ( $x = $dbr->fetchObject ( $res ) )
                {
                        $t = $ns = $wgLang->getNsText ( $x->cur_namespace ) ;
                        if ( $t != '' ) $t .= ':' ;
@@ -448,7 +457,7 @@ cl_sortkey" ;
                                array_push ( $articles_start_char, $wgLang->firstChar( $x->cl_sortkey ) ) ;
                        }
                }
-               wfFreeResult ( $res ) ;
+               $dbr->freeResult ( $res ) ;
 
                $ti = $this->mTitle->getText() ;
 
@@ -665,6 +674,9 @@ cl_sortkey" ;
 
        # parse the wiki syntax used to render tables
        function doTableStuff ( $t ) {
+               $fname = 'Parser::doTableStuff';
+               wfProfileIn( $fname );
+               
                $t = explode ( "\n" , $t ) ;
                $td = array () ; # Is currently a td tag open?
                        $ltd = array () ; # Was it TD or TH?
@@ -760,6 +772,7 @@ cl_sortkey" ;
 
                $t = implode ( "\n" , $t ) ;
                #               $t = $this->removeHTMLtags( $t );
+               wfProfileOut( $fname );
                return $t ;
        }
 
@@ -2025,9 +2038,14 @@ cl_sortkey" ;
        # Return an HTML link for the "ISBN 123456" text
        /* private */ function magicISBN( $text ) {
                global $wgLang;
+               $fname = 'Parser::magicISBN';
+               wfProfileIn( $fname );
 
                $a = split( 'ISBN ', " $text" );
-               if ( count ( $a ) < 2 ) return $text;
+               if ( count ( $a ) < 2 ) {
+                       wfProfileOut( $fname );
+                       return $text;
+               }
                $text = substr( array_shift( $a ), 1);
                $valid = '0123456789-ABCDEFGHIJKLMNOPQRSTUVWXYZ';
 
@@ -2054,6 +2072,7 @@ cl_sortkey" ;
                                $text .= $x;
                        }
                }
+               wfProfileOut( $fname );
                return $text;
        }
        
index ed58bf0..e27c766 100755 (executable)
@@ -40,7 +40,7 @@ class Profiler
        {
                global $wgDebugFunctionEntry;
                if ( $wgDebugFunctionEntry && function_exists( "wfDebug" ) ) {
-                       wfDebug( "Entering $functionname\n" );
+                       wfDebug( str_repeat( " ", count( $this->mWorkStack ) ) . "Entering $functionname\n" );
                }
                array_push( $this->mWorkStack, array($functionname, count( $this->mWorkStack ), microtime() ) );
        }
@@ -50,7 +50,7 @@ class Profiler
                global $wgDebugProfiling, $wgDebugFunctionEntry;
 
                if ( $wgDebugFunctionEntry && function_exists( "wfDebug" ) ) {
-                       wfDebug( "Exiting $functionname\n" );
+                       wfDebug( str_repeat( " ", count( $this->mWorkStack ) - 1 ) . "Exiting $functionname\n" );
                }
                
                $bit = array_pop( $this->mWorkStack );
@@ -77,8 +77,11 @@ class Profiler
                }
        }
 
-       function getOutput( $scriptStart, $scriptElapsed )
+       function getOutput()
        {
+               global $wgDebugFunctionEntry;
+               $wgDebugFunctionEntry = false;
+
                if( !count( $this->mStack ) ) {
                        return "No profiling output\n";
                }
@@ -148,19 +151,21 @@ class Profiler
 
        /* static */ function logToDB($name, $timeSum, $eventCount) 
        {
-               $name = wfStrencode( $name );
-               $sql = "UPDATE profiling ".
+               $dbw =& wfGetDB( DB_WRITE );
+               $profiling = $dbw->tableName( 'profiling' );
+
+               $name = $dbw->strencode( $name );
+               $sql = "UPDATE $profiling ".
                        "SET pf_count=pf_count+{$eventCount}, ".
                        "pf_time=pf_time + {$timeSum} ".
                        "WHERE pf_name='{$name}'";
-               wfQuery($sql , DB_WRITE);
+               $dbw->query($sql);
 
-               $rc = wfAffectedRows(); 
+               $rc = $dbw->affectedRows();     
                if( $rc == 0) {
-                       $sql = "INSERT IGNORE INTO profiling (pf_name,pf_count,pf_time) ".
+                       $sql = "INSERT IGNORE INTO $profiling (pf_name,pf_count,pf_time) ".
                                "VALUES ('{$name}', {$eventCount}, {$timeSum}) ";
-                       wfQuery($sql , DB_WRITE);
-                       $rc = wfAffectedRows();    
+                       $dbw->query($sql , DB_WRITE);
                }
                // When we upgrade to mysql 4.1, the insert+update
                // can be merged into just a insert with this construct added:
index 43804ce..77a5532 100644 (file)
@@ -65,38 +65,67 @@ class QueryPage {
 
                $sname = $this->getName();
                $fname = get_class($this) . "::doQuery";
-               $sql = $this->getSQL( $offset, $limit );
+               $sql = $this->getSQL();
+               $dbr =& wfGetDB( DB_READ );
+               $dbw =& wfGetDB( DB_WRITE );
+               $querycache = $dbr->tableName( 'querycache' );
 
                $wgOut->setSyndicated( true );
+               $res = false;
                
                if ( $this->isExpensive() ) {
-                       $type = wfStrencode( $sname );
                        $recache = $wgRequest->getBool( "recache" );
                        if( $recache ) {
                                # Clear out any old cached data
-                               $res = wfQuery( "DELETE FROM querycache WHERE qc_type='$type'", DB_WRITE, $fname );
-
-                               # Save results into the querycache table
+                               $dbw->delete( 'querycache', array( 'qc_type' => $sname ), $fname );
+                               
+                               # Do query on the (possibly out of date) slave server
                                $maxstored = 1000;
-                               $res = wfQuery(
-                                       "INSERT INTO querycache(qc_type,qc_namespace,qc_title,qc_value) " .
-                                       $this->getSQL() .
-                                       $this->getOrderLimit( 0, $maxstored ),
-                                       DB_WRITE, $fname );
+                               $res = $dbr->query( $sql . $this->getOrderLimit( 0, $maxstored ), $fname );
+                               
+                               # Fetch results
+                               $insertSql = "INSERT INTO $querycache (qc_type,qc_namespace,qc_title,qc_value) VALUES ";
+                               $first = true;
+                               while ( $row = $dbr->fetchObject( $res ) ) {
+                                       if ( $first ) {
+                                               $first = false;
+                                       } else {
+                                               $insertSql .= ",";
+                                       } 
+                                       $insertSql .= "(" .
+                                               $dbw->addQuotes( $row->type ) . "," .
+                                               $dbw->addQuotes( $row->namespace ) . "," .
+                                               $dbw->addQuotes( $row->title ) . "," .
+                                               $dbw->addQuotes( $row->value ) . ")"
+                               }
+
+                               # Save results into the querycache table on the master
+                               $dbw->query( $insertSql, $fname );
+
+                               # Set result pointer to allow reading for display
+                               $numRows = $dbr->numRows( $res );
+                               if ( $numRows <= $offset ) {
+                                       $num = 0;
+                               } else {
+                                       $dbr->dataSeek( $res, $offset );
+                                       $num = max( $limit, $numRows - $offset );
+                               }
                        }
                        if( $wgMiserMode || $recache ) {
+                               $type = $dbr->strencdode( $sname );
                                $sql =
                                        "SELECT qc_type as type, qc_namespace as namespace,qc_title as title, qc_value as value
-                                        FROM querycache WHERE qc_type='$type'";
+                                        FROM $querycache WHERE qc_type='$type'";
                        }
                        if( $wgMiserMode ) {
                                $wgOut->addWikiText( wfMsg( "perfcached" ) );
                        }
                }
-
-               $res = wfQuery( $sql . $this->getOrderLimit( $offset, $limit ), DB_READ, $fname );
+               if ( $res === false ) {
+                       $res = $dbr->query( $sql . $this->getOrderLimit( $offset, $limit ), $fname );
+                       $num = $dbr->numRows($res);
+               }
                
-               $num = wfNumRows($res);
                
                $sk = $wgUser->getSkin( );
 
@@ -110,11 +139,12 @@ class QueryPage {
                $wgOut->addHTML( "<br />{$sl}</p>\n" );
 
                $s = "<ol start='" . ( $offset + 1 ) . "'>";
-               while ( $obj = wfFetchObject( $res ) ) {
+               # Only read at most $num rows, because $res may contain the whole 1000
+               for ( $i = 0; $i < $num && $obj = $dbr->fetchObject( $res ); $i++ ) {
                        $format = $this->formatResult( $sk, $obj );
                        $s .= "<li>{$format}</li>\n";
                }
-               wfFreeResult( $res );
+               $dbr->freeResult( $res );
                $s .= "</ol>";
                $wgOut->addHTML( $s );
                $wgOut->addHTML( "<p>{$sl}</p>\n" );
@@ -131,13 +161,14 @@ class QueryPage {
                                $this->feedUrl() );
                        $feed->outHeader();
                        
-                       $sql = $this->getSQL( 0, 50 );
-                       $res = wfQuery( $sql, DB_READ, "QueryPage::doFeed" );
-                       while( $obj = wfFetchObject( $res ) ) {
+                       $dbr = wfGetDB( DB_READ );
+                       $sql = $this->getSQL() . $this->getOrderLimit( 0, 50 );
+                       $res = $dbr->query( $sql, "QueryPage::doFeed" );
+                       while( $obj = $dbr->fetchObject( $res ) ) {
                                $item = $this->feedResult( $obj );
                                if( $item ) $feed->outItem( $item );
                        }
-                       wfFreeResult( $res );
+                       $dbr->freeResult( $res );
 
                        $feed->outFooter();
                        return true;
index 003ab45..9179a5e 100644 (file)
@@ -56,13 +56,16 @@ class RawPage {
                } else {
                        echo $this->getrawtext();
                }
-               wfAbruptExit();
+               $wgOut->disable();
        }
        
        function getrawtext () {
-               global $wgInputEncoding, $wgLang, $wgIsPg;
+               global $wgInputEncoding, $wgLang;
+               $fname = 'RawPage::getrawtext';
+               
                if( !$this->mTitle ) return '';
-               $t = wfStrencode( $this->mTitle->getDBKey() );
+               $dbr = wfGetDB( DB_READ );
+               $t = $dbr->strencode( $this->mTitle->getDBKey() );
                $ns = $this->mTitle->getNamespace();
                # special case
                if($ns == NS_MEDIAWIKI) {
@@ -73,7 +76,7 @@ class RawPage {
                }
                # else get it from the DB
                if(!empty($this->mOldId)) {
-                       $oldtable=$wgIsPg?'"old"':'old';
+                       $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 " .
                        "WHERE old_id={$this->mOldId}";
@@ -82,8 +85,8 @@ class RawPage {
                        "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 ) ) {
+               $res = $dbr->query( $sql, $fname );
+               if( $s = $dbr->fetchObject( $res ) ) {
                        $rawtext = Article::getRevisionText( $s, "" );
                        if($wgInputEncoding != $this->mCharset)
                        $rawtext = $wgLang->iconv( $wgInputEncoding, $this->mCharset, $rawtext );
index ff17c89..bb2ed08 100644 (file)
@@ -157,21 +157,17 @@ class SearchEngine {
        {
                global $wgUser, $wgTitle, $wgOut, $wgLang, $wgRequest;
                global $wgDisableTextSearch, $wgInputEncoding;
-               global $wgLoadBalancer;
-                               
-                $wgLoadBalancer->force(-1);
-
-                $fname = "SearchEngine::showResults";
+               $fname = "SearchEngine::showResults";
 
                $search = $wgRequest->getText( 'search' );
 
                $powersearch = $this->powersearch(); /* Need side-effects here? */
 
                $this->setupPage();
-               
+
                $sk = $wgUser->getSkin();
                $header = wfMsg( "searchresulttext", $sk->makeKnownLink(
-                 wfMsg( "searchhelppage" ), wfMsg( "searchingwikipedia" ) ) );
+                                       wfMsg( "searchhelppage" ), wfMsg( "searchingwikipedia" ) ) );
                $wgOut->addHTML( $header );
 
                $this->parseQuery();
@@ -284,8 +280,7 @@ class SearchEngine {
                        $wgOut->addHTML( "<p>{$sl}</p>\n" );
                        $wgOut->addHTML( $powersearch );
                }
-               $wgLoadBalancer->force(0);
-        }
+       }
 
        function legalSearchChars()
        {
index c7b9c61..55bad79 100644 (file)
@@ -25,19 +25,21 @@ class SearchUpdate {
 
        function doUpdate()
        {
-               global $wgDBminWordLen, $wgLang, $wgDisableSearchUpdate, $wgIsMySQL;
+               global $wgDBminWordLen, $wgLang, $wgDisableSearchUpdate;
 
                if( $wgDisableSearchUpdate || !$this->mId ) {
                        return false;
                }
                $lc = SearchEngine::legalSearchChars() . "&#;";
+               $db =& wfGetDB( DB_WRITE );
+               
                if( $this->mText == false ) {
                        # Just update the title
-                       $lowpri=$wgIsMySQL?"LOW_PRIORITY":"";
+                       $lowpri = $db->lowPriorityOption();
                        $sql = "UPDATE $lowpri searchindex SET si_title='" .
                          wfStrencode( Title::indexTitle( $this->mNamespace, $this->mTitle ) ) .
                          "' WHERE si_page={$this->mId}";
-                       wfQuery( $sql, DB_WRITE, "SearchUpdate::doUpdate" );
+                       $db->query( $sql, "SearchUpdate::doUpdate" );
                        return;
                }
 
@@ -80,7 +82,7 @@ class SearchUpdate {
                $sql = "REPLACE  INTO searchindex (si_page,si_title,si_text) VALUES ({$this->mId},'" .
                  wfStrencode( Title::indexTitle( $this->mNamespace, $this->mTitle ) ) . "','" .
                  wfStrencode( $text ) . "')";
-               wfQuery( $sql, DB_WRITE, "SearchUpdate::doUpdate" );
+               $db->query( $sql, "SearchUpdate::doUpdate" );
        }
 }
 
index 21d5ef3..90be866 100644 (file)
@@ -70,9 +70,10 @@ global $wgUser, $wgLang, $wgOut, $wgTitle;
 global $wgArticle, $wgDeferredUpdateList, $wgLinkCache;
 global $wgMemc, $wgMagicWords, $wgMwRedir, $wgDebugLogFile;
 global $wgMessageCache, $wgUseMemCached, $wgUseDatabaseMessages;
-global $wgMsgCacheExpiry, $wgDBname, $wgCommandLineMode;
+global $wgMsgCacheExpiry, $wgCommandLineMode;
 global $wgBlockCache, $wgParserCache, $wgParser, $wgDBConnections;
-global $wgLoadBalancer, $wgDBservers, $wgDBloads, $wgDBuser, $wgDBpassword;
+global $wgLoadBalancer, $wgDBservers;
+global $wgDBserver, $wgDBuser, $wgDBpassword, $wgDBname, $wgDBtype;
 
 # Useful debug output
 if ( $wgCommandLineMode ) {
@@ -146,10 +147,16 @@ wfProfileOut( $fname.'-memcached' );
 wfProfileIn( $fname.'-database' );
 
 if ( !$wgDBservers ) {
-       $wgDBservers = array( $wgDBserver );
-       $wgDBloads = array( 1 );
+       $wgDBservers = array(array( 
+               'host' => $wgDBserver,
+               'user' => $wgDBuser,
+               'password' => $wgDBpassword,
+               'dbname' => $wgDBname,
+               'type' => $wgDBtype,
+               'load' => 1
+       ));
 }
-$wgLoadBalancer = LoadBalancer::newFromParams( $wgDBservers, $wgDBloads, $wgDBuser, $wgDBpassword, $wgDBname );
+$wgLoadBalancer = LoadBalancer::newFromParams( $wgDBservers );
 $wgLoadBalancer->force(0);
 
 wfProfileOut( $fname.'-database' );
index 900956b..f8a6bb5 100644 (file)
@@ -15,7 +15,6 @@ class SiteStatsUpdate {
 
        function doUpdate()
        {
-               global $wgIsMySQL;
                $a = array();
 
                if ( $this->mViews < 0 ) { $m = "-1"; }
@@ -32,10 +31,12 @@ class SiteStatsUpdate {
                else if ( $this->mGood > 0 ) { $m = "+1"; }
                else $m = "";
                array_push( $a, "ss_good_articles=(ss_good_articles$m)" );
-               $lowpri=$wgIsMySQL?"LOW_PRIORITY":"";
+
+               $db =& wfGetDB( DB_WRITE );
+               $lowpri = $db->lowPriorityOption();
                $sql = "UPDATE $lowpri site_stats SET " . implode ( ",", $a ) .
                  " WHERE ss_row_id=1";
-               wfQuery( $sql, DB_WRITE, "SiteStatsUpdate::doUpdate" );
+               $db->query( $sql, "SiteStatsUpdate::doUpdate" );
        }
 }
 
index c3dd2e6..e739e97 100644 (file)
@@ -1440,7 +1440,9 @@ class Skin {
        # Pass a title object, not a title string
        function makeLinkObj( &$nt, $text= '', $query = '', $trail = '', $prefix = '' )
        {
-               global $wgOut, $wgUser, $wgLoadBalancer;
+               global $wgOut, $wgUser;
+               $fname = 'Skin::makeLinkObj';
+
                if ( $nt->isExternal() ) {
                        $u = $nt->getFullURL();
                        $link = $nt->getPrefixedURL();
@@ -1467,16 +1469,17 @@ class Skin {
                        } else {
                                $threshold = $wgUser->getOption('stubthreshold') ;
                                if ( $threshold > 0 ) {
-                                       $wgLoadBalancer->force(-1);
-                                       $res = wfQuery ( "SELECT LENGTH(cur_text) AS x, cur_namespace, cur_is_redirect FROM cur WHERE cur_id='{$aid}'", DB_READ ) ;
-                                       $wgLoadBalancer->force(0);
-                                       if ( wfNumRows( $res ) > 0 ) {
-                                               $s = wfFetchObject( $res );
+                                       $s = $dbr->getArray( '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
                                                }
-                                               wfFreeResult( $res );
                                        } else {
                                                $size = $threshold*2 ; # Really big
                                        }
index 2a098c3..b7bb276 100644 (file)
@@ -43,7 +43,9 @@
                        // interpolate variables
                        while (preg_match('/\$([0-9]*?)/sm', $value, $m)) {
                                list($src, $var) = $m;
-                               $varValue = @$this->_context[$var];
+                               wfSuppressWarnings();
+                               $varValue = $this->_context[$var];
+                               wfRestoreWarnings();
                                $value = str_replace($src, $varValue, $value);
                        }
                        return $value;
index 1cdeaa7..27b2b3b 100644 (file)
@@ -2,12 +2,10 @@
 
 function wfSpecialAllpages( $par=NULL )
 {
-       global $indexMaxperpage, $wgRequest, $wgLoadBalancer;
+       global $indexMaxperpage, $wgRequest;
        $indexMaxperpage = 480;
        $from = $wgRequest->getVal( 'from' );
        
-       $wgLoadBalancer->force(-1);
-
        if( $par ) {
                indexShowChunk( $par );
        } elseif( !is_null( $from ) ) {
@@ -15,8 +13,6 @@ function wfSpecialAllpages( $par=NULL )
        } else {
                indexShowToplevel();
        }
-
-       $wgLoadBalancer->force(0);
 }
 
 function indexShowToplevel()
index 3aa93a5..69d2d43 100644 (file)
@@ -13,8 +13,8 @@ class AncientPagesPage extends QueryPage {
        }
 
        function getSQL() {
-               global $wgIsMySQL;
-               $use_index=$wgIsMySQL?"USE INDEX (cur_timestamp)":"";
+               $db = wfGetDB( DB_READ );
+               $use_index = $db->useIndexClause( 'cur_timestamp' );
                return
                        "SELECT 'Ancientpages' as type,
                                        cur_namespace as namespace,
index 0dcd5eb..5fd831a 100644 (file)
@@ -2,7 +2,7 @@
 
 function wfSpecialContributions( $par = "" )
 {
-       global $wgUser, $wgOut, $wgLang, $wgRequest, $wgIsPg;
+       global $wgUser, $wgOut, $wgLang, $wgRequest;
        $fname = "wfSpecialContributions";
        $sysop = $wgUser->isSysop();
 
@@ -65,7 +65,7 @@ function wfSpecialContributions( $par = "" )
                  "&offset={$offset}&limit={$limit}&hideminor=1" );
        }
 
-       $oldtable=$wgIsPg?'"old"':'old';
+       $oldtable = wfTableName( 'old', DB_READ );
        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} " .
index 8518c43..ba5a579 100644 (file)
@@ -16,8 +16,7 @@ class ListAdminsPage extends PageQueryPage {
        }
 
        function getSQL() {
-               global $wgIsPg;
-               $usertable = $wgIsPg?'"user"':'user';
+               $usertable = wfTableName( 'user' );
                $userspace = Namespace::getUser();
                return 'SELECT user_rights as type,'.$userspace.' as namespace,'.
                       'user_name as title, user_name as value '.
index e74f2a2..5a317f2 100644 (file)
@@ -13,8 +13,7 @@ class ListUsersPage extends QueryPage {
        }
 
        function getSQL() {
-               global $wgIsPg;
-               $usertable = $wgIsPg?'"user"':'user';
+               $usertable = wfTableName( 'user', DB_READ );
                $userspace = Namespace::getUser();
                return "SELECT user_rights as type, $userspace as namespace, user_name as title, user_name as value FROM $usertable";
        }
@@ -36,7 +35,7 @@ class ListUsersPage extends QueryPage {
 }
 
 function wfSpecialListusers() {
-       global $wgUser, $wgOut, $wgLang, $wgIsPg;
+       global $wgUser, $wgOut, $wgLang;
 
        list( $limit, $offset ) = wfCheckLimits();
 
index 3b16d6a..6e3f2d0 100644 (file)
@@ -10,46 +10,27 @@ function sns()
 function wfSpecialMaintenance( $par=NULL )
 {
        global $wgUser, $wgOut, $wgLang, $wgTitle, $wgRequest, $wgLanguageCode;
-       global $wgMiserMode, $wgLoadBalancer;
+       global $wgMiserMode;
 
        if ( $wgMiserMode ) {
                $wgOut->addWikiText( wfMsg( "perfdisabled" ) );
                return;
        }
        
-       $wgLoadBalancer->force(-1);
-
        $submitmll = $wgRequest->getVal( 'submitmll' );
-       
+
        if( $par )
                $subfunction = $par;
        else
                $subfunction = $wgRequest->getText( 'subfunction' );
 
-       $done = true;
-
-       if ( $subfunction == "disambiguations" ) {
-               wfSpecialDisambiguations() ;
-       } elseif ( $subfunction == "doubleredirects" ) {
-               wfSpecialDoubleRedirects() ;
-       } elseif ( $subfunction == "brokenredirects" ) {
-               wfSpecialBrokenRedirects() ;
-       } elseif ( $subfunction == "selflinks" ) {
-               wfSpecialSelfLinks() ;
-       } elseif ( $subfunction == "mispeelings" ) {
-               wfSpecialMispeelings() ;
-       } elseif ( $subfunction == "missinglanguagelinks" ) {
-          wfSpecialMissingLanguageLinks() ;
-       } elseif ( !is_null( $submitmll ) ) {
-               wfSpecialMissingLanguageLinks() ;
-       } else {
-               $done = false;
-       }
-       
-       $wgLoadBalancer->force(0);
-       if ( $done ) {
-               return;
-       }
+       if ( $subfunction == "disambiguations" ) return wfSpecialDisambiguations() ;
+       if ( $subfunction == "doubleredirects" ) return wfSpecialDoubleRedirects() ;
+       if ( $subfunction == "brokenredirects" ) return wfSpecialBrokenRedirects() ;
+       if ( $subfunction == "selflinks" ) return wfSpecialSelfLinks() ;
+       if ( $subfunction == "mispeelings" ) return wfSpecialMispeelings() ;
+       if ( $subfunction == "missinglanguagelinks" ) return wfSpecialMissingLanguageLinks() ;
+       if ( !is_null( $submitmll ) ) return wfSpecialMissingLanguageLinks() ;
 
        $sk = $wgUser->getSkin();
        $ns = $wgLang->getNamespaces() ;
@@ -59,7 +40,7 @@ function wfSpecialMaintenance( $par=NULL )
        $r .= "<li>".getMPL("doubleredirects")."</li>\n" ;
        $r .= "<li>".getMPL("brokenredirects")."</li>\n" ;
        $r .= "<li>".getMPL("selflinks")."</li>\n" ;
-        $r .= "<li>".getMPL("mispeelings")."</li>\n" ;
+       $r .= "<li>".getMPL("mispeelings")."</li>\n" ;
 
        $r .= "<li>";
        $l = getMPL("missinglanguagelinks");
@@ -77,7 +58,7 @@ function wfSpecialMaintenance( $par=NULL )
        foreach ( $ak AS $k ) {
                if ( $k != $wgLanguageCode )
                        $r .= "<option value='{$k}'>{$a[$k]}</option>\n" ;
-               }
+       }
        $r .= "</select>\n" ;
        $r .= "</FORM>\n</li>" ;
 
@@ -278,69 +259,69 @@ function wfSpecialSelfLinks()
 
 function wfSpecialMispeelings ()
 {
-        global $wgUser, $wgOut, $wgLang, $wgTitle;
-        $sk = $wgUser->getSkin();
-        $fname = "wfSpecialMispeelings";
-
-               list( $limit, $offset ) = wfCheckLimits();
-
-        # Determine page name
-        $ms = wfMsg ( "mispeelingspage" ) ;
-        $mss = wfStrencode( 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 = explode ( "\n" , $l ) ;
-        $a = array () ;
-        foreach ( $l as $x )
-                if ( substr ( trim ( $x ) , 0 , 1 ) == "*" )
-                        $a[] = strtolower ( trim ( substr ( trim ( $x ) , 1 ) ) );
-        asort ( $a ) ;
-
-        $cnt = 0 ;
-        $b = array () ;
-        foreach ( $a AS $x ) {
-                if ( $cnt < $offset+$limit && $x != "" ) {
-                        $y = $x ;
-                        $x = preg_replace( '/^(\S+).*$/', '$1', $x );
+       global $wgUser, $wgOut, $wgLang, $wgTitle;
+       $sk = $wgUser->getSkin();
+       $fname = "wfSpecialMispeelings";
+
+       list( $limit, $offset ) = wfCheckLimits();
+
+       # Determine page name
+       $ms = wfMsg ( "mispeelingspage" ) ;
+       $mss = wfStrencode( 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 = explode ( "\n" , $l ) ;
+       $a = array () ;
+       foreach ( $l as $x )
+               if ( substr ( trim ( $x ) , 0 , 1 ) == "*" )
+                       $a[] = strtolower ( trim ( substr ( trim ( $x ) , 1 ) ) );
+       asort ( $a ) ;
+
+       $cnt = 0 ;
+       $b = array () ;
+       foreach ( $a AS $x ) {
+               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 ) ) {
-                                if ( $cnt >= $offset AND $cnt < $offset+$limit ) {
-                                        if ( $y != "" ) {
-                                                if ( count ( $b ) > 0 ) $b[] = "</OL>\n" ;
-                                                $b[] = "<H3>{$y}</H3>\n<OL start=".($cnt+1).">\n" ;
-                                                $y = "" ;
-                                                }
-                                        $b[] = "<li>".
-                                                $sk->makeKnownLink ( $obj->cur_title ).
-                                                " (".
-                                                $sk->makeBrokenLink ( $obj->cur_title , wfMsg ( "qbedit" ) ).
-                                                ")</li>\n" ;
-                                        }
-                                $cnt++ ;
-                                }
-                        }
-                }
-        $top = getMaintenancePageBacklink( "mispeelings" );
-        $top .= "<p>".wfMsg( "mispeelingstext", $msl )."</p><br>\n";
-        $top .= wfShowingResults( $offset, $limit );
-        $wgOut->addHTML( "<p>{$top}\n" );
-
-        $sl = wfViewPrevNext( $offset, $limit, "REPLACETHIS" ) ;
-        $sl = str_replace ( "REPLACETHIS" , sns().":Maintenance&subfunction=mispeelings" , $sl ) ;
-        $wgOut->addHTML( "<br>{$sl}\n" );
-
-        $s = implode ( "" , $b ) ;
-        if ( count ( $b ) > 0 ) $s .= "</ol>";
-        $wgOut->addHTML( $s );
-        $wgOut->addHTML( "<p>{$sl}\n" );
+                       $res = wfQuery( $sql, DB_READ, $fname );
+                       while ( $obj = wfFetchObject ( $res ) ) {
+                               if ( $cnt >= $offset AND $cnt < $offset+$limit ) {
+                                       if ( $y != "" ) {
+                                               if ( count ( $b ) > 0 ) $b[] = "</OL>\n" ;
+                                               $b[] = "<H3>{$y}</H3>\n<OL start=".($cnt+1).">\n" ;
+                                               $y = "" ;
+                                       }
+                                       $b[] = "<li>".
+                                               $sk->makeKnownLink ( $obj->cur_title ).
+                                               " (".
+                                               $sk->makeBrokenLink ( $obj->cur_title , wfMsg ( "qbedit" ) ).
+                                               ")</li>\n" ;
+                               }
+                               $cnt++ ;
+                       }
+               }
+       }
+       $top = getMaintenancePageBacklink( "mispeelings" );
+       $top .= "<p>".wfMsg( "mispeelingstext", $msl )."</p><br>\n";
+       $top .= wfShowingResults( $offset, $limit );
+       $wgOut->addHTML( "<p>{$top}\n" );
+
+       $sl = wfViewPrevNext( $offset, $limit, "REPLACETHIS" ) ;
+       $sl = str_replace ( "REPLACETHIS" , sns().":Maintenance&subfunction=mispeelings" , $sl ) ;
+       $wgOut->addHTML( "<br>{$sl}\n" );
+
+       $s = implode ( "" , $b ) ;
+       if ( count ( $b ) > 0 ) $s .= "</ol>";
+       $wgOut->addHTML( $s );
+       $wgOut->addHTML( "<p>{$sl}\n" );
 }
 
 
index 77940e9..095bb7f 100644 (file)
@@ -14,7 +14,7 @@ class NewPagesPage extends QueryPage {
                #return parent::isExpensive();
        }
 
-       function getSQL( $offset, $limit ) {
+       function getSQL() {
                return
                        "SELECT 'Newpages' as type,
                                rc_namespace AS namespace,
index c795670..0dd4b60 100644 (file)
@@ -3,14 +3,15 @@
 
 function wfSpecialRandompage()
 {
-       global $wgOut, $wgTitle, $wgArticle, $wgIsMySQL, $wgExtraRandompageSQL;
+       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, ".", "" );
-       $use_index=$wgIsMySQL?"USE INDEX (cur_random)":"";
+       $db =& wfGetDB( DB_READ );
+       $use_index = $db->useIndexClause( 'cur_random' );
        if ( $wgExtraRandompageSQL ) {
                $extra = "AND ($wgExtraRandompageSQL)";
        } else {
@@ -22,8 +23,8 @@ function wfSpecialRandompage()
                AND cur_random>$randstr
                ORDER BY cur_random
                LIMIT 1";
-       $res = wfQuery( $sqlget, DB_READ, $fname );
-       if( $s = wfFetchObject( $res ) ) {
+       $res = $db->query( $sqlget, $fname );
+       if( $s = $db->fetchObject( $res ) ) {
                $rt = wfUrlEncode( $s->cur_title );
        } else {
                # No articles?!
index f53cebc..883ef0f 100644 (file)
@@ -2,22 +2,22 @@
 
 function wfSpecialStatistics()
 {
-       global $wgUser, $wgOut, $wgLang, $wgIsPg, $wgLoadBalancer;
+       global $wgUser, $wgOut, $wgLang;
        $fname = "wfSpecialStatistics";
 
-       $wgLoadBalancer->force(-1);
-
        $wgOut->addHTML( "<h2>" . wfMsg( "sitestats" ) . "</h2>\n" );
+       
+       $db =& wfGetDB( DB_READ );
 
        $sql = "SELECT COUNT(cur_id) AS total FROM cur";
-       $res = wfQuery( $sql, DB_READ, $fname );
-       $row = wfFetchObject( $res );
+       $res = $db->query( $sql, $fname );
+       $row = $db->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 = wfQuery( $sql, DB_READ, $fname );
-       $row = wfFetchObject( $res );
+       $res = $db->query( $sql, $fname );
+       $row = $db->fetchObject( $res );
        $views = $row->ss_total_views;
        $edits = $row->ss_total_edits;
        $good = $row->ss_good_articles;
@@ -33,16 +33,16 @@ function wfSpecialStatistics()
        $wgOut->addWikiText( $text );
        $wgOut->addHTML( "<h2>" . wfMsg( "userstats" ) . "</h2>\n" );
 
-       $usertable=$wgIsPg?'"user"':'user';
+       $usertable = $db->tableName( 'user' );
        $sql = "SELECT COUNT(user_id) AS total FROM $usertable";
-       $res = wfQuery( $sql, DB_READ, $fname );
-       $row = wfFetchObject( $res );
+       $res = $db->query( $sql, $fname );
+       $row = $db->fetchObject( $res );
        $total = $row->total;
 
        $sql = "SELECT COUNT(user_id) AS total FROM $usertable " .
          "WHERE user_rights LIKE '%sysop%'";
-       $res = wfQuery( $sql, DB_READ, $fname );
-       $row = wfFetchObject( $res );
+       $res = $db->query( $sql, $fname );
+       $row = $db->fetchObject( $res );
        $admins = $row->total;
 
        $sk = $wgUser->getSkin();
@@ -53,7 +53,6 @@ function wfSpecialStatistics()
                $wgLang->formatNum( $admins ), $ap );
        $wgOut->addWikiText( $text );
 
-       $wgLoadBalancer->force(0);
 }
 
 ?>
index aece38b..ba93309 100644 (file)
@@ -4,8 +4,8 @@ require_once( "WatchedItem.php" );
 
 function wfSpecialWatchlist()
 {
-       global $wgUser, $wgOut, $wgLang, $wgTitle, $wgMemc, $wgLoadBalancer;
-       global $wgUseWatchlistCache, $wgWLCacheTimeout, $wgDBname, $wgIsMySQL;
+       global $wgUser, $wgOut, $wgLang, $wgTitle, $wgMemc;
+       global $wgUseWatchlistCache, $wgWLCacheTimeout, $wgDBname;
        global $days, $limit, $target; # From query string
        $fname = "wfSpecialWatchlist";
 
@@ -51,19 +51,15 @@ function wfSpecialWatchlist()
                }
        }
        
-       $wgLoadBalancer->force(-1);
        $sql = "SELECT COUNT(*) AS n FROM watchlist WHERE wl_user=$uid";
        $res = wfQuery( $sql, DB_READ );
        $s = wfFetchObject( $res );
        $nitems = $s->n;
-       $wgLoadBalancer->force(0);
        if($nitems == 0) {
         $wgOut->addHTML( wfMsg( "nowatchlist" ) );
         return;
        }
        
-       $wgLoadBalancer->force(-1);
-       
        if ( ! isset( $days ) ) {
                $big = 1000;
                if($nitems > $big) {
@@ -119,7 +115,6 @@ function wfSpecialWatchlist()
                        wfMsg( "removechecked" ) . "' />\n" .
                        "</form>\n" );
                
-               $wgLoadBalancer->force(0);
                return;
        }
        
@@ -145,7 +140,7 @@ function wfSpecialWatchlist()
                $wgLang->formatNum( $nitems ), $wgLang->formatNum( $npages ), $y,
                $specialTitle->escapeLocalUrl( "magic=yes" ) ) . "</i><br />\n" );
         
-       $use_index=$wgIsMySQL?"USE INDEX ($x)":"";
+       $use_index = wfUseIndexClause( $x, DB_READ );
        $sql = "SELECT
   cur_namespace,cur_title,cur_comment, cur_id,
   cur_user,cur_user_text,cur_timestamp,cur_minor_edit,cur_is_new
@@ -171,7 +166,6 @@ function wfSpecialWatchlist()
 
        if ( wfNumRows( $res ) == 0 ) {
                $wgOut->addHTML( "<p><i>" . wfMsg( "watchnochange" ) . "</i></p>" );
-               $wgLoadBalancer->force(0);
                return;
        }
 
@@ -193,7 +187,6 @@ function wfSpecialWatchlist()
                $wgMemc->set( $memckey, $s, $wgWLCacheTimeout);
        }
        
-       $wgLoadBalancer->force(0);
 }
 
 
index 7acdc61..14728c8 100644 (file)
@@ -88,7 +88,7 @@ class Title {
        # From a URL-encoded title
        /* static */ function newFromURL( $url )
        {
-               global $wgLang, $wgServer, $wgIsMySQL, $wgIsPg;
+               global $wgLang, $wgServer;
                $t = new Title();
                
                # For compatibility with old buggy URLs. "+" is not valid in titles,
@@ -109,20 +109,10 @@ class Title {
                
                $t->mDbkeyform = str_replace( " ", "_", $s );
                if( $t->secureAndSplit() ) {
-                       # check that lenght of title is < cur_title size
-                       if ($wgIsMySQL) {
-                               $sql = "SHOW COLUMNS FROM cur LIKE \"cur_title\";";
-                               $cur_title_object = wfFetchObject(wfQuery( $sql, DB_READ ));
-
-                               preg_match( "/\((.*)\)/", $cur_title_object->Type, $cur_title_type);
-                               $cur_title_size=$cur_title_type[1];
-                       } else {
-                               /* midom:FIXME pg_field_type does not return varchar length
-                                  assume 255 */
-                               $cur_title_size=255;
-                       }
-
-                       if (strlen($t->mDbkeyform) > $cur_title_size ) {
+                       # check that length of title is < cur_title size
+                       $dbr =& wfGetDB( DB_READ );
+                       $maxSize = $dbr->textFieldSize( 'cur', 'cur_title' );
+                       if ( $maxSize != -1 && strlen( $t->mDbkeyform ) > $maxSize ) {
                                return NULL;
                        }
 
@@ -138,7 +128,8 @@ class Title {
        /* static */ function newFromID( $id ) 
        {
                $fname = "Title::newFromID";
-               $row = wfGetArray( "cur", array( "cur_namespace", "cur_title" ), 
+               $dbr =& wfGetDB( DB_READ );
+               $row = $dbr->getArray( "cur", array( "cur_namespace", "cur_title" ), 
                        array( "cur_id" => $id ), $fname );
                if ( $row !== false ) {
                        $title = Title::makeTitle( $row->cur_namespace, $row->cur_title );
@@ -172,12 +163,12 @@ class Title {
        # Get the prefixed DB key associated with an ID
        /* static */ function nameOf( $id )
        {
-               $sql = "SELECT cur_namespace,cur_title FROM cur WHERE " .
-                 "cur_id={$id}";
-               $res = wfQuery( $sql, DB_READ, "Article::nameOf" );
-               if ( 0 == wfNumRows( $res ) ) { return NULL; }
+               $fname = 'Title::nameOf';
+               $dbr =& wfGetDB( DB_READ );
+               
+               $s = $dbr->getArray( 'cur', array( 'cur_namespace','cur_title' ),  array( 'cur_id' => $id ), $fname );
+               if ( $s === false ) { return NULL; }
 
-               $s = wfFetchObject( $res );
                $n = Title::makeName( $s->cur_namespace, $s->cur_title );
                return $n;
        }
@@ -244,8 +235,7 @@ class Title {
        function getInterwikiLink( $key )
        {       
                global $wgMemc, $wgDBname, $wgInterwikiExpiry, $wgTitleInterwikiCache;
-                global $wgLoadBalancer;
-                
+               $fname = 'Title::getInterwikiLink';
                $k = "$wgDBname:interwiki:$key";
 
                if( array_key_exists( $k, $wgTitleInterwikiCache ) )
@@ -257,17 +247,16 @@ class Title {
                        $wgTitleInterwikiCache[$k] = $s;
                        return $s->iw_url;
                }
-               $dkey = wfStrencode( $key );
-               $wgLoadBalancer->force(-1);
-                $query = "SELECT iw_url,iw_local FROM interwiki WHERE iw_prefix='$dkey'";
-               $res = wfQuery( $query, DB_READ, "Title::getInterwikiLink" );
-               $wgLoadBalancer->force(0);
+               $dbr =& wfGetDB( DB_READ );
+               $res = $dbr->select( 'interwiki', array( 'iw_url', 'iw_local' ), array( 'iw_prefix' => $key ), $fname );
                 if(!$res) return "";
                
-               $s = wfFetchObject( $res );
+               $s = $dbr->fetchObject( $res );
                if(!$s) {
+                       # Cache non-existence: create a blank object and save it to memcached
                        $s = (object)false;
                        $s->iw_url = "";
+                       $s->iw_local = 0;
                }
                $wgMemc->set( $k, $s, $wgInterwikiExpiry );
                $wgTitleInterwikiCache[$k] = $s;
@@ -296,20 +285,21 @@ class Title {
                if ( $timestamp == "" ) {
                        $timestamp = wfTimestampNow();
                }
-               $sql = "UPDATE cur SET cur_touched='{$timestamp}' WHERE cur_id IN (";
+               $dbw =& wfGetDB( DB_WRITE );
+               $cur = $dbw->tableName( 'cur' );
+               $sql = "UPDATE $cur SET cur_touched='{$timestamp}' WHERE cur_id IN (";
                $first = true;
 
                foreach ( $titles as $title ) {
                        if ( ! $first ) { 
                                $sql .= ","; 
                        }
-
                        $first = false;
                        $sql .= $title->getArticleID();
                }
                $sql .= ")";
                if ( ! $first ) {
-                       wfQuery( $sql, DB_WRITE, "Title::touchArray" );
+                       $dbw->query( $sql, "Title::touchArray" );
                }
        }
 
@@ -568,7 +558,8 @@ class Title {
                if ( 0 == $id ) { return array(); }
 
                if ( ! $this->mRestrictionsLoaded ) {
-                       $res = wfGetSQL( "cur", "cur_restrictions", "cur_id=$id" );
+                       $dbr =& wfGetDB( DB_READ );
+                       $res = $dbr->getField( "cur", "cur_restrictions", "cur_id=$id" );
                        $this->mRestrictions = explode( ",", trim( $res ) );
                        $this->mRestrictionsLoaded = true;
                }
@@ -576,15 +567,13 @@ class Title {
        }
        
        # Is there a version of this page in the deletion archive?
+       # Returns the number of archived revisions
        function isDeleted() {
-               $ns = $this->getNamespace();
-               $t = wfStrencode( $this->getDBkey() );
-               $sql = "SELECT COUNT(*) AS n FROM archive WHERE ar_namespace=$ns AND ar_title='$t'";
-               if( $res = wfQuery( $sql, DB_READ ) ) {
-                       $s = wfFetchObject( $res );
-                       return $s->n;
-               }
-               return 0;
+               $fname = 'Title::isDeleted';
+               $dbr =& wfGetDB( DB_READ );
+               $n = $dbr->getField( 'archive', 'COUNT(*)', array( 'ar_namespace' => $this->getNamespace(), 
+                       'ar_title' => $this->getDBkey() ), $fname );
+               return (int)$n;
        }
 
        # Get the article ID from the link cache
@@ -616,10 +605,16 @@ class Title {
        # Called from LinksUpdate.php
        function invalidateCache() {
                $now = wfTimestampNow();
-               $ns = $this->getNamespace();
-               $ti = wfStrencode( $this->getDBkey() );
-               $sql = "UPDATE cur SET cur_touched='$now' WHERE cur_namespace=$ns AND cur_title='$ti'";
-               return wfQuery( $sql, DB_WRITE, "Title::invalidateCache" );
+               $dbw =& wfGetDB( DB_WRITE );
+               $success = $dbw->updateArray( 'cur', 
+                       array( /* SET */ 
+                               'cur_touched' => wfTimestampNow()
+                       ), array( /* WHERE */ 
+                               'cur_namespace' => $this->getNamespace() ,
+                               'cur_title' => $this->getDBkey()
+                       ), 'Title::invalidateCache'
+               );
+               return $success;
        }
 
        # Prefixes some arbitrary text with the namespace or interwiki prefix of this object
@@ -640,8 +635,8 @@ class Title {
        # Secure and split - main initialisation function for this object
        # 
        # Assumes that mDbkeyform has been set, and is urldecoded
-    # and uses undersocres, but not otherwise munged.  This function
-    # removes illegal characters, splits off the winterwiki and
+    # and uses underscores, but not otherwise munged.  This function
+    # removes illegal characters, splits off the interwiki and
     # namespace prefixes, sets the other forms, and canonicalizes
     # everything.      
        #
@@ -733,6 +728,7 @@ class Title {
                # Reject illegal characters.
                #
                if( preg_match( $rxTc, $r ) ) {
+                       wfProfileOut( $fname );
                        return false;
                }
                
@@ -743,6 +739,7 @@ class Title {
                       strpos( $r, "/./" !== false ) ||
                       strpos( $r, "/../" !== false ) ) )
                {
+                       wfProfileOut( $fname );
                        return false;
                }
 
@@ -773,21 +770,31 @@ class Title {
 
        # Get an array of Title objects linking to this title
        # Also stores the IDs in the link cache
+       # $options may be FOR UPDATE
        function getLinksTo( $options = '' ) {
                global $wgLinkCache;
                $id = $this->getArticleID();
-               $sql = "SELECT cur_namespace,cur_title,cur_id FROM cur,links WHERE l_from=cur_id AND l_to={$id} $options";
-               $res = wfQuery( $sql, DB_READ, "Title::getLinksTo" );
+               
+               if ( $options ) {
+                       $db =& wfGetDB( DB_WRITE );
+               } else {
+                       $db =& wfGetDB( DB_READ );
+               }
+               $cur = $db->tableName( 'cur' );
+               $links = $db->tableName( 'links' );
+
+               $sql = "SELECT cur_namespace,cur_title,cur_id FROM $cur,$links WHERE l_from=cur_id AND l_to={$id} $options";
+               $res = $db->query( $sql, "Title::getLinksTo" );
                $retVal = array();
-               if ( wfNumRows( $res ) ) {
-                       while ( $row = wfFetchObject( $res ) ) {
+               if ( $db->numRows( $res ) ) {
+                       while ( $row = $db->fetchObject( $res ) ) {
                                if ( $titleObj = Title::makeTitle( $row->cur_namespace, $row->cur_title ) ) {
                                        $wgLinkCache->addGoodLink( $row->cur_id, $titleObj->getPrefixedDBkey() );
                                        $retVal[] = $titleObj;
                                }
                        }
                }
-               wfFreeResult( $res );
+               $db->freeResult( $res );
                return $retVal;
        }
 
@@ -795,19 +802,28 @@ class Title {
        # Also stores the IDs in the link cache
        function getBrokenLinksTo( $options = '' ) {
                global $wgLinkCache;
-               $encTitle = wfStrencode( $this->getPrefixedDBkey() );
-               $sql = "SELECT cur_namespace,cur_title,cur_id FROM brokenlinks,cur " .
+               
+               if ( $options ) {
+                       $db =& wfGetDB( DB_WRITE );
+               } else {
+                       $db =& wfGetDB( DB_READ );
+               }
+               $cur = $db->tableName( 'cur' );
+               $brokenlinks = $db->tableName( 'brokenlinks' );
+               $encTitle = $db->strencode( $this->getPrefixedDBkey() );
+
+               $sql = "SELECT cur_namespace,cur_title,cur_id FROM $brokenlinks,$cur " .
                  "WHERE bl_from=cur_id AND bl_to='$encTitle' $options";
-               $res = wfQuery( $sql, DB_READ, "Title::getBrokenLinksTo" );
+               $res = $db->query( $sql, "Title::getBrokenLinksTo" );
                $retVal = array();
-               if ( wfNumRows( $res ) ) {
-                       while ( $row = wfFetchObject( $res ) ) {
+               if ( $db->numRows( $res ) ) {
+                       while ( $row = $db->fetchObject( $res ) ) {
                                $titleObj = Title::makeTitle( $row->cur_namespace, $row->cur_title );
                                $wgLinkCache->addGoodLink( $row->cur_id, $titleObj->getPrefixedDBkey() );
                                $retVal[] = $titleObj;
                        }
                }
-               wfFreeResult( $res );
+               $db->freeResult( $res );
                return $retVal;
        }
 
@@ -896,10 +912,11 @@ class Title {
         $won = wfInvertTimestamp( $now );
                $newid = $nt->getArticleID();
                $oldid = $this->getArticleID();
-               
+               $dbw =& wfGetDB( DB_WRITE );
+               $links = $dbw->tableName( 'links' );
+
                # Change the name of the target page:
-               wfUpdateArray( 
-                       /* table */ 'cur',
+               $dbw->updateArray( 'cur',
                        /* SET */ array( 
                                'cur_touched' => $now, 
                                'cur_namespace' => $nt->getNamespace(),
@@ -914,8 +931,7 @@ class Title {
                # by definition if we've got here it's rather uninteresting.
                
                $redirectText = $wgMwRedir->getSynonym( 0 ) . " [[" . $nt->getPrefixedText() . "]]\n";
-               wfUpdateArray( 
-                       /* table */ 'cur',
+               $dbw->updateArray( 'cur',
                        /* SET */ array(
                                'cur_touched' => $now,
                                'cur_timestamp' => $now,
@@ -940,7 +956,7 @@ class Title {
 
                # Fix the redundant names for the past revisions of the target page.
                # The redirect should have no old revisions.
-               wfUpdateArray(
+               $dbw->updateArray(
                        /* table */ 'old',
                        /* SET */ array( 
                                'old_namespace' => $nt->getNamespace(),
@@ -962,12 +978,12 @@ class Title {
                $linksToNew = $nt->getLinksTo( 'FOR UPDATE' );
                
                # Delete them all
-               $sql = "DELETE FROM links WHERE l_to=$oldid OR l_to=$newid";
-               wfQuery( $sql, DB_WRITE, $fname );
+               $sql = "DELETE FROM $links WHERE l_to=$oldid OR l_to=$newid";
+               $dbw->query( $sql, $fname );
 
                # Reinsert
                if ( count( $linksToOld ) || count( $linksToNew )) {
-                       $sql = "INSERT INTO links (l_from,l_to) VALUES ";
+                       $sql = "INSERT INTO $links (l_from,l_to) VALUES ";
                        $first = true;
 
                        # Insert links to old title
@@ -992,15 +1008,13 @@ class Title {
                                $sql .= "($id, $oldid)";
                        }
 
-                       wfQuery( $sql, DB_WRITE, $fname );
+                       $dbw->query( $sql, DB_WRITE, $fname );
                }
 
                # Now, we record the link from the redirect to the new title.
                # It should have no other outgoing links...
-               $sql = "DELETE FROM links WHERE l_from={$newid}";
-               wfQuery( $sql, DB_WRITE, $fname );
-               $sql = "INSERT INTO links (l_from,l_to) VALUES ({$newid},{$oldid})";
-               wfQuery( $sql, DB_WRITE, $fname );
+               $dbw->delete( 'links', array( 'l_from' => $newid ) );
+               $dbw->insertArray( 'links', array( 'l_from' => $newid, 'l_to' => $oldid ) );
                
                # Clear linkscc
                LinkCache::linksccClearLinksTo( $oldid );
@@ -1027,10 +1041,10 @@ class Title {
                $won = wfInvertTimestamp( $now );
                $newid = $nt->getArticleID();
                $oldid = $this->getArticleID();
+               $dbw =& wfGetDB( DB_WRITE );
 
                # Rename cur entry
-               wfUpdateArray(
-                       /* table */ 'cur',
+               $dbw->updateArray( 'cur',
                        /* SET */ array(
                                'cur_touched' => $now,
                                'cur_namespace' => $nt->getNamespace(),
@@ -1043,7 +1057,7 @@ class Title {
                $wgLinkCache->clearLink( $nt->getPrefixedDBkey() );
 
                # Insert redirct
-               wfInsertArray( 'cur', array(
+               $dbw->insertArray( 'cur', array(
                        'cur_namespace' => $this->getNamespace(),
                        'cur_title' => $this->getDBkey(),
                        'cur_comment' => $comment,
@@ -1054,13 +1068,13 @@ class Title {
                        'cur_touched' => $now,
                        'cur_is_redirect' => 1,
                        'cur_is_new' => 1,
-                       'cur_text' => "#REDIRECT [[" . $nt->getPrefixedText() . "]]\n" )
+                       'cur_text' => "#REDIRECT [[" . $nt->getPrefixedText() . "]]\n" ), $fname
                );
-               $newid = wfInsertId();
+               $newid = $dbw->insertId();
                $wgLinkCache->clearLink( $this->getPrefixedDBkey() );
 
                # Rename old entries
-               wfUpdateArray( 
+               $dbw->updateArray( 
                        /* table */ 'old',
                        /* SET */ array(
                                'old_namespace' => $nt->getNamespace(),
@@ -1079,13 +1093,11 @@ class Title {
                Article::onArticleCreate( $nt );
 
                # Any text links to the old title must be reassigned to the redirect
-               $sql = "UPDATE links SET l_to={$newid} WHERE l_to={$oldid}";
-               wfQuery( $sql, DB_WRITE, $fname );
+               $dbw->updateArray( 'links', array( 'l_to' => $newid ), array( 'l_to' => $oldid ), $fname );
                LinkCache::linksccClearLinksTo( $oldid );
 
                # Record the just-created redirect's linking to the page
-               $sql = "INSERT INTO links (l_from,l_to) VALUES ({$newid},{$oldid})";
-               wfQuery( $sql, DB_WRITE, $fname );
+               $dbw->insertArray( 'links', array( 'l_from' => $newid, 'l_to' => $oldid ), $fname );
 
                # Non-existent target may have had broken links to it; these must
                # now be removed and made into good links.
@@ -1106,19 +1118,18 @@ class Title {
        }
 
        # Checks if $this can be moved to $nt
-       # Both titles must exist in the database, otherwise it will blow up
+       # Selects for update, so don't call it unless you mean business
        function isValidMoveTarget( $nt )
        {
                $fname = "Title::isValidMoveTarget";
+               $dbw =& wfGetDB( DB_WRITE );
 
                # Is it a redirect?
                $id  = $nt->getArticleID();
-               $sql = "SELECT cur_is_redirect,cur_text FROM cur " .
-                 "WHERE cur_id={$id}";
-               $res = wfQuery( $sql, DB_READ, $fname );
-               $obj = wfFetchObject( $res );
+               $obj = $dbw->getArray( 'cur', array( 'cur_is_redirect','cur_text' ), 
+                       array( 'cur_id' => $id ), $fname, 'FOR UPDATE' );
 
-               if ( 0 == $obj->cur_is_redirect ) { 
+               if ( !$obj || 0 == $obj->cur_is_redirect ) { 
                        # Not a redirect
                        return false; 
                }
@@ -1132,9 +1143,11 @@ class Title {
                }
 
                # Does the article have a history?
-               $row = wfGetArray( 'old', array( 'old_id' ), array( 
-                       'old_namespace' => $nt->getNamespace(),
-                       'old_title' => $nt->getDBkey() )
+               $row = $dbw->getArray( 'old', array( 'old_id' ), 
+                       array( 
+                               'old_namespace' => $nt->getNamespace(),
+                               'old_title' => $nt->getDBkey() 
+                       ), $fname, 'FOR UPDATE' 
                );
 
                # Return true if there was no history
@@ -1149,10 +1162,14 @@ class Title {
                        return false;
                }
                
+               $fname = "Title::createRedirect";
+               $dbw =& wfGetDB( DB_WRITE );
                $now = wfTimestampNow();
                $won = wfInvertTimestamp( $now );
+               $seqVal = $dbw->nextSequenceValue( 'cur_cur_id_seq' );
 
-               wfInsertArray( 'cur', array(
+               $dbw->insertArray( 'cur', array(
+                       'cur_id' => $seqVal,
                        'cur_namespace' => $this->getNamespace(),
                        'cur_title' => $this->getDBkey(),
                        'cur_comment' => $comment,
@@ -1164,21 +1181,25 @@ class Title {
                        'cur_is_redirect' => 1,
                        'cur_is_new' => 1,
                        'cur_text' => "#REDIRECT [[" . $dest->getPrefixedText() . "]]\n" 
-               ));
-               $newid = wfInsertId();
+               ), $fname );
+               $newid = $dbw->insertId();
                $this->resetArticleID( $newid );
                
                # Link table
                if ( $dest->getArticleID() ) {
-                       wfInsertArray( 'links', array(
-                               'l_to' => $dest->getArticleID(),
-                               'l_from' => $newid
-                       ));
+                       $dbw->insertArray( 'links', 
+                               array(
+                                       'l_to' => $dest->getArticleID(),
+                                       'l_from' => $newid
+                               ), $fname 
+                       );
                } else {
-                       wfInsertArray( 'brokenlinks', array( 
-                               'bl_to' => $dest->getPrefixedDBkey(),
-                               'bl_from' => $newid
-                       ));
+                       $dbw->insertArray( 'brokenlinks', 
+                               array( 
+                                       'bl_to' => $dest->getPrefixedDBkey(),
+                                       'bl_from' => $newid
+                               ), $fname
+                       );
                }
 
                Article::onArticleCreate( $this );
@@ -1191,21 +1212,23 @@ class Title {
        {
                global $wgLang,$wgUser;
                
-               #$titlekey = wfStrencode( $this->getArticleID() );
                $titlekey = $this->getArticleId();
                $cns = Namespace::getCategory();
                $sk =& $wgUser->getSkin();
                $parents = array();
-               
+               $dbr =& wfGetDB( DB_READ );
+               $cur = $dbr->tableName( 'cur' );
+               $categorylinks = $dbr->tableName( 'categorylinks' );
+
                # get the parents categories of this title from the database
-               $sql = "SELECT DISTINCT cur_id FROM cur,categorylinks
+               $sql = "SELECT DISTINCT cur_id FROM $cur,$categorylinks
                        WHERE cl_from='$titlekey' AND cl_to=cur_title AND cur_namespace='$cns'
                                ORDER BY cl_sortkey" ;
-               $res = wfQuery ( $sql, DB_READ ) ;
+               $res = $dbr->query ( $sql ) ;
                
-               if(wfNumRows($res) > 0) {
-                       while ( $x = wfFetchObject ( $res ) ) $data[] = $x ;
-                       wfFreeResult ( $res ) ;
+               if($dbr->numRows($res) > 0) {
+                       while ( $x = $dbr->fetchObject ( $res ) ) $data[] = $x ;
+                       $dbr->freeResult ( $res ) ;
                } else {
                        $data = '';
                }
index 16976f1..470fa69 100644 (file)
@@ -12,12 +12,13 @@ class ViewCountUpdate {
 
        function doUpdate()
        {
-               global $wgDisableCounters, $wgIsMySQL;
+               global $wgDisableCounters;
                if ( $wgDisableCounters ) { return; }
-               $lowpri=$wgIsMySQL?"LOW_PRIORITY":"";
+               $db =& wfGetDB( DB_WRITE );
+               $lowpri = $db->lowPriorityOption();
                $sql = "UPDATE $lowpri cur SET cur_counter=(1+cur_counter)," .
                  "cur_timestamp=cur_timestamp WHERE cur_id={$this->mPageID}";
-               $res = wfQuery( $sql, DB_WRITE, "ViewCountUpdate::doUpdate" );
+               $res = $db->query( $sql, "ViewCountUpdate::doUpdate" );
        }
 }
 ?>
index 23ad280..e2d9506 100644 (file)
@@ -36,24 +36,17 @@ class WatchedItem {
 
        function addWatch()
        {
-               global $wgIsMySQL;
+               $fname = "WatchedItem::addWatch";
                # REPLACE instead of INSERT because occasionally someone
                # accidentally reloads a watch-add operation.
-               if ($wgIsMySQL) {
-                       $sql = "REPLACE INTO watchlist (wl_user, wl_namespace,wl_title) ". 
-                               "VALUES ($this->id,$this->ns,'$this->eti')";
-                       $res = wfQuery( $sql, DB_WRITE );
-               } else {
-                       $sql = "DELETE FROM watchlist WHERE wl_user=$this->id AND
-                                       wl_namespace=$this->ns AND wl_title='$this->eti'";
-                       wfQuery( $sql, DB_WRITE);
-                       $sql = "INSERT INTO watchlist (wl_user, wl_namespace,wl_title) ". 
-                               "VALUES ($this->id,$this->ns,'$this->eti')";
-                       $res = wfQuery( $sql, DB_WRITE );
-               }
+               $dbw =& wfGetDB( DB_WRITE );
+               $dbw->replace( 'watchlist', array(array('wl_user', 'wl_namespace', 'wl_title')),
+                 array( 
+                   'wl_user' => $this->id,
+                       'wl_namespace' => $this->ns,
+                       'wl_title' => $this->eti,
+                 ), $fname );
 
-               if( $res === false ) return false;
-               
                global $wgMemc;
                $wgMemc->set( $this->watchkey(), 1 );
                return true;
index 992a28b..075e721 100644 (file)
--- a/index.php
+++ b/index.php
@@ -95,7 +95,8 @@ if ( $search = $wgRequest->getText( 'search' ) ) {
                $wgArticle = new Article( $wgTitle );
        }
 
-       wfQuery("BEGIN", DB_WRITE);
+       $db =& wfGetDB( DB_WRITE );
+       $db->query("BEGIN", DB_WRITE);
        switch( $action ) {
                case "view":
                        $wgOut->setSquidMaxage( $wgSquidMaxage );
@@ -165,7 +166,7 @@ if ( $search = $wgRequest->getText( 'search' ) ) {
                default:
                        $wgOut->errorpage( "nosuchaction", "nosuchactiontext" );
        }
-       wfQuery("COMMIT", DB_WRITE);
+       $db->query("COMMIT");
 }
 
 $wgOut->output();
index 040c34d..2ee841f 100644 (file)
@@ -132,7 +132,8 @@ function dbsource( $fname, $database = false ) {
 # Obsolete, use Database::fieldExists()
 function field_exists( $table, $field ) {
        $fname = "Update script: field_exists";
-       $res = wfQuery( "DESCRIBE $table", $fname );
+       $db =& wfGetDB( DB_READ );
+       $res = $db->query( "DESCRIBE $table", $fname );
        $found = false;
        
        while ( $row = wfFetchObject( $res ) ) {
index 7a91271..7f5e1a0 100644 (file)
@@ -7,148 +7,160 @@ print "?xml version=\"1.0\" encoding=\"utf-8\"?";
 print ">";
 ?>
 <!DOCTYPE html
-    PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
-       "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
+       PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
+               "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 <html xmlns="http://www.w3.org/1999/xhtml"><head><title>texvc</title></head><body>
 <?php
 print "<form method=\"post\" action=\"{$wgServer}{$wgScriptPath}/texvc_cgi.phtml\">"
 ?>
 <textarea name='math' rows='10' cols='80'><?
-    global $math;
-    $math = preg_replace ("/\\\\\\\\/", '\\', $math);
-    print $math;
+       global $math;
+       $math = preg_replace ("/\\\\\\\\/", '\\', $math);
+       print $math;
 ?></textarea><br /><input type="submit" value="Preview" name="preview" /></form>
 <?php
 function xlinkToMathImage ( $tex, $outputhash )
 {
-    global $wgMathPath;
-    return "<img src=\"".$wgMathPath."/".$outputhash.".png\" alt=\"".wfEscapeHTML($tex)."\" />";
+       global $wgMathPath;
+       return "<img src=\"".$wgMathPath."/".$outputhash.".png\" alt=\"".wfEscapeHTML($tex)."\" />";
 }
 
 function texvc_cgi_renderMath( $tex )
 {
-    global $wgMathDirectory, $wgTmpDirectory, $wgInputEncoding;
-    $mf   = wfMsg( "math_failure" );
-    $munk = wfMsg( "math_unknown_error" );
-
-    $image = "";
-    $outhtml = "";
-    $outtex = "";
-
-    $fname = "texvc_cgi_renderMath";
-
-    $md5 = md5($tex);
-    $md5_sql = mysql_escape_string(pack("H32", $md5));
-    $sql = "SELECT math_outputhash,math_html_conservativeness,math_html,math_mathml FROM math WHERE math_inputhash = '".$md5_sql."'";
-
-    $res = wfQuery( $sql, 0, $fname );
-    if ( wfNumRows( $res ) == 0 )
-    {
-       $cmd = "./math/texvc ".escapeshellarg($wgTmpDirectory)." ".
-                     escapeshellarg($wgMathDirectory)." ".escapeshellarg($tex)." ".escapeshellarg($wgInputEncoding);
-       $contents = `$cmd`;
-
-       if (strlen($contents) == 0)
-           return "<h3>".$mf." (".$munk."): ".wfEscapeHTML($tex)."</h3>";
-       $retval = substr ($contents, 0, 1);
-
-       if (($retval == "C") || ($retval == "M") || ($retval == "L")) {
-           if ($retval == "C")
-               $conservativeness = 2;
-           else if ($retval == "M")
-               $conservativeness = 1;
-           else
-               $conservativeness = 0;
-           $outdata = substr ($contents, 33);
-
-           $i = strpos($outdata, "\000");
-
-           $outhtml = substr($outdata, 0, $i);
-           $mathml = substr($outdata, $i+1);
-
-           $sql_html = "'".mysql_escape_string($outhtml)."'";
-           $sql_mathml = "'".mysql_escape_string($mathml)."'";
-       } else if (($retval == "c") || ($retval == "m") || ($retval == "l"))  {
-           $outhtml = substr ($contents, 33);
-           if ($retval == "c")
-               $conservativeness = 2;
-           else if ($retval == "m")
-               $conservativeness = 1;
-           else
-               $conservativeness = 0;
-           $sql_html = "'".mysql_escape_string($outhtml)."'";
-           $mathml = '';
-           $sql_mathml = 'NULL';
-       } else if ($retval == "X") {
-           $outhtml = '';
-           $mathml = substr ($contents, 33);
-           $sql_html = 'NULL';
-           $sql_mathml = "'".mysql_escape_string($mathml)."'";
-           $conservativeness = 0;
-       } else if ($retval == "+") {
-           $outhtml = '';
-           $mathml = '';
-           $sql_html = 'NULL';
-           $sql_mathml = 'NULL';
-           $conservativeness = 0;
+       global $wgMathDirectory, $wgTmpDirectory, $wgInputEncoding;
+       $dbr =& wfGetDB( DB_READ );
+       $mf   = wfMsg( "math_failure" );
+       $munk = wfMsg( "math_unknown_error" );
+
+       $image = "";
+       $outhtml = "";
+       $outtex = "";
+
+       $fname = "texvc_cgi_renderMath";
+
+       $md5 = md5($tex);
+       $md5_sql = pack("H32", $md5);
+
+       $mathTable = $dbr->tableName( 'math' );
+       $rpage = $dbr->getArray( 'math', array('math_outputhash','math_html_conservativeness','math_html','math_mathml'),
+         array( 'math_inputhash' => $md5_sql ) );
+       
+       if ( $rpage === false )
+       {
+               $cmd = "./math/texvc ".wfEscapeShellArg($wgTmpDirectory)." ".
+                                         wfEscapeShellArg($wgMathDirectory)." ".wfEscapeShellArg($tex)." ".wfEscapeShellArg($wgInputEncoding);
+               $contents = `$cmd`;
+
+               if (strlen($contents) == 0)
+                       return "<h3>".$mf." (".$munk."): ".wfEscapeHTML($tex)."</h3>";
+               $retval = substr ($contents, 0, 1);
+
+               if (($retval == "C") || ($retval == "M") || ($retval == "L")) {
+                       if ($retval == "C")
+                               $conservativeness = 2;
+                       else if ($retval == "M")
+                               $conservativeness = 1;
+                       else
+                               $conservativeness = 0;
+                       $outdata = substr ($contents, 33);
+
+                       $i = strpos($outdata, "\000");
+
+                       $outhtml = substr($outdata, 0, $i);
+                       $mathml = substr($outdata, $i+1);
+
+                       #$sql_html = "'".mysql_escape_string($outhtml)."'";
+                       #$sql_mathml = "'".mysql_escape_string($mathml)."'";
+               } else if (($retval == "c") || ($retval == "m") || ($retval == "l"))  {
+                       $outhtml = substr ($contents, 33);
+                       if ($retval == "c")
+                               $conservativeness = 2;
+                       else if ($retval == "m")
+                               $conservativeness = 1;
+                       else
+                               $conservativeness = 0;
+                       #$sql_html = "'".mysql_escape_string($outhtml)."'";
+                       $mathml = NULL;
+                       #$sql_mathml = 'NULL';
+               } else if ($retval == "X") {
+                       $outhtml = NULL;
+                       $mathml = substr ($contents, 33);
+                       #$sql_html = 'NULL';
+                       #$sql_mathml = "'".mysql_escape_string($mathml)."'";
+                       $conservativeness = 0;
+               } else if ($retval == "+") {
+                       $outhtml = NULL;
+                       $mathml = NULL;
+                       #$sql_html = 'NULL';
+                       #$sql_mathml = 'NULL';
+                       $conservativeness = 0;
+               } else {
+                       if ($retval == "E")
+                               $errmsg = wfMsg( "math_lexing_error" );
+                       else if ($retval == "S")
+                               $errmsg = wfMsg( "math_syntax_error" );
+                       else if ($retval == "F")
+                               $errmsg = wfMsg( "math_unknown_function" );
+                       else
+                               $errmsg = $munk;
+                       return "<h3>".$mf." (".$errmsg.substr($contents, 1)."): ".wfEscapeHTML($tex)."</h3>";
+               }
+
+               $outmd5 = substr ($contents, 1, 32);
+               if (!preg_match("/^[a-f0-9]{32}$/", $outmd5))
+                       return "<h3>".$mf." (".$munk."): ".wfEscapeHTML($tex)."</h3>";
+
+               $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->insertArray( 'math', 
+                 array( 
+                   'math_inputhash' => $md5_sql, 
+                       'math_outputhash' => $outmd5_sql,
+                       'math_html_conservativeness' => $conservativeness,
+                       'math_html' => $outhtml,
+                       'math_mathml' => $mathml,
+                 ), $fname, array( 'IGNORE' ) 
+               );
+               
+// we don't really care if it fails
        } else {
-           if ($retval == "E")
-               $errmsg = wfMsg( "math_lexing_error" );
-           else if ($retval == "S")
-               $errmsg = wfMsg( "math_syntax_error" );
-           else if ($retval == "F")
-               $errmsg = wfMsg( "math_unknown_function" );
-           else
-               $errmsg = $munk;
-           return "<h3>".$mf." (".$errmsg.substr($contents, 1)."): ".wfEscapeHTML($tex)."</h3>";
+               $rpage = $dbr->fetchObject ( $res );
+               $outmd5 = unpack ("H32md5", $rpage->math_outputhash);
+               $outmd5 = $outmd5 ['md5'];
+               $outhtml = $rpage->math_html;
+               $conservativeness = $rpage->math_html_conservativeness;
+               $mathml = $rpage->math_mathml;
        }
-
-       $outmd5 = substr ($contents, 1, 32);
-       if (!preg_match("/^[a-f0-9]{32}$/", $outmd5))
-           return "<h3>".$mf." (".$munk."): ".wfEscapeHTML($tex)."</h3>";
-
-       $outmd5_sql = mysql_escape_string(pack("H32", $outmd5));
-
-       $sql = "INSERT INTO math VALUES ('".$md5_sql."', '".$outmd5_sql."', ".$conservativeness.", ".$sql_html.", ".$sql_mathml.")";
-
-       $res = wfQuery( $sql, 0, $fname );
-// we don't really care if it fails
-    } else {
-       $rpage = wfFetchObject ( $res );
-       $outmd5 = unpack ("H32md5", $rpage->math_outputhash);
-       $outmd5 = $outmd5 ['md5'];
-       $outhtml = $rpage->math_html;
-       $conservativeness = $rpage->math_html_conservativeness;
-       $mathml = $rpage->math_mathml;
-    }
-    if ($mathml == '')
-       $mathml = "<h3>Failed to generate MathML</h3>";
-    else
-       $mathml = "<h3>MathML</h3><math xmlns=\"http://www.w3.org/1998/Math/MathML\">$mathml</math>";
-    $image = "<h3>Image</h3>" . xlinkToMathImage ( $tex, $outmd5 );
-    $cmd = "./math/texvc_tex ".escapeshellarg($tex)." ".escapeshellarg($wgInputEncoding);
-    $outtex = `$cmd`;
-
-    if ( $outhtml == '' )
-        $outhtml = "<h3>Failed to generate HTML</h3>";
-    else
-       if ( $conservativeness == 2)
-           $outhtml = "<h3>HTML (conservative)</h3>" . $outhtml;
-       else if ( $conservativeness == 1)
-           $outhtml = "<h3>HTML (moderate)</h3>" . $outhtml;
+       if ( is_null( $mathml ) || $mathml === '' )
+               $mathml = "<h3>Failed to generate MathML</h3>";
        else
-           $outhtml = "<h3>HTML (liberal)</h3>" . $outhtml;
+               $mathml = "<h3>MathML</h3><math xmlns=\"http://www.w3.org/1998/Math/MathML\">$mathml</math>";
+       $image = "<h3>Image</h3>" . xlinkToMathImage ( $tex, $outmd5 );
+       $cmd = "./math/texvc_tex ".escapeshellarg($tex)." ".escapeshellarg($wgInputEncoding);
+       $outtex = `$cmd`;
 
-    if ( $outtex == '' )
-       $outtex = "<h3>Failed to generate TeX</h3>";
-    else
-       $outtex = "<h3>TeX</h3>" . wfEscapeHTML($outtex);
+       if ( is_null( $outhtml ) || $outhtml === '' )
+               $outhtml = "<h3>Failed to generate HTML</h3>";
+       else
+               if ( $conservativeness == 2)
+                       $outhtml = "<h3>HTML (conservative)</h3>" . $outhtml;
+               else if ( $conservativeness == 1)
+                       $outhtml = "<h3>HTML (moderate)</h3>" . $outhtml;
+               else
+                       $outhtml = "<h3>HTML (liberal)</h3>" . $outhtml;
+
+       if ( $outtex == '' )
+               $outtex = "<h3>Failed to generate TeX</h3>";
+       else
+               $outtex = "<h3>TeX</h3>" . wfEscapeHTML($outtex);
 
-    return $outtex . $outhtml . $mathml . $image;
+       return $outtex . $outhtml . $mathml . $image;
 }
 
 global $math;
 if ($math != '')
-    print texvc_cgi_renderMath($math);
+       print texvc_cgi_renderMath($math);
 ?>
 </body></html>