Merge "Skin: Make skins aware of their registered skin name"
[lhc/web/wiklou.git] / includes / libs / rdbms / database / Database.php
index 64fbea3..bc1454b 100644 (file)
@@ -54,8 +54,8 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
        const PING_TTL = 1.0;
        const PING_QUERY = 'SELECT 1 AS ping';
 
-       const TINY_WRITE_SEC = .010;
-       const SLOW_WRITE_SEC = .500;
+       const TINY_WRITE_SEC = 0.010;
+       const SLOW_WRITE_SEC = 0.500;
        const SMALL_WRITE_ROWS = 100;
 
        /** @var string SQL query */
@@ -1130,6 +1130,20 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                }
        }
 
+       /**
+        * Checks whether the cause of the error is detected to be a timeout.
+        *
+        * It returns false by default, and not all engines support detecting this yet.
+        * If this returns false, it will be treated as a generic query error.
+        *
+        * @param string $error Error text
+        * @param int $errno Error number
+        * @return bool
+        */
+       protected function wasQueryTimeout( $error, $errno ) {
+               return false;
+       }
+
        public function reportQueryError( $error, $errno, $sql, $fname, $tempIgnore = false ) {
                if ( $this->ignoreErrors() || $tempIgnore ) {
                        $this->queryLogger->debug( "SQL ERROR (ignored): $error\n" );
@@ -1146,7 +1160,12 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                                ] )
                        );
                        $this->queryLogger->debug( "SQL ERROR: " . $error . "\n" );
-                       throw new DBQueryError( $this, $error, $errno, $sql, $fname );
+                       $wasQueryTimeout = $this->wasQueryTimeout( $error, $errno );
+                       if ( $wasQueryTimeout ) {
+                               throw new DBQueryTimeoutError( $this, $error, $errno, $sql, $fname );
+                       } else {
+                               throw new DBQueryError( $this, $error, $errno, $sql, $fname );
+                       }
                }
        }
 
@@ -2106,6 +2125,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
 
        /**
         * @param string $s
+        * @param string $escapeChar
         * @return string
         */
        protected function escapeLikeInternal( $s, $escapeChar = '`' ) {
@@ -2388,6 +2408,37 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                        );
                }
 
+               return $this->nonNativeInsertSelect(
+                       $destTable,
+                       $srcTable,
+                       $varMap,
+                       $conds,
+                       $fname,
+                       $insertOptions,
+                       $selectOptions,
+                       $selectJoinConds
+               );
+       }
+
+       /**
+        * Implementation of insertSelect() based on select() and insert()
+        *
+        * @see IDatabase::insertSelect()
+        * @since 1.30
+        * @param string $destTable
+        * @param string|array $srcTable
+        * @param array $varMap
+        * @param array $conds
+        * @param string $fname
+        * @param array $insertOptions
+        * @param array $selectOptions
+        * @param array $selectJoinConds
+        * @return bool
+        */
+       protected function nonNativeInsertSelect( $destTable, $srcTable, $varMap, $conds,
+               $fname = __METHOD__,
+               $insertOptions = [], $selectOptions = [], $selectJoinConds = []
+       ) {
                // For web requests, do a locking SELECT and then INSERT. This puts the SELECT burden
                // on only the master (without needing row-based-replication). It also makes it easy to
                // know how big the INSERT is going to be.
@@ -2416,6 +2467,15 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
         * we don't want to select everything into memory
         *
         * @see IDatabase::insertSelect()
+        * @param string $destTable
+        * @param string|array $srcTable
+        * @param array $varMap
+        * @param array $conds
+        * @param string $fname
+        * @param array $insertOptions
+        * @param array $selectOptions
+        * @param array $selectJoinConds
+        * @return bool
         */
        protected function nativeInsertSelect( $destTable, $srcTable, $varMap, $conds,
                $fname = __METHOD__,
@@ -3018,8 +3078,16 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
 
                $this->mTrxIdleCallbacks = []; // clear
                $this->mTrxPreCommitCallbacks = []; // clear
-               $this->runOnTransactionIdleCallbacks( self::TRIGGER_ROLLBACK );
-               $this->runTransactionListenerCallbacks( self::TRIGGER_ROLLBACK );
+               try {
+                       $this->runOnTransactionIdleCallbacks( self::TRIGGER_ROLLBACK );
+               } catch ( Exception $e ) {
+                       // already logged; finish and let LoadBalancer move on during mass-rollback
+               }
+               try {
+                       $this->runTransactionListenerCallbacks( self::TRIGGER_ROLLBACK );
+               } catch ( Exception $e ) {
+                       // already logged; let LoadBalancer move on during mass-rollback
+               }
        }
 
        /**