diff --git a/system/Database/BaseConnection.php b/system/Database/BaseConnection.php index 6581dc7c5ac0..663f9c120a0c 100644 --- a/system/Database/BaseConnection.php +++ b/system/Database/BaseConnection.php @@ -897,6 +897,16 @@ public function transRollback(): bool return false; } + /** + * Reset transaction status - to restart transactions after strict mode failure + */ + public function resetTransStatus(): static + { + $this->transStatus = true; + + return $this; + } + /** * Begin Transaction */ diff --git a/tests/system/Database/Live/TransactionDBDebugTrueTest.php b/tests/system/Database/Live/TransactionDBDebugTrueTest.php index da77edb9b975..cbfa6a1ff289 100644 --- a/tests/system/Database/Live/TransactionDBDebugTrueTest.php +++ b/tests/system/Database/Live/TransactionDBDebugTrueTest.php @@ -208,6 +208,54 @@ public function testTransStrictFalse(): void $this->seeInDatabase('job', ['name' => 'Comedian']); } + public function testTransStrictTrueAndResetTransStatus(): void + { + $builder = $this->db->table('job'); + + // The first transaction group + $this->db->transStart(); + + $jobData = [ + 'name' => 'Grocery Sales', + 'description' => 'Discount!', + ]; + $builder->insert($jobData); + + $this->assertTrue($this->db->transStatus()); + + // Duplicate entry '1' for key 'PRIMARY' + $jobData = [ + 'id' => 1, + 'name' => 'Comedian', + 'description' => 'Theres something in your teeth', + ]; + $builder->insert($jobData); + + $this->assertFalse($this->db->transStatus()); + + $this->db->transComplete(); + + $this->dontSeeInDatabase('job', ['name' => 'Grocery Sales']); + + // Resets TransStatus + $this->db->resetTransStatus(); + + // The second transaction group + $this->db->transStart(); + + $jobData = [ + 'name' => 'Comedian', + 'description' => 'Theres something in your teeth', + ]; + $builder->insert($jobData); + + $this->assertTrue($this->db->transStatus()); + + $this->db->transComplete(); + + $this->seeInDatabase('job', ['name' => 'Comedian']); + } + public function testTransBegin(): void { $builder = $this->db->table('job'); diff --git a/user_guide_src/source/changelogs/v4.6.0.rst b/user_guide_src/source/changelogs/v4.6.0.rst index 481c4eace8f4..fe3e80b9b4fc 100644 --- a/user_guide_src/source/changelogs/v4.6.0.rst +++ b/user_guide_src/source/changelogs/v4.6.0.rst @@ -135,6 +135,8 @@ Others ------ - Added a new configuration ``foundRows`` for MySQLi to use ``MYSQLI_CLIENT_FOUND_ROWS``. +- Added the ``BaseConnection::resetTransStatus()`` method to reset the transaction + status. See :ref:`transactions-resetting-transaction-status` for details. Model ===== diff --git a/user_guide_src/source/database/transactions.rst b/user_guide_src/source/database/transactions.rst index 4fe44c8929e5..5c48f2806240 100644 --- a/user_guide_src/source/database/transactions.rst +++ b/user_guide_src/source/database/transactions.rst @@ -14,7 +14,7 @@ transactions. .. contents:: :local: - :depth: 2 + :depth: 3 CodeIgniter's Approach to Transactions ====================================== @@ -52,16 +52,33 @@ or failure of any given query. Strict Mode =========== -By default, CodeIgniter runs all transactions in Strict Mode. When strict -mode is enabled, if you are running multiple groups of transactions, if -one group fails all subsequent groups will be rolled back. If strict mode is -disabled, each group is treated independently, meaning a failure of one -group will not affect any others. +By default, CodeIgniter runs all transactions in Strict Mode. + +When strict mode is enabled, if you are running multiple groups of transactions, +if one group fails all subsequent groups will be rolled back. + +If strict mode is disabled, each group is treated independently, meaning a failure +of one group will not affect any others. Strict Mode can be disabled as follows: .. literalinclude:: transactions/002.php +.. _transactions-resetting-transaction-status: + +Resetting Transaction Status +---------------------------- + +.. versionadded:: 4.6.0 + +When strict mode is enabled, if one transaction fails, all subsequent transactions +will be rolled back. + +If you wan to restart transactions after a failure, you can reset the transaction +status: + +.. literalinclude:: transactions/009.php + .. _transactions-managing-errors: Managing Errors diff --git a/user_guide_src/source/database/transactions/009.php b/user_guide_src/source/database/transactions/009.php new file mode 100644 index 000000000000..6b92adf1793f --- /dev/null +++ b/user_guide_src/source/database/transactions/009.php @@ -0,0 +1,3 @@ +db->resetTransStatus();