From 25cf33183902ca18e3b33d5af15af7922dc67147 Mon Sep 17 00:00:00 2001 From: Alexander Kartavenko Date: Mon, 15 Jul 2019 13:54:33 +0300 Subject: [PATCH 1/3] Closes #10023. Fix MSSQL "There are no more rows" exception when using `each()` and `batch()` --- framework/CHANGELOG.md | 1 + framework/db/BatchQueryResult.php | 17 +++++++-- .../db/mssql/BatchQueryResultTest.php | 35 ------------------- 3 files changed, 15 insertions(+), 38 deletions(-) diff --git a/framework/CHANGELOG.md b/framework/CHANGELOG.md index 9442b55f87d..cbf0cddb6d2 100644 --- a/framework/CHANGELOG.md +++ b/framework/CHANGELOG.md @@ -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 diff --git a/framework/db/BatchQueryResult.php b/framework/db/BatchQueryResult.php index 131e6de5034..ad543a0d9c2 100644 --- a/framework/db/BatchQueryResult.php +++ b/framework/db/BatchQueryResult.php @@ -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. @@ -140,8 +144,15 @@ protected function fetchData() $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); diff --git a/tests/framework/db/mssql/BatchQueryResultTest.php b/tests/framework/db/mssql/BatchQueryResultTest.php index ca123e59447..492373d72c1 100644 --- a/tests/framework/db/mssql/BatchQueryResultTest.php +++ b/tests/framework/db/mssql/BatchQueryResultTest.php @@ -7,8 +7,6 @@ namespace yiiunit\framework\db\mssql; -use yii\db\BatchQueryResult; - /** * @group db * @group mssql @@ -16,37 +14,4 @@ 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; - } } From 4bee9a4ed9d4270efd55da7a5209f34a011ddeed Mon Sep 17 00:00:00 2001 From: Alexander Kartavenko Date: Mon, 15 Jul 2019 14:49:11 +0300 Subject: [PATCH 2/3] #10023. Fix codeclimate issue --- framework/db/BatchQueryResult.php | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/framework/db/BatchQueryResult.php b/framework/db/BatchQueryResult.php index ad543a0d9c2..8daf9cd084e 100644 --- a/framework/db/BatchQueryResult.php +++ b/framework/db/BatchQueryResult.php @@ -135,6 +135,7 @@ public function next() /** * Fetches the next batch of data. * @return array the data fetched + * @throws Exception */ protected function fetchData() { @@ -142,6 +143,17 @@ protected function fetchData() $this->_dataReader = $this->query->createCommand($this->db)->query(); } + $rows = $this->getRows(); + + return $this->query->populate($rows); + } + + /** + * Reads and collects rows for batch + * @return array + */ + protected function getRows() + { $rows = []; $count = 0; @@ -155,7 +167,7 @@ protected function fetchData() } } - return $this->query->populate($rows); + return $rows; } /** From a26f8f6ed2d8700a5f44821014bd66c35274906b Mon Sep 17 00:00:00 2001 From: Alexander Makarov Date: Mon, 15 Jul 2019 23:00:10 +0300 Subject: [PATCH 3/3] Added since tag --- framework/db/BatchQueryResult.php | 1 + 1 file changed, 1 insertion(+) diff --git a/framework/db/BatchQueryResult.php b/framework/db/BatchQueryResult.php index 8daf9cd084e..eba90c2cd7c 100644 --- a/framework/db/BatchQueryResult.php +++ b/framework/db/BatchQueryResult.php @@ -150,6 +150,7 @@ protected function fetchData() /** * Reads and collects rows for batch + * @since 2.0.23 * @return array */ protected function getRows()