1
1
Fork 0
mirror of https://code.mensbeam.com/MensBeam/Arsse.git synced 2024-12-22 21:22:40 +00:00

Make result sets single-use; change savewepoint exceptions

- Result sets are now single-use; this is required for PDO drivers (PDO result sets are not rewindable)
- Change savepoint exceptions to be simple database exceptions; codes remain the same
This commit is contained in:
J. King 2017-11-05 22:13:44 -05:00
parent 65963f228f
commit 9304f99032
8 changed files with 35 additions and 32 deletions

View file

@ -33,9 +33,10 @@ abstract class AbstractException extends \Exception {
"Db/Exception.paramTypeUnknown" => 10222, "Db/Exception.paramTypeUnknown" => 10222,
"Db/Exception.paramTypeMissing" => 10223, "Db/Exception.paramTypeMissing" => 10223,
"Db/Exception.engineErrorGeneral" => 10224, // this symbol may have engine-specific duplicates to accomodate engine-specific error string construction "Db/Exception.engineErrorGeneral" => 10224, // this symbol may have engine-specific duplicates to accomodate engine-specific error string construction
"Db/Exception.unknownSavepointStatus" => 10225, "Db/Exception.savepointStatusUnknown" => 10225,
"Db/ExceptionSavepoint.invalid" => 10226, "Db/Exception.savepointInvalid" => 10226,
"Db/ExceptionSavepoint.stale" => 10227, "Db/Exception.savepointStale" => 10227,
"Db/Exception.resultReused" => 10227,
"Db/ExceptionInput.missing" => 10231, "Db/ExceptionInput.missing" => 10231,
"Db/ExceptionInput.whitespace" => 10232, "Db/ExceptionInput.whitespace" => 10232,
"Db/ExceptionInput.tooLong" => 10233, "Db/ExceptionInput.tooLong" => 10233,

View file

@ -60,9 +60,9 @@ abstract class AbstractDriver implements Driver {
break; break;
case self::TR_COMMIT: case self::TR_COMMIT:
case self::TR_ROLLBACK: //@codeCoverageIgnore case self::TR_ROLLBACK: //@codeCoverageIgnore
throw new ExceptionSavepoint("stale", ['action' => "commit", 'index' => $index]); throw new Exception("savepointStale", ['action' => "commit", 'index' => $index]);
default: default:
throw new Exception("unknownSavepointStatus", $this->transStatus[$index]); //@codeCoverageIgnore throw new Exception("savepointStatusUnknown", $this->transStatus[$index]); // @codeCoverageIgnore
} }
if ($index==$this->transDepth) { if ($index==$this->transDepth) {
while ($this->transDepth > 0 && $this->transStatus[$this->transDepth] > self::TR_PEND) { while ($this->transDepth > 0 && $this->transStatus[$this->transDepth] > self::TR_PEND) {
@ -76,7 +76,7 @@ abstract class AbstractDriver implements Driver {
} }
return $out; return $out;
} else { } else {
throw new ExceptionSavepoint("invalid", ['action' => "commit", 'index' => $index]); throw new Exception("savepointInvalid", ['action' => "commit", 'index' => $index]);
} }
} }
@ -106,9 +106,9 @@ abstract class AbstractDriver implements Driver {
break; break;
case self::TR_COMMIT: case self::TR_COMMIT:
case self::TR_ROLLBACK: //@codeCoverageIgnore case self::TR_ROLLBACK: //@codeCoverageIgnore
throw new ExceptionSavepoint("stale", ['action' => "rollback", 'index' => $index]); throw new Exception("savepointStale", ['action' => "rollback", 'index' => $index]);
default: default:
throw new Exception("unknownSavepointStatus", $this->transStatus[$index]); //@codeCoverageIgnore throw new Exception("savepointStatusUnknown", $this->transStatus[$index]); // @codeCoverageIgnore
} }
if ($index==$this->transDepth) { if ($index==$this->transDepth) {
while ($this->transDepth > 0 && $this->transStatus[$this->transDepth] > self::TR_PEND) { while ($this->transDepth > 0 && $this->transStatus[$this->transDepth] > self::TR_PEND) {
@ -122,7 +122,7 @@ abstract class AbstractDriver implements Driver {
} }
return $out; return $out;
} else { } else {
throw new ExceptionSavepoint("invalid", ['action' => "rollback", 'index' => $index]); throw new Exception("savepointInvalid", ['action' => "rollback", 'index' => $index]);
} }
} }

View file

@ -1,6 +0,0 @@
<?php
declare(strict_types=1);
namespace JKingWeb\Arsse\Db;
class ExceptionSavepoint extends \JKingWeb\Arsse\AbstractException {
}

View file

