Merge "Show user names as subpages of special pages in autocomplete search"
[lhc/web/wiklou.git] / includes / db / Database.php
index 99716a5..3fec522 100644 (file)
@@ -148,6 +148,9 @@ abstract class DatabaseBase implements IDatabase {
         */
        private $mTrxWriteDuration = 0.0;
 
+       /** @var IDatabase|null Lazy handle to the master DB this server replicates from */
+       private $lazyMasterHandle;
+
        /**
         * @since 1.21
         * @var resource File handle for upgrade
@@ -328,6 +331,25 @@ abstract class DatabaseBase implements IDatabase {
                }
        }
 
+       /**
+        * Set a lazy-connecting DB handle to the master DB (for replication status purposes)
+        *
+        * @param IDatabase $conn
+        * @since 1.27
+        */
+       public function setLazyMasterHandle( IDatabase $conn ) {
+               $this->lazyMasterHandle = $conn;
+       }
+
+       /**
+        * @return IDatabase|null
+        * @see setLazyMasterHandle()
+        * @since 1.27
+        */
+       public function getLazyMasterHandle() {
+               return $this->lazyMasterHandle;
+       }
+
        /**
         * @return TransactionProfiler
         */
@@ -989,7 +1011,7 @@ abstract class DatabaseBase implements IDatabase {
                }
 
                if ( $this->debug() ) {
-                       wfDebugLog( 'queries', sprintf( "%s: %s", $this->mDBname, $sql ) );
+                       wfDebugLog( 'queries', sprintf( "%s: %s", $this->mDBname, $commentedSql ) );
                }
 
                $queryId = MWDebug::query( $sql, $fname, $isMaster );
@@ -1264,13 +1286,14 @@ abstract class DatabaseBase implements IDatabase {
         * @param string|array $cond The condition array. See DatabaseBase::select() for details.
         * @param string $fname The function name of the caller.
         * @param string|array $options The query options. See DatabaseBase::select() for details.
+        * @param string|array $join_conds The join conditions. See DatabaseBase::select() for details.
         *
         * @return bool|array The values from the field, or false on failure
         * @throws DBUnexpectedError
         * @since 1.25
         */
        public function selectFieldValues(
-               $table, $var, $cond = '', $fname = __METHOD__, $options = array()
+               $table, $var, $cond = '', $fname = __METHOD__, $options = array(), $join_conds = array()
        ) {
                if ( $var === '*' ) { // sanity
                        throw new DBUnexpectedError( $this, "Cannot use a * field: got '$var'" );
@@ -1280,7 +1303,7 @@ abstract class DatabaseBase implements IDatabase {
                        $options = array( $options );
                }
 
-               $res = $this->select( $table, $var, $cond, $fname, $options );
+               $res = $this->select( $table, $var, $cond, $fname, $options, $join_conds );
                if ( $res === false ) {
                        return false;
                }
@@ -3308,7 +3331,11 @@ abstract class DatabaseBase implements IDatabase {
                                        list( $phpCallback ) = $callback;
                                        $this->clearFlag( DBO_TRX ); // make each query its own transaction
                                        call_user_func( $phpCallback );
-                                       $this->setFlag( $autoTrx ? DBO_TRX : 0 ); // restore automatic begin()
+                                       if ( $autoTrx ) {
+                                               $this->setFlag( DBO_TRX ); // restore automatic begin()
+                                       } else {
+                                               $this->clearFlag( DBO_TRX ); // restore auto-commit
+                                       }
                                } catch ( Exception $e ) {
                                        if ( $ePrior ) {
                                                MWExceptionHandler::logException( $ePrior );
@@ -3420,6 +3447,21 @@ abstract class DatabaseBase implements IDatabase {
                }
        }
 
+       final public function doAtomicSection( $fname, $callback ) {
+               if ( !is_callable( $callback ) ) {
+                       throw new UnexpectedValueException( "Invalid callback." );
+               };
+
+               $this->startAtomic( $fname );
+               try {
+                       call_user_func_array( $callback, array( $this, $fname ) );
+               } catch ( Exception $e ) {
+                       $this->rollback( $fname );
+                       throw $e;
+               }
+               $this->endAtomic( $fname );
+       }
+
        /**
         * Begin a transaction. If a transaction is already in progress,
         * that transaction will be committed before the new transaction is started.
@@ -3773,19 +3815,6 @@ abstract class DatabaseBase implements IDatabase {
                return true;
        }
 
-       /**
-        * Get the slave lag when the current transaction started
-        * or a general lag estimate if not transaction is active
-        *
-        * This is useful when transactions might use snapshot isolation
-        * (e.g. REPEATABLE-READ in innodb), so the "real" lag of that data
-        * is this lag plus transaction duration. If they don't, it is still
-        * safe to be pessimistic. In AUTO-COMMIT mode, this still gives an
-        * indication of the staleness of subsequent reads.
-        *
-        * @return array ('lag': seconds, 'since': UNIX timestamp of BEGIN)
-        * @since 1.27
-        */
        public function getSessionLagStatus() {
                return $this->getTransactionLagStatus() ?: $this->getApproximateLagStatus();
        }
@@ -3798,7 +3827,7 @@ abstract class DatabaseBase implements IDatabase {
         * is this lag plus transaction duration. If they don't, it is still
         * safe to be pessimistic. This returns null if there is no transaction.
         *
-        * @return array|null ('lag': seconds, 'since': UNIX timestamp of BEGIN)
+        * @return array|null ('lag': seconds or false on error, 'since': UNIX timestamp of BEGIN)
         * @since 1.27
         */
        public function getTransactionLagStatus() {
@@ -3810,7 +3839,7 @@ abstract class DatabaseBase implements IDatabase {
        /**
         * Get a slave lag estimate for this server
         *
-        * @return array ('lag': seconds, 'since': UNIX timestamp of estimate)
+        * @return array ('lag': seconds or false on error, 'since': UNIX timestamp of estimate)
         * @since 1.27
         */
        public function getApproximateLagStatus() {
@@ -3833,7 +3862,7 @@ abstract class DatabaseBase implements IDatabase {
         * @param IDatabase $db1
         * @param IDatabase ...
         * @return array Map of values:
-        *   - lag: highest lag of any of the DBs
+        *   - lag: highest lag of any of the DBs or false on error (e.g. replication stopped)
         *   - since: oldest UNIX timestamp of any of the DB lag estimates
         *   - pending: whether any of the DBs have uncommitted changes
         * @since 1.27
@@ -3843,7 +3872,11 @@ abstract class DatabaseBase implements IDatabase {
                foreach ( func_get_args() as $db ) {
                        /** @var IDatabase $db */
                        $status = $db->getSessionLagStatus();
-                       $res['lag'] = max( $res['lag'], $status['lag'] );
+                       if ( $status['lag'] === false ) {
+                               $res['lag'] = false;
+                       } elseif ( $res['lag'] !== false ) {
+                               $res['lag'] = max( $res['lag'], $status['lag'] );
+                       }
                        $res['since'] = min( $res['since'], $status['since'] );
                        $res['pending'] = $res['pending'] ?: $db->writesPending();
                }
@@ -3851,15 +3884,6 @@ abstract class DatabaseBase implements IDatabase {
                return $res;
        }
 
-       /**
-        * Get slave lag. Currently supported only by MySQL.
-        *
-        * Note that this function will generate a fatal error on many
-        * installations. Most callers should use LoadBalancer::safeGetLag()
-        * instead.
-        *
-        * @return int Database replication lag in seconds
-        */
        public function getLag() {
                return 0;
        }