}
}
+ protected function wasKnownStatementRollbackError() {
+ $errors = sqlsrv_errors( SQLSRV_ERR_ALL );
+ if ( !$errors ) {
+ return false;
+ }
+ // The transaction vs statement rollback behavior depends on XACT_ABORT, so make sure
+ // that the "statement has been terminated" error (3621) is specifically present.
+ // https://docs.microsoft.com/en-us/sql/t-sql/statements/set-xact-abort-transact-sql
+ $statementOnly = false;
+ $codeWhitelist = [ '2601', '2627', '547' ];
+ foreach ( $errors as $error ) {
+ if ( $error['code'] == '3621' ) {
+ $statementOnly = true;
+ } elseif ( !in_array( $error['code'], $codeWhitelist ) ) {
+ $statementOnly = false;
+ break;
+ }
+ }
+
+ return $statementOnly;
+ }
+
/**
* @return int
*/
* Returns -1 if count cannot be found
* Takes same arguments as Database::select()
* @param string $table
- * @param string $vars
+ * @param string $var
* @param string $conds
* @param string $fname
* @param array $options
* @param array $join_conds
* @return int
*/
- public function estimateRowCount( $table, $vars = '*', $conds = '',
+ public function estimateRowCount( $table, $var = '*', $conds = '',
$fname = __METHOD__, $options = [], $join_conds = []
) {
+ $conds = $this->normalizeConditions( $conds, $fname );
+ $column = $this->extractSingleFieldFromList( $var );
+ if ( is_string( $column ) && !in_array( $column, [ '*', '1' ] ) ) {
+ $conds[] = "$column IS NOT NULL";
+ }
+
// http://msdn2.microsoft.com/en-us/library/aa259203.aspx
$options['EXPLAIN'] = true;
$options['FOR COUNT'] = true;
- $res = $this->select( $table, $vars, $conds, $fname, $options, $join_conds );
+ $res = $this->select( $table, $var, $conds, $fname, $options, $join_conds );
$rows = -1;
if ( $res ) {
return false;
}
+ protected function doSavepoint( $identifier, $fname ) {
+ $this->query( 'SAVE TRANSACTION ' . $this->addIdentifierQuotes( $identifier ), $fname );
+ }
+
+ protected function doReleaseSavepoint( $identifier, $fname ) {
+ // Not supported. Also not really needed, a new doSavepoint() for the
+ // same identifier will overwrite the old.
+ }
+
+ protected function doRollbackToSavepoint( $identifier, $fname ) {
+ $this->query( 'ROLLBACK TRANSACTION ' . $this->addIdentifierQuotes( $identifier ), $fname );
+ }
+
/**
* Begin a transaction, committing any previously open transaction
* @param string $fname