@ -1,6 +1,7 @@
<?php <?php
declare(strict_types=1); declare(strict_types=1);
namespace JKingWeb\Arsse\Db\SQLite3; namespace JKingWeb\Arsse\Db\SQLite3;
use JKingWeb\Arsse\Db\Exception;
class Result implements \JKingWeb\Arsse\Db\Result { class Result implements \JKingWeb\Arsse\Db\Result {
protected $st; protected $st;
@ -27,11 +28,7 @@ class Result implements \JKingWeb\Arsse\Db\Result {
} }
public function getAll(): array { public function getAll(): array {
$out = []; return iterator_to_array($this, false);
foreach ($this as $row) {
$out [] = $row;
}
return $out;
} }
public function changes() { public function changes() {
@ -80,8 +77,8 @@ class Result implements \JKingWeb\Arsse\Db\Result {
} }
public function rewind() { public function rewind() {
$this->pos = 0; if ($this->pos) {
$this->cur = null; throw new Exception("resultReused");
$this->set->reset(); }
} }
} }

View file

@ -123,7 +123,10 @@ return [
other {Automatic updating of the {driver_name} database failed because its version, {current}, is newer than the requested version, {target}} other {Automatic updating of the {driver_name} database failed because its version, {current}, is newer than the requested version, {target}}
}', }',
'Exception.JKingWeb/Arsse/Db/Exception.engineErrorGeneral' => '{0}', 'Exception.JKingWeb/Arsse/Db/Exception.engineErrorGeneral' => '{0}',
'Exception.JKingWeb/Arsse/Db/Exception.unknownSavepointStatus' => 'Savepoint status code {0} not implemented', 'Exception.JKingWeb/Arsse/Db/Exception.savepointStatusUnknown' => 'Savepoint status code {0} not implemented',
'Exception.JKingWeb/Arsse/Db/Exception.savepointInvalid' => 'Tried to {action} invalid savepoint {index}',
'Exception.JKingWeb/Arsse/Db/Exception.savepointStale' => 'Tried to {action} stale savepoint {index}',
'Exception.JKingWeb/Arsse/Db/Exception.resultReused' => 'Result set already iterated',
'Exception.JKingWeb/Arsse/Db/ExceptionInput.missing' => 'Required field "{field}" missing while performing action "{action}"', 'Exception.JKingWeb/Arsse/Db/ExceptionInput.missing' => 'Required field "{field}" missing while performing action "{action}"',
'Exception.JKingWeb/Arsse/Db/ExceptionInput.whitespace' => 'Field "{field}" of action "{action}" may not contain only whitespace', 'Exception.JKingWeb/Arsse/Db/ExceptionInput.whitespace' => 'Field "{field}" of action "{action}" may not contain only whitespace',
'Exception.JKingWeb/Arsse/Db/ExceptionInput.tooLong' => 'Field "{field}" of action "{action}" has a maximum length of {max}', 'Exception.JKingWeb/Arsse/Db/ExceptionInput.tooLong' => 'Field "{field}" of action "{action}" has a maximum length of {max}',
@ -136,8 +139,6 @@ return [
'Exception.JKingWeb/Arsse/Db/ExceptionInput.engineConstraintViolation' => '{0}', 'Exception.JKingWeb/Arsse/Db/ExceptionInput.engineConstraintViolation' => '{0}',
'Exception.JKingWeb/Arsse/Db/ExceptionInput.engineTypeViolation' => '{0}', 'Exception.JKingWeb/Arsse/Db/ExceptionInput.engineTypeViolation' => '{0}',
'Exception.JKingWeb/Arsse/Db/ExceptionTimeout.general' => '{0}', 'Exception.JKingWeb/Arsse/Db/ExceptionTimeout.general' => '{0}',
'Exception.JKingWeb/Arsse/Db/ExceptionSavepoint.invalid' => 'Tried to {action} invalid savepoint {index}',
'Exception.JKingWeb/Arsse/Db/ExceptionSavepoint.stale' => 'Tried to {action} stale savepoint {index}',
'Exception.JKingWeb/Arsse/User/Exception.alreadyExists' => 'Could not perform action "{action}" because the user {user} already exists', 'Exception.JKingWeb/Arsse/User/Exception.alreadyExists' => 'Could not perform action "{action}" because the user {user} already exists',
'Exception.JKingWeb/Arsse/User/Exception.doesNotExist' => 'Could not perform action "{action}" because the user {user} does not exist', 'Exception.JKingWeb/Arsse/User/Exception.doesNotExist' => 'Could not perform action "{action}" because the user {user} does not exist',
'Exception.JKingWeb/Arsse/User/Exception.authMissing' => 'Please log in to proceed', 'Exception.JKingWeb/Arsse/User/Exception.authMissing' => 'Please log in to proceed',

View file

@ -117,14 +117,14 @@ class TestDbDriverSQLite3 extends Test\AbstractTest {
public function testReleaseASavepoint() { public function testReleaseASavepoint() {
$this->assertEquals(1, $this->drv->savepointCreate()); $this->assertEquals(1, $this->drv->savepointCreate());
$this->assertEquals(true, $this->drv->savepointRelease()); $this->assertEquals(true, $this->drv->savepointRelease());
$this->assertException("invalid", "Db", "ExceptionSavepoint"); $this->assertException("savepointInvalid", "Db");
$this->drv->savepointRelease(); $this->drv->savepointRelease();
} }
public function testUndoASavepoint() { public function testUndoASavepoint() {
$this->assertEquals(1, $this->drv->savepointCreate()); $this->assertEquals(1, $this->drv->savepointCreate());
$this->assertEquals(true, $this->drv->savepointUndo()); $this->assertEquals(true, $this->drv->savepointUndo());
$this->assertException("invalid", "Db", "ExceptionSavepoint"); $this->assertException("savepointInvalid", "Db");
$this->drv->savepointUndo(); $this->drv->savepointUndo();
} }
@ -141,7 +141,7 @@ class TestDbDriverSQLite3 extends Test\AbstractTest {
$this->assertTrue($this->drv->savepointRelease(6)); $this->assertTrue($this->drv->savepointRelease(6));
$this->assertEquals(3, $this->drv->savepointCreate()); $this->assertEquals(3, $this->drv->savepointCreate());
$this->assertTrue($this->drv->savepointRelease(2)); $this->assertTrue($this->drv->savepointRelease(2));
$this->assertException("stale", "Db", "ExceptionSavepoint"); $this->assertException("savepointStale", "Db");
$this->drv->savepointRelease(2); $this->drv->savepointRelease(2);
} }
@ -152,7 +152,7 @@ class TestDbDriverSQLite3 extends Test\AbstractTest {
$this->assertEquals(4, $this->drv->savepointCreate()); $this->assertEquals(4, $this->drv->savepointCreate());
$this->assertTrue($this->drv->savepointRelease(2)); $this->assertTrue($this->drv->savepointRelease(2));
$this->assertFalse($this->drv->savepointUndo(3)); $this->assertFalse($this->drv->savepointUndo(3));
$this->assertException("stale", "Db", "ExceptionSavepoint"); $this->assertException("savepointStale", "Db");
$this->drv->savepointUndo(2); $this->drv->savepointUndo(2);
} }

