X-Git-Url: http://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2Flibs%2Frdbms%2Fdatabase%2FDatabase.php;h=aa8a899b85ea0ca8307a387910c20629758634cf;hb=4d10bb14e81aadb907a00e4bd13973ef668ab1f8;hp=60062fbc139d97ae4a086eeb4028da22425d45bf;hpb=cbf8446b74b616a00024ef27225bd1e12ffd3bf6;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/libs/rdbms/database/Database.php b/includes/libs/rdbms/database/Database.php index 60062fbc13..aa8a899b85 100644 --- a/includes/libs/rdbms/database/Database.php +++ b/includes/libs/rdbms/database/Database.php @@ -61,7 +61,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware protected $cliMode; /** @var string Agent name for query profiling */ protected $agent; - /** @var int Bitfield of class DBO_* constants */ + /** @var int Bit field of class DBO_* constants */ protected $flags; /** @var array LoadBalancer tracking information */ protected $lbInfo = []; @@ -217,6 +217,18 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware /** @var float Assume an insert of this many rows or less should be fast to replicate */ private static $SMALL_WRITE_ROWS = 100; + /** @var string[] List of DBO_* flags that can be changed after connection */ + protected static $MUTABLE_FLAGS = [ + 'DBO_DEBUG', + 'DBO_NOBUFFER', + 'DBO_TRX', + 'DBO_DDLMODE', + ]; + /** @var int Bit field of all DBO_* flags that can be changed after connection */ + protected static $DBO_MUTABLE = ( + self::DBO_DEBUG | self::DBO_NOBUFFER | self::DBO_TRX | self::DBO_DDLMODE + ); + /** * @note exceptions for missing libraries/drivers should be thrown in initConnection() * @param array $params Parameters passed from Database::factory() @@ -283,23 +295,18 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware /** * Actually connect to the database over the wire (or to local files) * - * @throws InvalidArgumentException * @throws DBConnectionError * @since 1.31 */ protected function doInitConnection() { - if ( strlen( $this->connectionParams['user'] ) ) { - $this->open( - $this->connectionParams['host'], - $this->connectionParams['user'], - $this->connectionParams['password'], - $this->connectionParams['dbname'], - $this->connectionParams['schema'], - $this->connectionParams['tablePrefix'] - ); - } else { - throw new InvalidArgumentException( "No database user provided" ); - } + $this->open( + $this->connectionParams['host'], + $this->connectionParams['user'], + $this->connectionParams['password'], + $this->connectionParams['dbname'], + $this->connectionParams['schema'], + $this->connectionParams['tablePrefix'] + ); } /** @@ -335,7 +342,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware * equivalent to a "database" in MySQL. Note that MySQL and SQLite do not use schemas. * - tablePrefix : Optional table prefix that is implicitly added on to all table names * recognized in queries. This can be used in place of schemas for handle site farms. - * - flags : Optional bitfield of DBO_* constants that define connection, protocol, + * - flags : Optional bit field of DBO_* constants that define connection, protocol, * buffering, and transaction behavior. It is STRONGLY adviced to leave the DBO_DEFAULT * flag in place UNLESS this this database simply acts as a key/value store. * - driver: Optional name of a specific DB client driver. For MySQL, there is only the @@ -446,7 +453,6 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware // we auto-detect the first available driver. For types without built-in support, // an class named "Database" us used, eg. DatabaseFoo for type 'foo'. static $builtinTypes = [ - 'mssql' => DatabaseMssql::class, 'mysql' => [ 'mysqli' => DatabaseMysqli::class ], 'sqlite' => DatabaseSqlite::class, 'postgres' => DatabasePostgres::class, @@ -613,10 +619,6 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware return $this->lazyMasterHandle; } - public function implicitGroupby() { - return true; - } - public function implicitOrderby() { return true; } @@ -625,10 +627,6 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware return $this->lastQuery; } - public function doneWrites() { - return (bool)$this->lastWriteTime; - } - public function lastDoneWrites() { return $this->lastWriteTime ?: false; } @@ -741,24 +739,32 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware } public function setFlag( $flag, $remember = self::REMEMBER_NOTHING ) { - if ( ( $flag & self::DBO_IGNORE ) ) { - throw new UnexpectedValueException( "Modifying DBO_IGNORE is not allowed" ); + if ( $flag & ~static::$DBO_MUTABLE ) { + throw new DBUnexpectedError( + $this, + "Got $flag (allowed: " . implode( ', ', static::$MUTABLE_FLAGS ) . ')' + ); } if ( $remember === self::REMEMBER_PRIOR ) { array_push( $this->priorFlags, $this->flags ); } + $this->flags |= $flag; } public function clearFlag( $flag, $remember = self::REMEMBER_NOTHING ) { - if ( ( $flag & self::DBO_IGNORE ) ) { - throw new UnexpectedValueException( "Modifying DBO_IGNORE is not allowed" ); + if ( $flag & ~static::$DBO_MUTABLE ) { + throw new DBUnexpectedError( + $this, + "Got $flag (allowed: " . implode( ', ', static::$MUTABLE_FLAGS ) . ')' + ); } if ( $remember === self::REMEMBER_PRIOR ) { array_push( $this->priorFlags, $this->flags ); } + $this->flags &= ~$flag; } @@ -776,26 +782,13 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware } public function getFlag( $flag ) { - return (bool)( $this->flags & $flag ); - } - - /** - * @param string $name Class field name - * @return mixed - * @deprecated Since 1.28 - */ - public function getProperty( $name ) { - return $this->$name; + return ( ( $this->flags & $flag ) === $flag ); } public function getDomainID() { return $this->currentDomain->getId(); } - final public function getWikiID() { - return $this->getDomainID(); - } - /** * Get information about an index into an object * @param string $table Table name @@ -929,7 +922,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware $closed = true; // already closed; nothing to do } - $this->conn = false; + $this->conn = null; // Throw any unexpected errors after having disconnected if ( $exception instanceof Exception ) { @@ -1177,7 +1170,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware * * @param string $sql Original SQL query * @param string $fname Name of the calling function - * @param int $flags Bitfield of class QUERY_* constants + * @param int $flags Bit field of class QUERY_* constants * @return array An n-tuple of: * - mixed|bool: An object, resource, or true on success; false on failure * - string: The result of calling lastError() @@ -1265,7 +1258,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware * @param string $commentedSql SQL query with debugging/trace comment * @param bool $isPermWrite Whether the query is a (non-temporary table) write * @param string $fname Name of the calling function - * @param int $flags Bitfield of class QUERY_* constants + * @param int $flags Bit field of class QUERY_* constants * @return array An n-tuple of: * - mixed|bool: An object, resource, or true on success; false on failure * - string: The result of calling lastError() @@ -1343,7 +1336,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware // Avoid the overhead of logging calls unless debug mode is enabled if ( $this->getFlag( self::DBO_DEBUG ) ) { $this->queryLogger->debug( - "{method} [{runtime}s]: $sql", + "{method} [{runtime}s] {db_host}: $sql", [ 'method' => $fname, 'db_host' => $this->getServer(), @@ -1570,9 +1563,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware if ( $ignore ) { $this->queryLogger->debug( "SQL ERROR (ignored): $error" ); } else { - $exception = $this->getQueryExceptionAndLog( $error, $errno, $sql, $fname ); - - throw $exception; + throw $this->getQueryExceptionAndLog( $error, $errno, $sql, $fname ); } } @@ -1584,19 +1575,18 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware * @return DBError */ private function getQueryExceptionAndLog( $error, $errno, $sql, $fname ) { - $sql1line = mb_substr( str_replace( "\n", "\\n", $sql ), 0, 5 * 1024 ); $this->queryLogger->error( "{fname}\t{db_server}\t{errno}\t{error}\t{sql1line}", $this->getLogContext( [ 'method' => __METHOD__, 'errno' => $errno, 'error' => $error, - 'sql1line' => $sql1line, + 'sql1line' => mb_substr( str_replace( "\n", "\\n", $sql ), 0, 5 * 1024 ), 'fname' => $fname, 'trace' => ( new RuntimeException() )->getTraceAsString() ] ) ); - $this->queryLogger->debug( "SQL ERROR: " . $error . "" ); + if ( $this->wasQueryTimeout( $error, $errno ) ) { $e = new DBQueryTimeoutError( $this, $error, $errno, $sql, $fname ); } elseif ( $this->wasConnectionError( $errno ) ) { @@ -1608,6 +1598,25 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware return $e; } + /** + * @param string $error + * @return DBConnectionError + */ + final protected function newExceptionAfterConnectError( $error ) { + // Connection was not fully initialized and is not safe for use + $this->conn = null; + + $this->connLogger->error( + "Error connecting to {db_server} as user {db_user}: {error}", + $this->getLogContext( [ + 'error' => $error, + 'trace' => ( new RuntimeException() )->getTraceAsString() + ] ) + ); + + return new DBConnectionError( $this, $error ); + } + public function freeResult( $res ) { } @@ -1705,10 +1714,6 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware $startOpts .= ' /*! STRAIGHT_JOIN */'; } - if ( isset( $noKeyOptions['HIGH_PRIORITY'] ) ) { - $startOpts .= ' HIGH_PRIORITY'; - } - if ( isset( $noKeyOptions['SQL_BIG_RESULT'] ) ) { $startOpts .= ' SQL_BIG_RESULT'; } @@ -1725,14 +1730,6 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware $startOpts .= ' SQL_CALC_FOUND_ROWS'; } - if ( isset( $noKeyOptions['SQL_CACHE'] ) ) { - $startOpts .= ' SQL_CACHE'; - } - - if ( isset( $noKeyOptions['SQL_NO_CACHE'] ) ) { - $startOpts .= ' SQL_NO_CACHE'; - } - if ( isset( $options['USE INDEX'] ) && is_string( $options['USE INDEX'] ) ) { $useIndex = $this->useIndexClause( $options['USE INDEX'] ); } else { @@ -2380,6 +2377,12 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware $this->doSelectDomain( DatabaseDomain::newFromId( $domain ) ); } + /** + * @param DatabaseDomain $domain + * @throws DBConnectionError + * @throws DBError + * @since 1.32 + */ protected function doSelectDomain( DatabaseDomain $domain ) { $this->currentDomain = $domain; } @@ -4297,7 +4300,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware */ protected function replaceLostConnection( $fname ) { $this->closeConnection(); - $this->conn = false; + $this->conn = null; $this->handleSessionLossPreconnect(); @@ -4876,7 +4879,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware if ( $this->isOpen() ) { // Open a new connection resource without messing with the old one - $this->conn = false; + $this->conn = null; $this->trxEndCallbacks = []; // don't copy $this->trxSectionCancelCallbacks = []; // don't copy $this->handleSessionLossPreconnect(); // no trx or locks anymore