Merge "rdbms: do not silently rollback empty transactions on error"
[lhc/web/wiklou.git] / includes / libs / rdbms / database / Database.php
index 8da1ca9..7425bf7 100644 (file)
@@ -677,6 +677,10 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                );
        }
 
+       public function preCommitCallbacksPending() {
+               return $this->trxLevel && $this->trxPreCommitCallbacks;
+       }
+
        /**
         * @return string|null
         */
@@ -1165,27 +1169,21 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
 
                if ( $ret === false ) {
                        if ( $this->trxLevel ) {
-                               if ( !$this->wasKnownStatementRollbackError() ) {
-                                       # Either the query was aborted or all queries after BEGIN where aborted.
-                                       if ( $this->explicitTrxActive() || $priorWritesPending ) {
-                                               # In the first case, the only options going forward are (a) ROLLBACK, or
-                                               # (b) ROLLBACK TO SAVEPOINT (if one was set). If the later case, the only
-                                               # option is ROLLBACK, since the snapshots would have been released.
-                                               $this->trxStatus = self::STATUS_TRX_ERROR;
-                                               $this->trxStatusCause =
-                                                       $this->makeQueryException( $lastError, $lastErrno, $sql, $fname );
-                                               $tempIgnore = false; // cannot recover
-                                       } else {
-                                               # Nothing prior was there to lose from the transaction,
-                                               # so just roll it back.
-                                               $this->rollback( __METHOD__ . " ($fname)", self::FLUSHING_INTERNAL );
-                                       }
-                                       $this->trxStatusIgnoredCause = null;
-                               } else {
+                               if ( $this->wasKnownStatementRollbackError() ) {
                                        # We're ignoring an error that caused just the current query to be aborted.
-                                       # But log the cause so we can log a deprecation notice if a
-                                       # caller actually does ignore it.
+                                       # But log the cause so we can log a deprecation notice if a caller actually
+                                       # does ignore it.
                                        $this->trxStatusIgnoredCause = [ $lastError, $lastErrno, $fname ];
+                               } else {
+                                       # Either the query was aborted or all queries after BEGIN where aborted.
+                                       # In the first case, the only options going forward are (a) ROLLBACK, or
+                                       # (b) ROLLBACK TO SAVEPOINT (if one was set). If the later case, the only
+                                       # option is ROLLBACK, since the snapshots would have been released.
+                                       $this->trxStatus = self::STATUS_TRX_ERROR;
+                                       $this->trxStatusCause =
+                                               $this->makeQueryException( $lastError, $lastErrno, $sql, $fname );
+                                       $tempIgnore = false; // cannot recover
+                                       $this->trxStatusIgnoredCause = null;
                                }
                        }
 
@@ -3288,7 +3286,7 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                $this->trxEndCallbacks[] = [ $callback, $fname, $this->currentAtomicSectionId() ];
        }
 
-       final public function onTransactionIdle( callable $callback, $fname = __METHOD__ ) {
+       final public function onTransactionCommitOrIdle( callable $callback, $fname = __METHOD__ ) {
                if ( !$this->trxLevel && $this->getTransactionRoundId() ) {
                        // Start an implicit transaction similar to how query() does
                        $this->begin( __METHOD__, self::TRANSACTION_INTERNAL );
@@ -3301,6 +3299,10 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
                }
        }
 
+       final public function onTransactionIdle( callable $callback, $fname = __METHOD__ ) {
+               $this->onTransactionCommitOrIdle( $callback, $fname );
+       }
+
        final public function onTransactionPreCommitOrIdle( callable $callback, $fname = __METHOD__ ) {
                if ( !$this->trxLevel && $this->getTransactionRoundId() ) {
                        // Start an implicit transaction similar to how query() does
@@ -4630,5 +4632,12 @@ abstract class Database implements IDatabase, IMaintainableDatabase, LoggerAware
        }
 }
 
-class_alias( Database::class, 'DatabaseBase' ); // b/c for old name
-class_alias( Database::class, 'Database' ); // b/c global alias
+/**
+ * @deprecated since 1.28
+ */
+class_alias( Database::class, 'DatabaseBase' );
+
+/**
+ * @deprecated since 1.29
+ */
+class_alias( Database::class, 'Database' );