Skip to content

Commit e1bcf24

Browse files
authored
Merge pull request laminas#211 from Ocramius/fix/laminas#210-correct-resultset-cloning-to-avoid-iterator-rewind-issues
Ensure that each `Adapter#query()` call produces a new `ResultSet`
2 parents a81d9e2 + 21b5f5d commit e1bcf24

File tree

2 files changed

+36
-14
lines changed

2 files changed

+36
-14
lines changed

src/Adapter/Adapter.php

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -195,9 +195,12 @@ public function query(
195195
}
196196

197197
if ($result instanceof Driver\ResultInterface && $result->isQueryResult()) {
198-
$resultSet = $resultPrototype !== null ? clone $resultPrototype : $this->queryResultSetPrototype;
199-
$resultSet->initialize($result);
200-
return $resultSet;
198+
$resultSet = $resultPrototype ?? $this->queryResultSetPrototype;
199+
$resultSetCopy = clone $resultSet;
200+
201+
$resultSetCopy->initialize($result);
202+
203+
return $resultSetCopy;
201204
}
202205

203206
return $result;

test/unit/Adapter/AdapterTest.php

Lines changed: 30 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,31 +31,31 @@
3131

3232
class AdapterTest extends TestCase
3333
{
34-
/** @var MockObject */
34+
/** @var MockObject&DriverInterface */
3535
protected $mockDriver;
3636

37-
/** @var MockObject */
37+
/** @var MockObject&PlatformInterface */
3838
protected $mockPlatform;
3939

40-
/** @var MockObject */
40+
/** @var MockObject&ConnectionInterface */
4141
protected $mockConnection;
4242

43-
/** @var MockObject */
43+
/** @var MockObject&StatementInterface */
4444
protected $mockStatement;
4545

4646
/** @var Adapter */
4747
protected $adapter;
4848

4949
protected function setUp(): void
5050
{
51-
$this->mockDriver = $this->getMockBuilder(DriverInterface::class)->getMock();
52-
$this->mockConnection = $this->getMockBuilder(ConnectionInterface::class)->getMock();
53-
$this->mockDriver->expects($this->any())->method('checkEnvironment')->will($this->returnValue(true));
54-
$this->mockDriver->expects($this->any())->method('getConnection')
51+
$this->mockDriver = $this->createMock(DriverInterface::class);
52+
$this->mockConnection = $this->createMock(ConnectionInterface::class);
53+
$this->mockDriver->method('checkEnvironment')->will($this->returnValue(true));
54+
$this->mockDriver->method('getConnection')
5555
->will($this->returnValue($this->mockConnection));
56-
$this->mockPlatform = $this->getMockBuilder(PlatformInterface::class)->getMock();
57-
$this->mockStatement = $this->getMockBuilder(StatementInterface::class)->getMock();
58-
$this->mockDriver->expects($this->any())->method('createStatement')
56+
$this->mockPlatform = $this->createMock(PlatformInterface::class);
57+
$this->mockStatement = $this->createMock(StatementInterface::class);
58+
$this->mockDriver->method('createStatement')
5959
->will($this->returnValue($this->mockStatement));
6060

6161
$this->adapter = new Adapter($this->mockDriver, $this->mockPlatform);
@@ -222,6 +222,25 @@ public function testQueryWhenPreparedProducesStatement()
222222
self::assertSame($this->mockStatement, $s);
223223
}
224224

225+
/** @group #210 */
226+
public function testProducedResultSetPrototypeIsDifferentForEachQuery()
227+
{
228+
$statement = $this->createMock(StatementInterface::class);
229+
$result = $this->createMock(ResultInterface::class);
230+
231+
$this->mockDriver->method('createStatement')
232+
->willReturn($statement);
233+
$this->mockStatement->method('execute')
234+
->willReturn($result);
235+
$result->method('isQueryResult')
236+
->willReturn(true);
237+
238+
self::assertNotSame(
239+
$this->adapter->query('SELECT foo', []),
240+
$this->adapter->query('SELECT foo', [])
241+
);
242+
}
243+
225244
/**
226245
* @testdox unit test: Test query() in prepare mode, with array of parameters, produces a result object
227246
* @covers \Laminas\Db\Adapter\Adapter::query

0 commit comments

Comments
 (0)