X-Git-Url: https://git.heureux-cyclage.org/?a=blobdiff_plain;f=includes%2Flibs%2Frdbms%2Fdatabase%2FDatabaseMssql.php;h=db029a389e7367dccc01ddef7f05031189f2c0e1;hb=436f8eb32fcbae49b7e943a1e231fbdce16ad769;hp=6c003dd5a76482120eba1117745a6d025cdf54a6;hpb=0dda44c8e7e54ab897447954d5c4174513ce7586;p=lhc%2Fweb%2Fwiklou.git diff --git a/includes/libs/rdbms/database/DatabaseMssql.php b/includes/libs/rdbms/database/DatabaseMssql.php index 6c003dd5a7..db029a389e 100644 --- a/includes/libs/rdbms/database/DatabaseMssql.php +++ b/includes/libs/rdbms/database/DatabaseMssql.php @@ -28,6 +28,7 @@ namespace Wikimedia\Rdbms; use Exception; +use RuntimeException; use stdClass; use Wikimedia\AtEase\AtEase; @@ -58,10 +59,6 @@ class DatabaseMssql extends Database { /** @var string[] */ protected $ignoreErrors = []; - public function implicitGroupby() { - return false; - } - public function implicitOrderby() { return false; } @@ -78,53 +75,50 @@ class DatabaseMssql extends Database { } protected function open( $server, $user, $password, $dbName, $schema, $tablePrefix ) { - // Test for driver support, to avoid suppressed fatal error if ( !function_exists( 'sqlsrv_connect' ) ) { throw new DBConnectionError( $this, - "Microsoft SQL Server Native (sqlsrv) functions missing. - You can download the driver from: http://go.microsoft.com/fwlink/?LinkId=123470\n" + "Microsoft SQL Server Native (sqlsrv) functions missing.\n + You can download the driver from: http://go.microsoft.com/fwlink/?LinkId=123470" ); } $this->close(); + + if ( $schema !== null ) { + throw $this->newExceptionAfterConnectError( "Got schema '$schema'; not supported." ); + } + $this->server = $server; $this->user = $user; $this->password = $password; $connectionInfo = []; - - if ( $dbName != '' ) { + if ( strlen( $dbName ) ) { $connectionInfo['Database'] = $dbName; } - - // Decide which auth scenerio to use - // if we are using Windows auth, then don't add credentials to $connectionInfo if ( !$this->useWindowsAuth ) { $connectionInfo['UID'] = $user; $connectionInfo['PWD'] = $password; } AtEase::suppressWarnings(); - $this->conn = sqlsrv_connect( $server, $connectionInfo ); + $this->conn = sqlsrv_connect( $server, $connectionInfo ) ?: null; AtEase::restoreWarnings(); - if ( $this->conn === false ) { - $error = $this->lastError(); - $this->connLogger->error( - "Error connecting to {db_server}: {error}", - $this->getLogContext( [ 'method' => __METHOD__, 'error' => $error ] ) - ); - throw new DBConnectionError( $this, $error ); + if ( !$this->conn ) { + throw $this->newExceptionAfterConnectError( $this->lastError() ); } - $this->currentDomain = new DatabaseDomain( - ( $dbName != '' ) ? $dbName : null, - null, - $tablePrefix - ); - - return (bool)$this->conn; + try { + $this->currentDomain = new DatabaseDomain( + strlen( $dbName ) ? $dbName : null, + null, + $tablePrefix + ); + } catch ( Exception $e ) { + throw $this->newExceptionAfterConnectError( $e->getMessage() ); + } } /** @@ -228,11 +222,7 @@ class DatabaseMssql extends Database { } public function freeResult( $res ) { - if ( $res instanceof ResultWrapper ) { - $res = $res->result; - } - - sqlsrv_free_stmt( $res ); + sqlsrv_free_stmt( ResultWrapper::unwrap( $res ) ); } /** @@ -257,12 +247,9 @@ class DatabaseMssql extends Database { * @return int */ public function numRows( $res ) { - if ( $res instanceof ResultWrapper ) { - $res = $res->result; - } + $res = ResultWrapper::unwrap( $res ); $ret = sqlsrv_num_rows( $res ); - if ( $ret === false ) { // we cannot get an amount of rows from this cursor type // has_rows returns bool true/false if the result has rows @@ -277,11 +264,7 @@ class DatabaseMssql extends Database { * @return int */ public function numFields( $res ) { - if ( $res instanceof ResultWrapper ) { - $res = $res->result; - } - - return sqlsrv_num_fields( $res ); + return sqlsrv_num_fields( ResultWrapper::unwrap( $res ) ); } /** @@ -290,11 +273,7 @@ class DatabaseMssql extends Database { * @return int */ public function fieldName( $res, $n ) { - if ( $res instanceof ResultWrapper ) { - $res = $res->result; - } - - return sqlsrv_field_metadata( $res )[$n]['Name']; + return sqlsrv_field_metadata( ResultWrapper::unwrap( $res ) )[$n]['Name']; } /** @@ -374,6 +353,17 @@ class DatabaseMssql extends Database { return $statementOnly; } + public function serverIsReadOnly() { + $encDatabase = $this->addQuotes( $this->getDBname() ); + $res = $this->query( + "SELECT IS_READ_ONLY FROM SYS.DATABASES WHERE NAME = $encDatabase", + __METHOD__ + ); + $row = $this->fetchObject( $res ); + + return $row ? (bool)$row->IS_READ_ONLY : false; + } + /** * @return int */ @@ -718,7 +708,7 @@ class DatabaseMssql extends Database { } $this->scrollableCursor = true; - if ( $ret instanceof ResultWrapper && !is_null( $identity ) ) { + if ( $ret instanceof IResultWrapper && !is_null( $identity ) ) { // Then we want to get the identity column value we were assigned and save it off $row = $ret->fetchObject(); if ( is_object( $row ) ) { @@ -1071,13 +1061,10 @@ class DatabaseMssql extends Database { $this->query( 'ROLLBACK TRANSACTION ' . $this->addIdentifierQuotes( $identifier ), $fname ); } - /** - * Begin a transaction, committing any previously open transaction - * @param string $fname - */ protected function doBegin( $fname = __METHOD__ ) { - sqlsrv_begin_transaction( $this->conn ); - $this->trxLevel = 1; + if ( !sqlsrv_begin_transaction( $this->conn ) ) { + $this->reportQueryError( $this->lastError(), $this->lastErrno(), 'BEGIN', $fname ); + } } /** @@ -1085,8 +1072,9 @@ class DatabaseMssql extends Database { * @param string $fname */ protected function doCommit( $fname = __METHOD__ ) { - sqlsrv_commit( $this->conn ); - $this->trxLevel = 0; + if ( !sqlsrv_commit( $this->conn ) ) { + $this->reportQueryError( $this->lastError(), $this->lastErrno(), 'COMMIT', $fname ); + } } /** @@ -1095,8 +1083,17 @@ class DatabaseMssql extends Database { * @param string $fname */ protected function doRollback( $fname = __METHOD__ ) { - sqlsrv_rollback( $this->conn ); - $this->trxLevel = 0; + if ( !sqlsrv_rollback( $this->conn ) ) { + $this->queryLogger->error( + "{fname}\t{db_server}\t{errno}\t{error}\t", + $this->getLogContext( [ + 'errno' => $this->lastErrno(), + 'error' => $this->lastError(), + 'fname' => $fname, + 'trace' => ( new RuntimeException() )->getTraceAsString() + ] ) + ); + } } /** @@ -1161,7 +1158,10 @@ class DatabaseMssql extends Database { protected function doSelectDomain( DatabaseDomain $domain ) { if ( $domain->getSchema() !== null ) { - throw new DBExpectedError( $this, __CLASS__ . ": domain schemas are not supported." ); + throw new DBExpectedError( + $this, + __CLASS__ . ": domain '{$domain->getId()}' has a schema component" + ); } $database = $domain->getDatabase();