Skip to content

Commit

Permalink
Closes #10023. Fix MSSQL "There are no more rows" exception (#17433)
Browse files Browse the repository at this point in the history
* Closes #10023. Fix MSSQL "There are no more rows" exception when using `each()` and `batch()`

* #10023. Fix codeclimate issue

* Added since tag
  • Loading branch information
samdark authored Jul 15, 2019
2 parents 136705c + a26f8f6 commit 7c8b85b
Show file tree
Hide file tree
Showing 3 changed files with 29 additions and 39 deletions.
1 change: 1 addition & 0 deletions framework/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ Yii Framework 2 Change Log
- Bug #17413, #17418, #17426, #17431: Fixed MSSQL tests (alexkart)
- Bug #17420: Fixed loading of column default values for MSSQL (alexkart)
- Bug #17395: Fixed issues with actions that contain underscores in their names (alexkart)
- Bug #10023: Fixed MSSQL "There are no more rows in the active result set" exception when using `each()` and `batch()` (alexkart)


2.0.22 July 02, 2019
Expand Down
32 changes: 28 additions & 4 deletions framework/db/BatchQueryResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,11 @@ class BatchQueryResult extends BaseObject implements \Iterator
* @var string|int the key for the current iteration
*/
private $_key;

/**
* @var string MSSQL exception that is thrown when last batch size less than specified batch size
* @see https://github.com/yiisoft/yii2/issues/10023
*/
private $mssqlNoMoreRowsErrorMessage = 'SQLSTATE[IMSSP]: There are no more rows in the active result set. Since this result set is not scrollable, no more data may be retrieved.';

/**
* Destructor.
Expand Down Expand Up @@ -131,20 +135,40 @@ public function next()
/**
* Fetches the next batch of data.
* @return array the data fetched
* @throws Exception
*/
protected function fetchData()
{
if ($this->_dataReader === null) {
$this->_dataReader = $this->query->createCommand($this->db)->query();
}

$rows = $this->getRows();

return $this->query->populate($rows);
}

/**
* Reads and collects rows for batch
* @since 2.0.23
* @return array
*/
protected function getRows()
{
$rows = [];
$count = 0;
while ($count++ < $this->batchSize && ($row = $this->_dataReader->read())) {
$rows[] = $row;

try {
while ($count++ < $this->batchSize && ($row = $this->_dataReader->read())) {
$rows[] = $row;
}
} catch (\PDOException $e) {
if ($e->getMessage() !== $this->mssqlNoMoreRowsErrorMessage) {
throw $e;
}
}

return $this->query->populate($rows);
return $rows;
}

/**
Expand Down
35 changes: 0 additions & 35 deletions tests/framework/db/mssql/BatchQueryResultTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,46 +7,11 @@

namespace yiiunit\framework\db\mssql;

use yii\db\BatchQueryResult;

/**
* @group db
* @group mssql
*/
class BatchQueryResultTest extends \yiiunit\framework\db\BatchQueryResultTest
{
public $driverName = 'sqlsrv';
private $noMoreRowsErrorMessage = 'SQLSTATE[IMSSP]: There are no more rows in the active result set. Since this result set is not scrollable, no more data may be retrieved.';

protected function getAllRowsFromBach(BatchQueryResult $batch)
{
$allRows = [];
try {
foreach ($batch as $rows) {
$allRows = array_merge($allRows, $rows);
}
} catch (\PDOException $e) {
if ($e->getMessage() !== $this->noMoreRowsErrorMessage) {
throw $e;
}
}

return $allRows;
}

protected function getAllRowsFromEach(BatchQueryResult $each)
{
$allRows = [];
try {
foreach ($each as $index => $row) {
$allRows[$index] = $row;
}
} catch (\PDOException $e) {
if ($e->getMessage() !== $this->noMoreRowsErrorMessage) {
throw $e;
}
}

return $allRows;
}
}

0 comments on commit 7c8b85b

Please sign in to comment.