- if ( !$this->trxAtomicLevels && $this->trxAutomaticAtomic ) {
- $this->rollback( $fname, self::FLUSHING_INTERNAL );
- } elseif ( $savepointId !== 'n/a' ) {
- $this->doRollbackToSavepoint( $savepointId, $fname );
- $this->trxStatus = self::STATUS_TRX_OK; // no exception; recovered
+ // Remove the last section and re-index the array
+ $this->trxAtomicLevels = array_slice( $this->trxAtomicLevels, 0, $pos );
+
+ if ( $savepointId !== null ) {
+ // Rollback the transaction to the state just before this atomic section
+ if ( $savepointId === 'n/a' ) {
+ $this->rollback( $fname, self::FLUSHING_INTERNAL );
+ } else {
+ $this->doRollbackToSavepoint( $savepointId, $fname );
+ $this->trxStatus = self::STATUS_TRX_OK; // no exception; recovered
+ $this->trxStatusIgnoredCause = null;
+ }
+ } elseif ( $this->trxStatus > self::STATUS_TRX_ERROR ) {
+ // Put the transaction into an error state if it's not already in one
+ $this->trxStatus = self::STATUS_TRX_ERROR;
+ $this->trxStatusCause = new DBUnexpectedError(
+ $this,
+ "Uncancelable atomic section canceled (got $fname)."
+ );