From bf5c757f8aa7bb35e1adf9ad6b4d926444a0bf20 Mon Sep 17 00:00:00 2001 From: Grundik Date: Sat, 17 Dec 2022 17:25:00 +0300 Subject: [PATCH] Fix data loss on multiple Result->rewind() Signed-off-by: Grundik --- src/Adapter/Driver/Pdo/Result.php | 8 +++-- test/unit/Adapter/Driver/Pdo/ResultTest.php | 33 +++++++++++++++++++++ 2 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/Adapter/Driver/Pdo/Result.php b/src/Adapter/Driver/Pdo/Result.php index be729cda..870afa08 100644 --- a/src/Adapter/Driver/Pdo/Result.php +++ b/src/Adapter/Driver/Pdo/Result.php @@ -201,9 +201,11 @@ public function rewind() 'This result is a forward only result set, calling rewind() after moving forward is not supported' ); } - $this->currentData = $this->resource->fetch($this->fetchMode); - $this->currentComplete = true; - $this->position = 0; + if (! $this->currentComplete) { + $this->currentData = $this->resource->fetch($this->fetchMode); + $this->currentComplete = true; + } + $this->position = 0; } /** diff --git a/test/unit/Adapter/Driver/Pdo/ResultTest.php b/test/unit/Adapter/Driver/Pdo/ResultTest.php index 4ca159b3..51014736 100644 --- a/test/unit/Adapter/Driver/Pdo/ResultTest.php +++ b/test/unit/Adapter/Driver/Pdo/ResultTest.php @@ -5,9 +5,11 @@ use Laminas\Db\Adapter\Driver\Pdo\Result; use Laminas\Db\Adapter\Exception\InvalidArgumentException; use PDO; +use PDOStatement; use PHPUnit\Framework\TestCase; use stdClass; +use function assert; use function uniqid; /** @@ -80,4 +82,35 @@ public function testFetchModeRange() self::assertEquals(11, $result->getFetchMode()); self::assertInstanceOf('stdClass', $result->current()); } + + public function testMultipleRewind() + { + $data = [ + ['test' => 1], + ['test' => 2], + ]; + $position = 0; + + $stub = $this->getMockBuilder('PDOStatement')->getMock(); + assert($stub instanceof PDOStatement); // to suppress IDE type warnings + $stub->expects($this->any()) + ->method('fetch') + ->will($this->returnCallback(function () use ($data, &$position) { + return $data[$position++]; + })); + $result = new Result(); + $result->initialize($stub, null); + + $result->rewind(); + $result->rewind(); + + $this->assertEquals(0, $result->key()); + $this->assertEquals(1, $position); + $this->assertEquals($data[0], $result->current()); + + $result->next(); + $this->assertEquals(1, $result->key()); + $this->assertEquals(2, $position); + $this->assertEquals($data[1], $result->current()); + } }