$this->close();
if ( $schema !== null ) {
- throw new DBExpectedError( $this, __CLASS__ . ": cannot use schemas ('$schema')" );
+ throw $this->newExceptionAfterConnectError( "Got schema '$schema'; not supported." );
}
$this->server = $server;
$this->installErrorHandler();
try {
$this->conn = $this->mysqlConnect( $this->server, $dbName );
- } catch ( Exception $ex ) {
+ } catch ( Exception $e ) {
$this->restoreErrorHandler();
- throw $ex;
+ throw $this->newExceptionAfterConnectError( $e->getMessage() );
}
$error = $this->restoreErrorHandler();
- # Always log connection errors
if ( !$this->conn ) {
- $error = $error ?: $this->lastError();
- $this->connLogger->error(
- "Error connecting to {db_server}: {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 );
+ throw $this->newExceptionAfterConnectError( $error ?: $this->lastError() );
}
try {
null,
$tablePrefix
);
-
// 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
);
}
} catch ( Exception $e ) {
- // Connection was not fully initialized and is not safe for use
- $this->conn = false;
+ throw $this->newExceptionAfterConnectError( $e->getMessage() );
}
-
- return true;
}
protected function doSelectDomain( DatabaseDomain $domain ) {
*
* @param string $realServer
* @param string|null $dbName
- * @return mixed Raw connection
+ * @return mixed|null Driver connection handle
* @throws DBConnectionError
*/
abstract protected function mysqlConnect( $realServer, $dbName );
protected function getHeartbeatData( array $conds ) {
// Query time and trip time are not counted
$nowUnix = microtime( true );
- // Do not bother starting implicit transactions here
- $this->clearFlag( self::DBO_TRX, self::REMEMBER_PRIOR );
- try {
- $whereSQL = $this->makeList( $conds, self::LIST_AND );
- // Use ORDER BY for channel based queries since that field might not be UNIQUE.
- // Note: this would use "TIMESTAMPDIFF(MICROSECOND,ts,UTC_TIMESTAMP(6))" but the
- // percision field is not supported in MySQL <= 5.5.
- $res = $this->query(
- "SELECT ts FROM heartbeat.heartbeat WHERE $whereSQL ORDER BY ts DESC LIMIT 1",
- __METHOD__,
- self::QUERY_SILENCE_ERRORS | self::QUERY_IGNORE_DBO_TRX
- );
- $row = $res ? $res->fetchObject() : false;
- } finally {
- $this->restoreFlags();
- }
+ $whereSQL = $this->makeList( $conds, self::LIST_AND );
+ // Use ORDER BY for channel based queries since that field might not be UNIQUE.
+ // Note: this would use "TIMESTAMPDIFF(MICROSECOND,ts,UTC_TIMESTAMP(6))" but the
+ // percision field is not supported in MySQL <= 5.5.
+ $res = $this->query(
+ "SELECT ts FROM heartbeat.heartbeat WHERE $whereSQL ORDER BY ts DESC LIMIT 1",
+ __METHOD__,
+ self::QUERY_SILENCE_ERRORS | self::QUERY_IGNORE_DBO_TRX
+ );
+ $row = $res ? $res->fetchObject() : false;
return [ $row ? $row->ts : null, $nowUnix ];
}
}
public function serverIsReadOnly() {
- $flags = self::QUERY_IGNORE_DBO_TRX;
- $res = $this->query( "SHOW GLOBAL VARIABLES LIKE 'read_only'", __METHOD__, $flags );
+ // Avoid SHOW to avoid internal temporary tables
+ $flags = self::QUERY_IGNORE_DBO_TRX | self::QUERY_SILENCE_ERRORS;
+ $res = $this->query( "SELECT @@GLOBAL.read_only AS Value", __METHOD__, $flags );
$row = $this->fetchObject( $res );
- return $row ? ( strtolower( $row->Value ) === 'on' ) : false;
+ return $row ? (bool)$row->Value : false;
}
/**
return "IGNORE INDEX (" . $this->indexName( $index ) . ")";
}
- /**
- * @return string
- */
- function lowPriorityOption() {
- return 'LOW_PRIORITY';
- }
-
/**
* @return string
*/