diff --git a/src/Adapter/Driver/Pdo/Result.php b/src/Adapter/Driver/Pdo/Result.php index 6c55f7f6..54d37647 100644 --- a/src/Adapter/Driver/Pdo/Result.php +++ b/src/Adapter/Driver/Pdo/Result.php @@ -81,7 +81,7 @@ class Result implements Iterator, ResultInterface /** @var string|int|false|null */ protected $generatedValue; - protected Closure|int $rowCount; + protected Closure|int|null $rowCount = null; /** * Initialize @@ -91,7 +91,7 @@ class Result implements Iterator, ResultInterface public function initialize( PDOStatement $resource, $generatedValue, - Closure|int $rowCount = 0 + Closure|int|null $rowCount = null ): ResultInterface&Result { $this->resource = $resource; $this->generatedValue = $generatedValue; @@ -250,7 +250,6 @@ public function count() if (is_int($this->rowCount)) { return $this->rowCount; } - /** @phpstan-ignore instanceof.alwaysTrue */ if ($this->rowCount instanceof Closure) { $this->rowCount = (int) ($this->rowCount)(); } else { diff --git a/test/unit/Adapter/Driver/Pdo/ResultTest.php b/test/unit/Adapter/Driver/Pdo/ResultTest.php index 85c38a9b..1044874a 100644 --- a/test/unit/Adapter/Driver/Pdo/ResultTest.php +++ b/test/unit/Adapter/Driver/Pdo/ResultTest.php @@ -17,6 +17,7 @@ use function uniqid; #[CoversMethod(Result::class, 'current')] +#[CoversMethod(Result::class, 'count')] #[Group('result-pdo')] final class ResultTest extends TestCase { @@ -108,4 +109,74 @@ public function testMultipleRewind(): void $this->assertEquals(2, $position); $this->assertEquals($data[1], $result->current()); } + + public function testCountWithNoRowCountFallsBackToStatementRowCount(): void + { + $stub = $this->getMockBuilder(PDOStatement::class)->getMock(); + $stub->expects($this->once()) + ->method('rowCount') + ->willReturn(5); + + $result = new Result(); + $result->initialize($stub, null); + + self::assertSame(5, $result->count()); + } + + public function testCountWithClosureInvokesClosureAndReturnsValue(): void + { + $stub = $this->getMockBuilder(PDOStatement::class)->getMock(); + $stub->expects($this->never())->method('rowCount'); + + $rowCount = static fn(): int => 42; + + $result = new Result(); + $result->initialize($stub, null, $rowCount); + + self::assertSame(42, $result->count()); + } + + public function testCountWithIntReturnsProvidedValue(): void + { + $stub = $this->getMockBuilder(PDOStatement::class)->getMock(); + $stub->expects($this->never())->method('rowCount'); + + $result = new Result(); + $result->initialize($stub, null, 10); + + self::assertSame(10, $result->count()); + } + + public function testCountCachesResultFromClosure(): void + { + $callCount = 0; + $rowCount = static function () use (&$callCount): int { + $callCount++; + return 7; + }; + + $stub = $this->getMockBuilder(PDOStatement::class)->getMock(); + + $result = new Result(); + $result->initialize($stub, null, $rowCount); + + $result->count(); + $result->count(); + + self::assertSame(1, $callCount); + } + + public function testCountCachesResultFromStatementRowCount(): void + { + $stub = $this->getMockBuilder(PDOStatement::class)->getMock(); + $stub->expects($this->once())->method('rowCount')->willReturn(3); + + $result = new Result(); + $result->initialize($stub, null); + + $result->count(); + $result->count(); + + self::assertSame(3, $result->count()); + } }