* The image_comment_temp database table is merged into the image table and
deprecated. Since access should be mediated by the CommentStore class, this
change shouldn't affect external code.
+* (T206147) Database::close() will no longer commit any open transactions.
== Compatibility ==
MediaWiki 1.32 requires PHP 7.0.0 or later. Although HHVM 3.18.5 or later is
$exception = null; // error to throw after disconnecting
if ( $this->conn ) {
- // Resolve any dangling transaction first
+ // Roll back any dangling transaction first
if ( $this->trxLevel ) {
if ( $this->trxAtomicLevels ) {
// Cannot let incomplete atomic sections be committed
);
} elseif ( $this->trxAutomatic ) {
// Only the connection manager can commit non-empty DBO_TRX transactions
+ // (empty ones we can silently roll back)
if ( $this->writesOrCallbacksPending() ) {
$exception = new DBUnexpectedError(
$this,
": mass commit/rollback of peer transaction required (DBO_TRX set)."
);
}
- } elseif ( $this->trxLevel ) {
- // Commit explicit transactions as if this was commit()
- $this->queryLogger->warning(
- __METHOD__ . ": writes or callbacks still pending.",
- [ 'trace' => ( new RuntimeException() )->getTraceAsString() ]
+ } else {
+ // Manual transactions should have been committed or rolled
+ // back, even if empty.
+ $exception = new DBUnexpectedError(
+ $this,
+ __METHOD__ . ": transaction is still open (from {$this->trxFname})."
);
}
);
}
- // Commit or rollback the changes and run any callbacks as needed
- if ( $this->trxStatus === self::STATUS_TRX_OK && !$exception ) {
- $this->commit(
- __METHOD__,
- $this->trxAutomatic ? self::FLUSHING_INTERNAL : self::FLUSHING_ONE
- );
- } else {
- $this->rollback( __METHOD__, self::FLUSHING_INTERNAL );
- }
+ // Rollback the changes and run any callbacks as needed
+ $this->rollback( __METHOD__, self::FLUSHING_INTERNAL );
}
// Close the actual connection in the binding handle
* Close the database connection
*
* This should only be called after any transactions have been resolved,
- * aside from read-only transactions (assuming no callbacks are registered).
- * If a transaction is still open anyway, it will be committed if possible.
+ * aside from read-only automatic transactions (assuming no callbacks are registered).
+ * If a transaction is still open anyway, it will be rolled back.
*
* @throws DBError
* @return bool Operation success. true if already closed.
$this->database->onTransactionCommitOrIdle( function () use ( $fname ) {
$this->database->query( 'SELECT 1', $fname );
} );
+ $this->database->onTransactionResolution( function () use ( $fname ) {
+ $this->database->query( 'SELECT 2', $fname );
+ } );
$this->database->delete( 'x', [ 'field' => 3 ], __METHOD__ );
- $this->database->close();
+ try {
+ $this->database->close();
+ $this->fail( 'Expected exception not thrown' );
+ } catch ( DBUnexpectedError $ex ) {
+ $this->assertSame(
+ "Wikimedia\Rdbms\Database::close: transaction is still open (from $fname).",
+ $ex->getMessage()
+ );
+ }
$this->assertFalse( $this->database->isOpen() );
- $this->assertLastSql( 'BEGIN; DELETE FROM x WHERE field = \'3\'; COMMIT; SELECT 1' );
+ $this->assertLastSql( 'BEGIN; DELETE FROM x WHERE field = \'3\'; ROLLBACK; SELECT 2' );
$this->assertEquals( 0, $this->database->trxLevel() );
}
$this->database->clearFlag( IDatabase::DBO_TRX );
$this->assertFalse( $this->database->isOpen() );
- $this->assertLastSql( 'BEGIN; SELECT 1; COMMIT' );
+ $this->assertLastSql( 'BEGIN; SELECT 1; ROLLBACK' );
$this->assertEquals( 0, $this->database->trxLevel() );
}
}