View file

@ -51,10 +51,11 @@ class TestDbResultSQLite3 extends Test\AbstractTest {
foreach ($test as $row) { foreach ($test as $row) {
$rows[] = $row['col']; $rows[] = $row['col'];
} }
$this->assertEquals([1,2,3], $rows);
$this->assertException("resultReused", "Db");
foreach ($test as $row) { foreach ($test as $row) {
$rows[] = $row['col']; $rows[] = $row['col'];
} }
$this->assertEquals([1,2,3,1,2,3], $rows);
} }
public function testGetSingleValues() { public function testGetSingleValues() {
@ -85,6 +86,15 @@ class TestDbResultSQLite3 extends Test\AbstractTest {
$this->assertEquals($rows[0], $test->getRow()); $this->assertEquals($rows[0], $test->getRow());
$this->assertEquals($rows[1], $test->getRow()); $this->assertEquals($rows[1], $test->getRow());
$this->assertSame(null, $test->getRow()); $this->assertSame(null, $test->getRow());
}
public function testGetAllRows() {
$set = $this->c->query("SELECT '2112' as album, '2112' as track union select 'Clockwork Angels' as album, 'The Wreckers' as track");
$rows = [
['album' => '2112', 'track' => '2112'],
['album' => 'Clockwork Angels', 'track' => 'The Wreckers'],
];
$test = new Db\SQLite3\Result($set);
$this->assertEquals($rows, $test->getAll()); $this->assertEquals($rows, $test->getAll());
} }
} }

View file

@ -47,7 +47,7 @@ class TestTransaction extends Test\AbstractTest {
} }
public function testIgnoreRollbackErrors() { public function testIgnoreRollbackErrors() {
Phake::when($this->drv)->savepointUndo->thenThrow(new Db\ExceptionSavepoint("stale")); Phake::when($this->drv)->savepointUndo->thenThrow(new Db\Exception("savepointStale"));
$tr1 = new Transaction($this->drv); $tr1 = new Transaction($this->drv);
$tr2 = new Transaction($this->drv); $tr2 = new Transaction($this->drv);
unset($tr1, $tr2); // no exception should bubble up unset($tr1, $tr2); // no exception should bubble up