diff --git a/lib/Db/AbstractDriver.php b/lib/Db/AbstractDriver.php index fc2ac4ce..3d461997 100644 --- a/lib/Db/AbstractDriver.php +++ b/lib/Db/AbstractDriver.php @@ -15,16 +15,14 @@ abstract class AbstractDriver implements Driver { } public function begin(): bool { - $this->exec("SAVEPOINT newssync_".($this->transDepth)); - $this->transDepth += 1; + $this->exec("SAVEPOINT newssync_".(++$this->transDepth)); return true; } public function commit(bool $all = false): bool { if($this->transDepth==0) return false; if(!$all) { - $this->exec("RELEASE SAVEPOINT newssync_".($this->transDepth - 1)); - $this->transDepth -= 1; + $this->exec("RELEASE SAVEPOINT newssync_".($this->transDepth--)); } else { $this->exec("COMMIT TRANSACTION"); $this->transDepth = 0; @@ -35,11 +33,9 @@ abstract class AbstractDriver implements Driver { public function rollback(bool $all = false): bool { if($this->transDepth==0) return false; if(!$all) { - $this->exec("ROLLBACK TRANSACTION TO SAVEPOINT newssync_".($this->transDepth - 1)); + $this->exec("ROLLBACK TRANSACTION TO SAVEPOINT newssync_".($this->transDepth)); // rollback to savepoint does not collpase the savepoint - $this->commit(); - $this->transDepth -= 1; - if($this->transDepth==0) $this->exec("ROLLBACK TRANSACTION"); + $this->exec("RELEASE SAVEPOINT newssync_".($this->transDepth--)); } else { $this->exec("ROLLBACK TRANSACTION"); $this->transDepth = 0; diff --git a/tests/Db/SQLite3/TestDbDriverSQLite3.php b/tests/Db/SQLite3/TestDbDriverSQLite3.php index 1ea3e139..2cbbe110 100644 --- a/tests/Db/SQLite3/TestDbDriverSQLite3.php +++ b/tests/Db/SQLite3/TestDbDriverSQLite3.php @@ -92,4 +92,158 @@ class TestDbDriverSQLite3 extends \PHPUnit\Framework\TestCase { $this->assertException("engineErrorGeneral", "Db"); $s = $this->drv->prepare("This is an invalid query", "int", "int"); } + + function testBeginTransaction() { + $select = "SELECT count(*) FROM test"; + $insert = "INSERT INTO test(id) values(null)"; + $ch = new \SQLite3($this->data->conf->dbSQLite3File); + $this->drv->exec("CREATE TABLE test(id integer primary key)"); + $this->drv->begin(); + $this->drv->query($insert); + $this->assertEquals(1, $this->drv->query($select)->getValue()); + $this->assertEquals(0, $ch->querySingle($select)); + $this->drv->query($insert); + $this->assertEquals(2, $this->drv->query($select)->getValue()); + $this->assertEquals(0, $ch->querySingle($select)); + } + + function testCommitTransaction() { + $select = "SELECT count(*) FROM test"; + $insert = "INSERT INTO test(id) values(null)"; + $ch = new \SQLite3($this->data->conf->dbSQLite3File); + $this->drv->exec("CREATE TABLE test(id integer primary key)"); + $this->drv->begin(); + $this->drv->query($insert); + $this->assertEquals(1, $this->drv->query($select)->getValue()); + $this->assertEquals(0, $ch->querySingle($select)); + $this->drv->commit(); + $this->assertEquals(1, $this->drv->query($select)->getValue()); + $this->assertEquals(1, $ch->querySingle($select)); + } + + function testRollbackTransaction() { + $select = "SELECT count(*) FROM test"; + $insert = "INSERT INTO test(id) values(null)"; + $ch = new \SQLite3($this->data->conf->dbSQLite3File); + $this->drv->exec("CREATE TABLE test(id integer primary key)"); + $this->drv->begin(); + $this->drv->query($insert); + $this->assertEquals(1, $this->drv->query($select)->getValue()); + $this->assertEquals(0, $ch->querySingle($select)); + $this->drv->rollback(); + $this->assertEquals(0, $this->drv->query($select)->getValue()); + $this->assertEquals(0, $ch->querySingle($select)); + } + + function testBeginChainedTransactions() { + $select = "SELECT count(*) FROM test"; + $insert = "INSERT INTO test(id) values(null)"; + $ch = new \SQLite3($this->data->conf->dbSQLite3File); + $this->drv->exec("CREATE TABLE test(id integer primary key)"); + $this->drv->begin(); + $this->drv->query($insert); + $this->assertEquals(1, $this->drv->query($select)->getValue()); + $this->assertEquals(0, $ch->querySingle($select)); + $this->drv->begin(); + $this->drv->query($insert); + $this->assertEquals(2, $this->drv->query($select)->getValue()); + $this->assertEquals(0, $ch->querySingle($select)); + } + + function testCommitChainedTransactions() { + $select = "SELECT count(*) FROM test"; + $insert = "INSERT INTO test(id) values(null)"; + $ch = new \SQLite3($this->data->conf->dbSQLite3File); + $this->drv->exec("CREATE TABLE test(id integer primary key)"); + $this->drv->begin(); + $this->drv->query($insert); + $this->assertEquals(1, $this->drv->query($select)->getValue()); + $this->assertEquals(0, $ch->querySingle($select)); + $this->drv->begin(); + $this->drv->query($insert); + $this->assertEquals(2, $this->drv->query($select)->getValue()); + $this->assertEquals(0, $ch->querySingle($select)); + $this->drv->commit(); + $this->assertEquals(0, $ch->querySingle($select)); + $this->drv->commit(); + $this->assertEquals(2, $ch->querySingle($select)); + } + + function testRollbackChainedTransactions() { + $select = "SELECT count(*) FROM test"; + $insert = "INSERT INTO test(id) values(null)"; + $ch = new \SQLite3($this->data->conf->dbSQLite3File); + $this->drv->exec("CREATE TABLE test(id integer primary key)"); + $this->drv->begin(); + $this->drv->query($insert); + $this->assertEquals(1, $this->drv->query($select)->getValue()); + $this->assertEquals(0, $ch->querySingle($select)); + $this->drv->begin(); + $this->drv->query($insert); + $this->assertEquals(2, $this->drv->query($select)->getValue()); + $this->assertEquals(0, $ch->querySingle($select)); + $this->drv->rollback(); + $this->assertEquals(1, $this->drv->query($select)->getValue()); + $this->assertEquals(0, $ch->querySingle($select)); + $this->drv->rollback(); + $this->assertEquals(0, $this->drv->query($select)->getValue()); + $this->assertEquals(0, $ch->querySingle($select)); + } + + function testPartiallyRollbackChainedTransactions() { + $select = "SELECT count(*) FROM test"; + $insert = "INSERT INTO test(id) values(null)"; + $ch = new \SQLite3($this->data->conf->dbSQLite3File); + $this->drv->exec("CREATE TABLE test(id integer primary key)"); + $this->drv->begin(); + $this->drv->query($insert); + $this->assertEquals(1, $this->drv->query($select)->getValue()); + $this->assertEquals(0, $ch->querySingle($select)); + $this->drv->begin(); + $this->drv->query($insert); + $this->assertEquals(2, $this->drv->query($select)->getValue()); + $this->assertEquals(0, $ch->querySingle($select)); + $this->drv->rollback(); + $this->assertEquals(1, $this->drv->query($select)->getValue()); + $this->assertEquals(0, $ch->querySingle($select)); + $this->drv->commit(); + $this->assertEquals(1, $this->drv->query($select)->getValue()); + $this->assertEquals(1, $ch->querySingle($select)); + } + + function testFullyRollbackChainedTransactions() { + $select = "SELECT count(*) FROM test"; + $insert = "INSERT INTO test(id) values(null)"; + $ch = new \SQLite3($this->data->conf->dbSQLite3File); + $this->drv->exec("CREATE TABLE test(id integer primary key)"); + $this->drv->begin(); + $this->drv->query($insert); + $this->assertEquals(1, $this->drv->query($select)->getValue()); + $this->assertEquals(0, $ch->querySingle($select)); + $this->drv->begin(); + $this->drv->query($insert); + $this->assertEquals(2, $this->drv->query($select)->getValue()); + $this->assertEquals(0, $ch->querySingle($select)); + $this->drv->rollback(true); + $this->assertEquals(0, $this->drv->query($select)->getValue()); + $this->assertEquals(0, $ch->querySingle($select)); + } + + function testFullyCommitChainedTransactions() { + $select = "SELECT count(*) FROM test"; + $insert = "INSERT INTO test(id) values(null)"; + $ch = new \SQLite3($this->data->conf->dbSQLite3File); + $this->drv->exec("CREATE TABLE test(id integer primary key)"); + $this->drv->begin(); + $this->drv->query($insert); + $this->assertEquals(1, $this->drv->query($select)->getValue()); + $this->assertEquals(0, $ch->querySingle($select)); + $this->drv->begin(); + $this->drv->query($insert); + $this->assertEquals(2, $this->drv->query($select)->getValue()); + $this->assertEquals(0, $ch->querySingle($select)); + $this->drv->commit(true); + $this->assertEquals(2, $this->drv->query($select)->getValue()); + $this->assertEquals(2, $ch->querySingle($select)); + } } \ No newline at end of file