Skip to content

Commit 8ac0fba

Browse files
author
cspruiell
committed
MAGETWO-56928: CLONE - Wrong algorithm for calculation batch size on category indexing
- Merge remote-tracking branch 'origin/MAGETWO-56928-CLONE-Wrong-algorithm-for-calculation-batch-size-2.1' into okapis-2.1.3-pr
2 parents 356dc37 + 1d0b153 commit 8ac0fba

File tree

6 files changed

+714
-43
lines changed

6 files changed

+714
-43
lines changed

lib/internal/Magento/Framework/DB/Adapter/Pdo/Mysql.php

Lines changed: 24 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
use Magento\Framework\Phrase;
2424
use Magento\Framework\Stdlib\DateTime;
2525
use Magento\Framework\Stdlib\StringUtils;
26+
use Magento\Framework\DB\Query\Generator as QueryGenerator;
2627

2728
/**
2829
* @SuppressWarnings(PHPMD.ExcessivePublicCount)
@@ -189,6 +190,11 @@ class Mysql extends \Zend_Db_Adapter_Pdo_Mysql implements AdapterInterface
189190
*/
190191
protected $logger;
191192

193+
/**
194+
* @var QueryGenerator
195+
*/
196+
private $queryGenerator;
197+
192198
/**
193199
* @param StringUtils $string
194200
* @param DateTime $dateTime
@@ -3329,57 +3335,32 @@ public function insertFromSelect(Select $select, $table, array $fields = [], $mo
33293335
* @param int $stepCount
33303336
* @return \Magento\Framework\DB\Select[]
33313337
* @throws LocalizedException
3338+
* @deprecated
33323339
*/
33333340
public function selectsByRange($rangeField, \Magento\Framework\DB\Select $select, $stepCount = 100)
33343341
{
3335-
$fromSelect = $select->getPart(\Magento\Framework\DB\Select::FROM);
3336-
if (empty($fromSelect)) {
3337-
throw new LocalizedException(
3338-
new \Magento\Framework\Phrase('Select object must have correct "FROM" part')
3339-
);
3340-
}
3341-
3342-
$tableName = [];
3343-
$correlationName = '';
3344-
foreach ($fromSelect as $correlationName => $formPart) {
3345-
if ($formPart['joinType'] == \Magento\Framework\DB\Select::FROM) {
3346-
$tableName = $formPart['tableName'];
3347-
break;
3348-
}
3349-
}
3350-
3351-
$selectRange = $this->select()
3352-
->from(
3353-
$tableName,
3354-
[
3355-
new \Zend_Db_Expr('MIN(' . $this->quoteIdentifier($rangeField) . ') AS min'),
3356-
new \Zend_Db_Expr('MAX(' . $this->quoteIdentifier($rangeField) . ') AS max'),
3357-
]
3358-
);
3359-
3360-
$rangeResult = $this->fetchRow($selectRange);
3361-
$min = $rangeResult['min'];
3362-
$max = $rangeResult['max'];
3363-
3342+
$iterator = $this->getQueryGenerator()->generate($rangeField, $select, $stepCount);
33643343
$queries = [];
3365-
while ($min <= $max) {
3366-
$partialSelect = clone $select;
3367-
$partialSelect->where(
3368-
$this->quoteIdentifier($correlationName) . '.'
3369-
. $this->quoteIdentifier($rangeField) . ' >= ?',
3370-
$min
3371-
)
3372-
->where(
3373-
$this->quoteIdentifier($correlationName) . '.'
3374-
. $this->quoteIdentifier($rangeField) . ' < ?',
3375-
$min + $stepCount
3376-
);
3377-
$queries[] = $partialSelect;
3378-
$min += $stepCount;
3344+
foreach ($iterator as $query) {
3345+
$queries[] = $query;
33793346
}
33803347
return $queries;
33813348
}
33823349

3350+
/**
3351+
* Get query generator
3352+
*
3353+
* @return QueryGenerator
3354+
* @deprecated
3355+
*/
3356+
private function getQueryGenerator()
3357+
{
3358+
if ($this->queryGenerator === null) {
3359+
$this->queryGenerator = \Magento\Framework\App\ObjectManager::getInstance()->create(QueryGenerator::class);
3360+
}
3361+
return $this->queryGenerator;
3362+
}
3363+
33833364
/**
33843365
* Get update table query using select object for join and update
33853366
*
Lines changed: 192 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,192 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Framework\DB\Query;
7+
8+
use Magento\Framework\DB\Adapter\AdapterInterface;
9+
use Magento\Framework\DB\Select;
10+
11+
/**
12+
* Query batch iterator
13+
*/
14+
class BatchIterator implements \Iterator
15+
{
16+
/**
17+
* @var int
18+
*/
19+
private $batchSize;
20+
21+
/**
22+
* @var Select
23+
*/
24+
private $select;
25+
26+
/**
27+
* @var int
28+
*/
29+
private $minValue = 0;
30+
31+
/**
32+
* @var string
33+
*/
34+
private $correlationName;
35+
36+
/**
37+
* @var string
38+
*/
39+
private $rangeField;
40+
41+
/**
42+
* @var Select
43+
*/
44+
private $currentSelect;
45+
46+
/**
47+
* @var AdapterInterface
48+
*/
49+
private $connection;
50+
51+
/**
52+
* @var int
53+
*/
54+
private $iteration = 0;
55+
56+
/**
57+
* @var string
58+
*/
59+
private $rangeFieldAlias;
60+
61+
/**
62+
* @var bool
63+
*/
64+
private $isValid = true;
65+
66+
/**
67+
* Initialize dependencies.
68+
*
69+
* @param Select $select
70+
* @param int $batchSize
71+
* @param string $correlationName
72+
* @param string $rangeField
73+
* @param string $rangeFieldAlias
74+
*/
75+
public function __construct(
76+
Select $select,
77+
$batchSize,
78+
$correlationName,
79+
$rangeField,
80+
$rangeFieldAlias
81+
) {
82+
$this->batchSize = $batchSize;
83+
$this->select = $select;
84+
$this->correlationName = $correlationName;
85+
$this->rangeField = $rangeField;
86+
$this->rangeFieldAlias = $rangeFieldAlias;
87+
$this->connection = $select->getConnection();
88+
}
89+
90+
/**
91+
* @return Select
92+
*/
93+
public function current()
94+
{
95+
if (null == $this->currentSelect) {
96+
$this->currentSelect = $this->initSelectObject();
97+
$itemsCount = $this->calculateBatchSize($this->currentSelect);
98+
$this->isValid = $itemsCount > 0;
99+
}
100+
return $this->currentSelect;
101+
}
102+
103+
/**
104+
* @return Select
105+
*/
106+
public function next()
107+
{
108+
if (null == $this->currentSelect) {
109+
$this->current();
110+
}
111+
$select = $this->initSelectObject();
112+
$itemsCountInSelect = $this->calculateBatchSize($select);
113+
$this->isValid = $itemsCountInSelect > 0;
114+
if ($this->isValid) {
115+
$this->iteration++;
116+
$this->currentSelect = $select;
117+
} else {
118+
$this->currentSelect = null;
119+
}
120+
return $this->currentSelect;
121+
}
122+
123+
/**
124+
* @return int
125+
*/
126+
public function key()
127+
{
128+
return $this->iteration;
129+
}
130+
131+
/**
132+
* @return bool
133+
*/
134+
public function valid()
135+
{
136+
return $this->isValid;
137+
}
138+
139+
/**
140+
* @return void
141+
*/
142+
public function rewind()
143+
{
144+
$this->minValue = 0;
145+
$this->currentSelect = null;
146+
$this->iteration = 0;
147+
$this->isValid = true;
148+
}
149+
150+
/**
151+
* Calculate batch size for select.
152+
*
153+
* @param Select $select
154+
* @return int
155+
*/
156+
private function calculateBatchSize(Select $select)
157+
{
158+
$wrapperSelect = $this->connection->select();
159+
$wrapperSelect->from(
160+
$select,
161+
[
162+
new \Zend_Db_Expr('MAX(' . $this->rangeFieldAlias . ') as max'),
163+
new \Zend_Db_Expr('COUNT(*) as cnt')
164+
]
165+
);
166+
$row = $this->connection->fetchRow($wrapperSelect);
167+
$this->minValue = $row['max'];
168+
return intval($row['cnt']);
169+
}
170+
171+
/**
172+
* Initialize select object.
173+
*
174+
* @return \Magento\Framework\DB\Select
175+
*/
176+
private function initSelectObject()
177+
{
178+
$object = clone $this->select;
179+
$object->where(
180+
$this->connection->quoteIdentifier($this->correlationName)
181+
. '.' . $this->connection->quoteIdentifier($this->rangeField)
182+
. ' > ?',
183+
$this->minValue
184+
);
185+
$object->limit($this->batchSize);
186+
/**
187+
* Reset sort order section from origin select object
188+
*/
189+
$object->order($this->correlationName . '.' . $this->rangeField . ' ' . \Magento\Framework\DB\Select::SQL_ASC);
190+
return $object;
191+
}
192+
}
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
<?php
2+
/**
3+
* Copyright © 2016 Magento. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Framework\DB\Query;
7+
8+
/**
9+
* Factory class for @see \Magento\Framework\DB\Query\BatchIterator
10+
*/
11+
class BatchIteratorFactory
12+
{
13+
/**
14+
* Object Manager instance
15+
*
16+
* @var \Magento\Framework\ObjectManagerInterface
17+
*/
18+
private $objectManager = null;
19+
20+
/**
21+
* Instance name to create
22+
*
23+
* @var string
24+
*/
25+
private $instanceName = null;
26+
27+
/**
28+
* Factory constructor
29+
*
30+
* @param \Magento\Framework\ObjectManagerInterface $objectManager
31+
* @param string $instanceName
32+
*/
33+
public function __construct(
34+
\Magento\Framework\ObjectManagerInterface $objectManager,
35+
$instanceName = \Magento\Framework\DB\Query\BatchIterator::class
36+
) {
37+
$this->objectManager = $objectManager;
38+
$this->instanceName = $instanceName;
39+
}
40+
41+
/**
42+
* Create class instance with specified parameters
43+
*
44+
* @param array $data
45+
* @return \Magento\Framework\DB\Query\BatchIterator
46+
*/
47+
public function create(array $data = [])
48+
{
49+
return $this->objectManager->create($this->instanceName, $data);
50+
}
51+
}

0 commit comments

Comments
 (0)