Merge "rdbms: make connection counting logic in LoadBalancer less stateful"
[lhc/web/wiklou.git] / includes / libs / rdbms / database / DatabaseMysqlBase.php
index b5f83da..e3c2268 100644 (file)
@@ -122,9 +122,12 @@ abstract class DatabaseMysqlBase extends Database {
        }
 
        protected function open( $server, $user, $password, $dbName, $schema, $tablePrefix ) {
-               # Close/unset connection handle
                $this->close();
 
+               if ( $schema !== null ) {
+                       throw new DBExpectedError( $this, __CLASS__ . ": domain schemas are not supported." );
+               }
+
                $this->server = $server;
                $this->user = $user;
                $this->password = $password;
@@ -143,88 +146,52 @@ abstract class DatabaseMysqlBase extends Database {
                        $error = $error ?: $this->lastError();
                        $this->connLogger->error(
                                "Error connecting to {db_server}: {error}",
-                               $this->getLogContext( [
-                                       'method' => __METHOD__,
-                                       'error' => $error,
-                               ] )
+                               $this->getLogContext( [ 'method' => __METHOD__, 'error' => $error ] )
                        );
                        $this->connLogger->debug( "DB connection error\n" .
                                "Server: $server, User: $user, Password: " .
                                substr( $password, 0, 3 ) . "..., error: " . $error . "\n" );
-
                        throw new DBConnectionError( $this, $error );
                }
 
-               if ( strlen( $dbName ) ) {
-                       $this->selectDomain( new DatabaseDomain( $dbName, null, $tablePrefix ) );
-               } else {
-                       $this->currentDomain = new DatabaseDomain( null, null, $tablePrefix );
-               }
-
-               // Tell the server what we're communicating with
-               if ( !$this->connectInitCharset() ) {
-                       $error = $this->lastError();
-                       $this->queryLogger->error(
-                               "Error setting character set: {error}",
-                               $this->getLogContext( [
-                                       'method' => __METHOD__,
-                                       'error' => $this->lastError(),
-                               ] )
+               try {
+                       $this->currentDomain = new DatabaseDomain(
+                               strlen( $dbName ) ? $dbName : null,
+                               null,
+                               $tablePrefix
                        );
-                       throw new DBConnectionError( $this, "Error setting character set: $error" );
-               }
 
-               // Abstract over any insane MySQL defaults
-               $set = [ 'group_concat_max_len = 262144' ];
-               // Set SQL mode, default is turning them all off, can be overridden or skipped with null
-               if ( is_string( $this->sqlMode ) ) {
-                       $set[] = 'sql_mode = ' . $this->addQuotes( $this->sqlMode );
-               }
-               // Set any custom settings defined by site config
-               // (e.g. https://dev.mysql.com/doc/refman/4.1/en/innodb-parameters.html)
-               foreach ( $this->connectionVariables as $var => $val ) {
-                       // Escape strings but not numbers to avoid MySQL complaining
-                       if ( !is_int( $val ) && !is_float( $val ) ) {
-                               $val = $this->addQuotes( $val );
+                       // Abstract over any insane MySQL defaults
+                       $set = [ 'group_concat_max_len = 262144' ];
+                       // Set SQL mode, default is turning them all off, can be overridden or skipped with null
+                       if ( is_string( $this->sqlMode ) ) {
+                               $set[] = 'sql_mode = ' . $this->addQuotes( $this->sqlMode );
+                       }
+                       // Set any custom settings defined by site config
+                       // (e.g. https://dev.mysql.com/doc/refman/4.1/en/innodb-parameters.html)
+                       foreach ( $this->connectionVariables as $var => $val ) {
+                               // Escape strings but not numbers to avoid MySQL complaining
+                               if ( !is_int( $val ) && !is_float( $val ) ) {
+                                       $val = $this->addQuotes( $val );
+                               }
+                               $set[] = $this->addIdentifierQuotes( $var ) . ' = ' . $val;
                        }
-                       $set[] = $this->addIdentifierQuotes( $var ) . ' = ' . $val;
-               }
 
-               if ( $set ) {
-                       // Use doQuery() to avoid opening implicit transactions (DBO_TRX)
-                       $success = $this->doQuery( 'SET ' . implode( ', ', $set ) );
-                       if ( !$success ) {
-                               $error = $this->lastError();
-                               $this->queryLogger->error(
-                                       'Error setting MySQL variables on server {db_server}: {error}',
-                                       $this->getLogContext( [
-                                               'method' => __METHOD__,
-                                               'error' => $error,
-                                       ] )
+                       if ( $set ) {
+                               $this->query(
+                                       'SET ' . implode( ', ', $set ),
+                                       __METHOD__,
+                                       self::QUERY_IGNORE_DBO_TRX | self::QUERY_NO_RETRY
                                );
-                               throw new DBConnectionError( $this, "Error setting MySQL variables: $error" );
                        }
+               } catch ( Exception $e ) {
+                       // Connection was not fully initialized and is not safe for use
+                       $this->conn = false;
                }
 
-               $this->opened = true;
-
                return true;
        }
 
-       /**
-        * Set the character set information right after connection
-        * @return bool
-        */
-       protected function connectInitCharset() {
-               if ( $this->utf8Mode ) {
-                       // Tell the server we're communicating with it in UTF-8.
-                       // This may engage various charset conversions.
-                       return $this->mysqlSetCharset( 'utf8' );
-               } else {
-                       return $this->mysqlSetCharset( 'binary' );
-               }
-       }
-
        protected function doSelectDomain( DatabaseDomain $domain ) {
                if ( $domain->getSchema() !== null ) {
                        throw new DBExpectedError( $this, __CLASS__ . ": domain schemas are not supported." );
@@ -269,14 +236,6 @@ abstract class DatabaseMysqlBase extends Database {
         */
        abstract protected function mysqlConnect( $realServer, $dbName );
 
-       /**
-        * Set the character set of the MySQL link
-        *
-        * @param string $charset
-        * @return bool
-        */
-       abstract protected function mysqlSetCharset( $charset );
-
        /**
         * @param IResultWrapper|resource $res
         * @throws DBUnexpectedError
@@ -744,7 +703,7 @@ abstract class DatabaseMysqlBase extends Database {
                return strlen( $name ) && $name[0] == '`' && substr( $name, -1, 1 ) == '`';
        }
 
-       public function getLag() {
+       protected function doGetLag() {
                if ( $this->getLagDetectionMethod() === 'pt-heartbeat' ) {
                        return $this->getLagFromPtHeartbeat();
                } else {