return $this->__call( __FUNCTION__, func_get_args() );
}
+ public function explicitTrxActive() {
+ return $this->__call( __FUNCTION__, func_get_args() );
+ }
+
public function tablePrefix( $prefix = null ) {
return $this->__call( __FUNCTION__, func_get_args() );
}
}
}
- /**
- * @return bool
- */
- protected function explicitTrxActive() {
+ public function explicitTrxActive() {
return $this->mTrxLevel && ( $this->mTrxAtomicLevels || !$this->mTrxAutomatic );
}
*/
public function trxTimestamp();
+ /**
+ * @return bool Whether an explicit transaction or atomic sections are still open
+ * @since 1.28
+ */
+ public function explicitTrxActive();
+
/**
* Get/set the table prefix.
* @param string $prefix The table prefix to set, or omitted to leave it unchanged.
public function approveMasterChanges( array $options ) {
$limit = isset( $options['maxWriteDuration'] ) ? $options['maxWriteDuration'] : 0;
$this->forEachOpenMasterConnection( function ( DatabaseBase $conn ) use ( $limit ) {
+ // If atomic section or explicit transactions are still open, some caller must have
+ // caught an exception but failed to properly rollback any changes. Detect that and
+ // throw and error (causing rollback).
+ if ( $conn->explicitTrxActive() ) {
+ throw new DBTransactionError(
+ $conn,
+ "Explicit transaction still active. A caller may have caught an error."
+ );
+ }
// Assert that the time to replicate the transaction will be sane.
// If this fails, then all DB transactions will be rollback back together.
$time = $conn->pendingWriteQueryDuration();