Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 22 additions & 3 deletions src/MongoDB/Session.c
Original file line number Diff line number Diff line change
Expand Up @@ -390,6 +390,24 @@ static PHP_METHOD(Session, endSession)
mongoc_client_session_destroy(intern->client_session);
} /* }}} */

/* {{{ proto void MongoDB\Driver\Session::isInTransaction(void)
Returns whether a multi-document transaction is in progress */
static PHP_METHOD(Session, isInTransaction)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method name looks strange to me, but I think it's preferable to the more verbose option of isTransactionInProgress() or the like.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Change it to inTransaction ? Don't like that much either...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't want to suggest inTransaction because it's not consistent with prefixing boolean-returning methods with "is". Totally OK with sticking with isInTransaction().

{
php_phongo_session_t* intern;
SUPPRESS_UNUSED_WARNING(return_value_ptr)
SUPPRESS_UNUSED_WARNING(return_value_used)

intern = Z_SESSION_OBJ_P(getThis());

if (zend_parse_parameters_none() == FAILURE) {
return;
}

RETURN_BOOL(mongoc_client_session_in_transaction(intern->client_session));
} /* }}} */


/* {{{ MongoDB\Driver\Session function entries */
ZEND_BEGIN_ARG_INFO_EX(ai_Session_advanceClusterTime, 0, 0, 1)
ZEND_ARG_INFO(0, clusterTime)
Expand All @@ -408,15 +426,16 @@ ZEND_END_ARG_INFO()

static zend_function_entry php_phongo_session_me[] = {
/* clang-format off */
PHP_ME(Session, abortTransaction, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
PHP_ME(Session, advanceClusterTime, ai_Session_advanceClusterTime, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
PHP_ME(Session, advanceOperationTime, ai_Session_advanceOperationTime, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
PHP_ME(Session, commitTransaction, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
PHP_ME(Session, endSession, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
PHP_ME(Session, getClusterTime, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
PHP_ME(Session, getLogicalSessionId, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
PHP_ME(Session, getOperationTime, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
PHP_ME(Session, isInTransaction, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
PHP_ME(Session, startTransaction, ai_Session_startTransaction, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
PHP_ME(Session, commitTransaction, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
PHP_ME(Session, abortTransaction, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
PHP_ME(Session, endSession, ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
ZEND_NAMED_ME(__construct, PHP_FN(MongoDB_disabled___construct), ai_Session_void, ZEND_ACC_PRIVATE | ZEND_ACC_FINAL)
ZEND_NAMED_ME(__wakeup, PHP_FN(MongoDB_disabled___wakeup), ai_Session_void, ZEND_ACC_PUBLIC | ZEND_ACC_FINAL)
PHP_FE_END
Expand Down
2 changes: 1 addition & 1 deletion src/libmongoc
Submodule libmongoc updated 231 files
74 changes: 74 additions & 0 deletions tests/session/session-isInTransaction-001.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
--TEST--
MongoDB\Driver\Session::isInTransaction()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this test would do well to cover both the "started" and "in progress" transaction states. At the moment, I believe it only covers "started", which is before the first command is sent. See test_in_transaction() for a good example. Ideally, we should just port that to a PHP test.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our test was basically that test already, but I added two sections that actually have an operation in the transaction too.

--SKIPIF--
<?php require __DIR__ . "/../utils/basic-skipif.inc"; ?>
<?php skip_if_not_libmongoc_crypto() ?>
<?php skip_if_server_version('<', '4.0'); ?>
<?php skip_if_not_replica_set(); ?>
<?php skip_if_not_clean(DATABASE_NAME, COLLECTION_NAME); ?>
--FILE--
<?php
require_once __DIR__ . "/../utils/basic.inc";

$manager = new MongoDB\Driver\Manager(URI);

/* Create collections as that can't be (automatically) done in a transaction */
$cmd = new \MongoDB\Driver\Command([
'create' => COLLECTION_NAME,
]);
$manager->executeCommand(DATABASE_NAME, $cmd);

/* Start a session */
$session = $manager->startSession();

/* Empty transaction, and aborted empty transaction */
var_dump($session->isInTransaction());
$session->startTransaction();
var_dump($session->isInTransaction());
$session->abortTransaction();
var_dump($session->isInTransaction());

/* Empty transaction, and committed empty transaction */
var_dump($session->isInTransaction());
$session->startTransaction();
var_dump($session->isInTransaction());
$session->commitTransaction();
var_dump($session->isInTransaction());
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Given that transactions are started lazily during the first command, how does this interact when the only operation is an abort or commit? I assume the driver is still sending something in this case and the server just registers it as a no-op?

Perhaps a question for @ShaneHarvey.


/* Aborted transaction with one operation */
var_dump($session->isInTransaction());
$session->startTransaction();
$bw = new \MongoDB\Driver\BulkWrite();
$bw->insert( [ '_id' => 0, 'msg' => 'Initial Value' ] );
$manager->executeBulkWrite(NS, $bw, ['session' => $session]);
var_dump($session->isInTransaction());
$session->abortTransaction();
var_dump($session->isInTransaction());

/* Committed transaction with one operation */
var_dump($session->isInTransaction());
$session->startTransaction();
$bw = new \MongoDB\Driver\BulkWrite();
$bw->insert( [ '_id' => 0, 'msg' => 'Initial Value' ] );
$manager->executeBulkWrite(NS, $bw, ['session' => $session]);
var_dump($session->isInTransaction());
$session->commitTransaction();
var_dump($session->isInTransaction());

?>
===DONE===
<?php exit(0); ?>
--EXPECTF--
bool(false)
bool(true)
bool(false)
bool(false)
bool(true)
bool(false)
bool(false)
bool(true)
bool(false)
bool(false)
bool(true)
bool(false)
===DONE===