BatchIterator.php 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202
  1. <?php
  2. /**
  3. * Copyright © Magento, Inc. All rights reserved.
  4. * See COPYING.txt for license details.
  5. */
  6. namespace Magento\Framework\DB\Query;
  7. use Magento\Framework\DB\Adapter\AdapterInterface;
  8. use Magento\Framework\DB\Select;
  9. /**
  10. * Query batch iterator
  11. */
  12. class BatchIterator implements BatchIteratorInterface
  13. {
  14. /**
  15. * @var int
  16. */
  17. private $batchSize;
  18. /**
  19. * @var Select
  20. */
  21. private $select;
  22. /**
  23. * @var int
  24. */
  25. private $minValue = 0;
  26. /**
  27. * @var string
  28. */
  29. private $correlationName;
  30. /**
  31. * @var string
  32. */
  33. private $rangeField;
  34. /**
  35. * @var Select
  36. */
  37. private $currentSelect;
  38. /**
  39. * @var AdapterInterface
  40. */
  41. private $connection;
  42. /**
  43. * @var int
  44. */
  45. private $iteration = 0;
  46. /**
  47. * @var string
  48. */
  49. private $rangeFieldAlias;
  50. /**
  51. * @var bool
  52. */
  53. private $isValid = true;
  54. /**
  55. * Initialize dependencies.
  56. *
  57. * @param Select $select
  58. * @param int $batchSize
  59. * @param string $correlationName
  60. * @param string $rangeField
  61. * @param string $rangeFieldAlias
  62. */
  63. public function __construct(
  64. Select $select,
  65. $batchSize,
  66. $correlationName,
  67. $rangeField,
  68. $rangeFieldAlias
  69. ) {
  70. $this->batchSize = $batchSize;
  71. $this->select = $select;
  72. $this->correlationName = $correlationName;
  73. $this->rangeField = $rangeField;
  74. $this->rangeFieldAlias = $rangeFieldAlias;
  75. $this->connection = $select->getConnection();
  76. }
  77. /**
  78. * Returns current select
  79. *
  80. * @return Select
  81. */
  82. public function current()
  83. {
  84. if (null == $this->currentSelect) {
  85. $this->currentSelect = $this->initSelectObject();
  86. $itemsCount = $this->calculateBatchSize($this->currentSelect);
  87. $this->isValid = $itemsCount > 0;
  88. }
  89. return $this->currentSelect;
  90. }
  91. /**
  92. * Returns next select
  93. *
  94. * @return Select
  95. */
  96. public function next()
  97. {
  98. if (null == $this->currentSelect) {
  99. $this->current();
  100. }
  101. $select = $this->initSelectObject();
  102. $itemsCountInSelect = $this->calculateBatchSize($select);
  103. $this->isValid = $itemsCountInSelect > 0;
  104. if ($this->isValid) {
  105. $this->iteration++;
  106. $this->currentSelect = $select;
  107. } else {
  108. $this->currentSelect = null;
  109. }
  110. return $this->currentSelect;
  111. }
  112. /**
  113. * Returns key
  114. *
  115. * @return int
  116. */
  117. public function key()
  118. {
  119. return $this->iteration;
  120. }
  121. /**
  122. * Returns is valid
  123. *
  124. * @return bool
  125. */
  126. public function valid()
  127. {
  128. return $this->isValid;
  129. }
  130. /**
  131. * Rewind
  132. *
  133. * @return void
  134. */
  135. public function rewind()
  136. {
  137. $this->minValue = 0;
  138. $this->currentSelect = null;
  139. $this->iteration = 0;
  140. $this->isValid = true;
  141. }
  142. /**
  143. * Calculate batch size for select.
  144. *
  145. * @param Select $select
  146. * @return int
  147. */
  148. private function calculateBatchSize(Select $select)
  149. {
  150. $wrapperSelect = $this->connection->select();
  151. $wrapperSelect->from(
  152. $select,
  153. [
  154. new \Zend_Db_Expr('MAX(' . $this->rangeFieldAlias . ') as max'),
  155. new \Zend_Db_Expr('COUNT(*) as cnt')
  156. ]
  157. );
  158. $row = $this->connection->fetchRow($wrapperSelect);
  159. $this->minValue = $row['max'];
  160. return (int)$row['cnt'];
  161. }
  162. /**
  163. * Initialize select object.
  164. *
  165. * @return \Magento\Framework\DB\Select
  166. */
  167. private function initSelectObject()
  168. {
  169. $object = clone $this->select;
  170. $object->where(
  171. $this->connection->quoteIdentifier($this->correlationName)
  172. . '.' . $this->connection->quoteIdentifier($this->rangeField)
  173. . ' > ?',
  174. $this->minValue
  175. );
  176. $object->limit($this->batchSize);
  177. /**
  178. * Reset sort order section from origin select object
  179. */
  180. $object->order($this->correlationName . '.' . $this->rangeField . ' ' . \Magento\Framework\DB\Select::SQL_ASC);
  181. return $object;
  182. }
  183. }