Commit 078d32ea authored by Ian Jenkins's avatar Ian Jenkins

Extract statement iterator into own class

parent 22b2b6b6
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
namespace Doctrine\DBAL\Driver\IBMDB2; namespace Doctrine\DBAL\Driver\IBMDB2;
use Doctrine\DBAL\Driver\Statement; use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Driver\StatementIterator;
class DB2Statement implements \IteratorAggregate, Statement class DB2Statement implements \IteratorAggregate, Statement
{ {
...@@ -199,9 +200,7 @@ class DB2Statement implements \IteratorAggregate, Statement ...@@ -199,9 +200,7 @@ class DB2Statement implements \IteratorAggregate, Statement
*/ */
public function getIterator() public function getIterator()
{ {
while ($row = $this->fetch()) { return new StatementIterator($this);
yield $row;
}
} }
/** /**
......
...@@ -20,6 +20,7 @@ ...@@ -20,6 +20,7 @@
namespace Doctrine\DBAL\Driver\Mysqli; namespace Doctrine\DBAL\Driver\Mysqli;
use Doctrine\DBAL\Driver\Statement; use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Driver\StatementIterator;
use PDO; use PDO;
/** /**
...@@ -406,8 +407,6 @@ class MysqliStatement implements \IteratorAggregate, Statement ...@@ -406,8 +407,6 @@ class MysqliStatement implements \IteratorAggregate, Statement
*/ */
public function getIterator() public function getIterator()
{ {
while ($row = $this->fetch()) { return new StatementIterator($this);
yield $row;
}
} }
} }
...@@ -37,7 +37,7 @@ class OCI8Connection implements Connection, ServerInfoAwareConnection ...@@ -37,7 +37,7 @@ class OCI8Connection implements Connection, ServerInfoAwareConnection
/** /**
* @var integer * @var integer
*/ */
protected $executeMode; protected $executeMode = OCI_COMMIT_ON_SUCCESS;
/** /**
* Creates a Connection to an Oracle Database using oci8 extension. * Creates a Connection to an Oracle Database using oci8 extension.
...@@ -57,8 +57,6 @@ class OCI8Connection implements Connection, ServerInfoAwareConnection ...@@ -57,8 +57,6 @@ class OCI8Connection implements Connection, ServerInfoAwareConnection
define('OCI_NO_AUTO_COMMIT', 0); define('OCI_NO_AUTO_COMMIT', 0);
} }
$this->executeMode = OCI_COMMIT_ON_SUCCESS;
$this->dbh = $persistent $this->dbh = $persistent
? @oci_pconnect($username, $password, $db, $charset, $sessionMode) ? @oci_pconnect($username, $password, $db, $charset, $sessionMode)
: @oci_connect($username, $password, $db, $charset, $sessionMode); : @oci_connect($username, $password, $db, $charset, $sessionMode);
......
...@@ -20,7 +20,8 @@ ...@@ -20,7 +20,8 @@
namespace Doctrine\DBAL\Driver\OCI8; namespace Doctrine\DBAL\Driver\OCI8;
use Doctrine\DBAL\Driver\Statement; use Doctrine\DBAL\Driver\Statement;
use \IteratorAggregate; use Doctrine\DBAL\Driver\StatementIterator;
use IteratorAggregate;
use PDO; use PDO;
/** /**
...@@ -370,9 +371,7 @@ class OCI8Statement implements IteratorAggregate, Statement ...@@ -370,9 +371,7 @@ class OCI8Statement implements IteratorAggregate, Statement
*/ */
public function getIterator() public function getIterator()
{ {
while ($row = $this->fetch()) { return new StatementIterator($this);
yield $row;
}
} }
/** /**
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
namespace Doctrine\DBAL\Driver\SQLAnywhere; namespace Doctrine\DBAL\Driver\SQLAnywhere;
use Doctrine\DBAL\Driver\StatementIterator;
use IteratorAggregate; use IteratorAggregate;
use PDO; use PDO;
use Doctrine\DBAL\Driver\Statement; use Doctrine\DBAL\Driver\Statement;
...@@ -278,9 +279,7 @@ class SQLAnywhereStatement implements IteratorAggregate, Statement ...@@ -278,9 +279,7 @@ class SQLAnywhereStatement implements IteratorAggregate, Statement
*/ */
public function getIterator() public function getIterator()
{ {
while ($row = $this->fetch()) { return new StatementIterator($this);
yield $row;
}
} }
/** /**
......
...@@ -19,6 +19,7 @@ ...@@ -19,6 +19,7 @@
namespace Doctrine\DBAL\Driver\SQLSrv; namespace Doctrine\DBAL\Driver\SQLSrv;
use Doctrine\DBAL\Driver\StatementIterator;
use PDO; use PDO;
use IteratorAggregate; use IteratorAggregate;
use Doctrine\DBAL\Driver\Statement; use Doctrine\DBAL\Driver\Statement;
...@@ -295,9 +296,7 @@ class SQLSrvStatement implements IteratorAggregate, Statement ...@@ -295,9 +296,7 @@ class SQLSrvStatement implements IteratorAggregate, Statement
*/ */
public function getIterator() public function getIterator()
{ {
while ($row = $this->fetch()) { return new StatementIterator($this);
yield $row;
}
} }
/** /**
......
<?php
namespace Doctrine\DBAL\Driver;
class StatementIterator implements \IteratorAggregate
{
/**
* @var Statement
*/
private $statement;
/**
* @param Statement $statement
*/
public function __construct(Statement $statement)
{
$this->statement = $statement;
}
/**
* {@inheritdoc}
*/
public function getIterator()
{
while (false !== ($result = $this->statement->fetch())) {
yield $result;
}
}
}
<?php
namespace Doctrine\Tests\DBAL\Driver;
use Doctrine\DBAL\Driver\Statement;
use Doctrine\DBAL\Driver\StatementIterator;
class StatementIteratorTest extends \Doctrine\Tests\DbalTestCase
{
public function testGettingIteratorDoesNotCallFetch()
{
$stmt = $this->createMock(Statement::class);
$stmt->expects($this->never())->method('fetch');
$stmt->expects($this->never())->method('fetchAll');
$stmt->expects($this->never())->method('fetchColumn');
$stmtIterator = new StatementIterator($stmt);
$stmtIterator->getIterator();
}
public function testIterationCallsFetchOncePerStep()
{
$values = ['foo', '', 'bar', '0', 'baz', 0, 'qux', null, 'quz', false, 'impossible'];
$calls = 0;
$stmt = $this->createMock(Statement::class);
$stmt->expects($this->exactly(10))
->method('fetch')
->willReturnCallback(function() use ($values, &$calls) {
$value = $values[$calls];
$calls++;
return $value;
});
$stmtIterator = new StatementIterator($stmt);
foreach ($stmtIterator as $i => $_) {
$this->assertEquals($i + 1, $calls);
}
}
}
...@@ -3,19 +3,8 @@ ...@@ -3,19 +3,8 @@
namespace Doctrine\Tests\DBAL\Functional; namespace Doctrine\Tests\DBAL\Functional;
use Doctrine\DBAL\Connection; use Doctrine\DBAL\Connection;
use Doctrine\DBAL\Driver\IBMDB2\DB2Connection;
use Doctrine\DBAL\Driver\IBMDB2\DB2Statement;
use Doctrine\DBAL\Driver\Mysqli\MysqliConnection;
use Doctrine\DBAL\Driver\Mysqli\MysqliStatement;
use Doctrine\DBAL\Driver\OCI8\OCI8Connection;
use Doctrine\DBAL\Driver\OCI8\OCI8Statement;
use Doctrine\DBAL\Driver\SQLAnywhere\SQLAnywhereConnection;
use Doctrine\DBAL\Driver\SQLAnywhere\SQLAnywhereStatement;
use Doctrine\DBAL\Driver\SQLSrv\SQLSrvConnection;
use Doctrine\DBAL\Driver\SQLSrv\SQLSrvStatement;
use Doctrine\DBAL\Platforms\AbstractPlatform; use Doctrine\DBAL\Platforms\AbstractPlatform;
use Doctrine\DBAL\Types\Type; use Doctrine\DBAL\Types\Type;
use IteratorIterator;
use PDO; use PDO;
class DataAccessTest extends \Doctrine\Tests\DbalFunctionalTestCase class DataAccessTest extends \Doctrine\Tests\DbalFunctionalTestCase
...@@ -877,55 +866,9 @@ class DataAccessTest extends \Doctrine\Tests\DbalFunctionalTestCase ...@@ -877,55 +866,9 @@ class DataAccessTest extends \Doctrine\Tests\DbalFunctionalTestCase
$this->markTestSkipped('Mysqli driver dont support this feature.'); $this->markTestSkipped('Mysqli driver dont support this feature.');
} }
} }
}
public function getConnections() class MyFetchClass
{ {
return [ public $test_int, $test_string, $test_datetime;
[MysqliConnection::class, MysqliStatement::class],
[OCI8Connection::class, OCI8Statement::class],
[DB2Connection::class, DB2Statement::class],
[SQLAnywhereConnection::class, SQLAnywhereStatement::class],
[SQLSrvConnection::class, SQLSrvStatement::class],
];
}
/**
* @dataProvider getConnections
*/
public function testGettingIteratorDoesNotCallFetch($connection, $statement)
{
$stmt = $this->createPartialMock($statement, ['fetch']);
$stmt->expects($this->never())->method('fetch');
$conn = $this->createMock($connection);
$conn->expects($this->any())->method('prepare')->willReturn($stmt);
$ii = new IteratorIterator($stmt);
$ii->getInnerIterator();
}
/**
* @dataProvider getConnections
*/
public function testIterationCallsFetchOncePerStep($connection, $statement)
{
$values = ['foo', '', 'bar', '0', 'baz', 0, 'qux', null, 'quz', false];
$calls = 0;
$stmt = $this->createPartialMock($statement, ['fetch']);
$stmt->expects($this->exactly(10))
->method('fetch')
->willReturnCallback(function() use ($values, &$calls) {
$calls++;
yield from $values;
});
$conn = $this->createMock($connection);
$conn->expects($this->any())->method('prepare')->willReturn($stmt);
foreach ($stmt as $i => $_) {
$_->next();
$this->assertEquals($i + 1, $calls);
}
}
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment