Skip to content

Commit f33c0ff

Browse files
author
Stanislav Idolov
committed
MAGETWO-66195: SQL Error during price reindexation process for custom profile
1 parent 9c1ed9f commit f33c0ff

File tree

9 files changed

+230
-15
lines changed

9 files changed

+230
-15
lines changed

app/code/Magento/Bundle/etc/di.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,4 +147,10 @@
147147
</argument>
148148
</arguments>
149149
</type>
150+
<type name="Magento\Bundle\Model\ResourceModel\Indexer\Price">
151+
<arguments>
152+
<argument name="tableStrategy" xsi:type="object">Magento\Catalog\Model\ResourceModel\Product\Indexer\TemporaryTableStrategy</argument>
153+
<argument name="connectionName" xsi:type="string">indexer</argument>
154+
</arguments>
155+
</type>
150156
</config>

app/code/Magento/Catalog/Model/Indexer/Product/Price/Action/Full.php

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -117,19 +117,22 @@ public function execute($ids = null)
117117
$entityIds = $this->batchProvider->getBatchIds($connection, $select, $batch);
118118

119119
if (!empty($entityIds)) {
120-
$this->_emptyTable($this->_defaultIndexerResource->getIdxTable());
120+
// Temporary table will created
121+
$idxTableName = $this->_defaultIndexerResource->getIdxTable();
122+
121123
if ($indexer->getIsComposite()) {
122124
$this->_copyRelationIndexData($entityIds);
123125
}
124126
$this->_prepareTierPriceIndex($entityIds);
127+
125128
// Reindex entities by id
126129
$indexer->reindexEntity($entityIds);
127130

128131
// Sync data from temp table to index table
129-
$this->_insertFromTable(
130-
$this->_defaultIndexerResource->getIdxTable(),
131-
$this->_defaultIndexerResource->getMainTable()
132-
);
132+
$this->_insertFromTable($idxTableName, $this->_defaultIndexerResource->getMainTable());
133+
134+
// Drop temporary index table
135+
$connection->dropTable($idxTableName);
133136
}
134137
}
135138
}

app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/CompositeProductRowSizeEstimator.php

Lines changed: 24 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -7,32 +7,42 @@
77
namespace Magento\Catalog\Model\ResourceModel\Product\Indexer\Price;
88

99
use Magento\Framework\Indexer\IndexTableRowSizeEstimatorInterface;
10+
use Magento\Store\Api\WebsiteManagementInterface;
11+
use Magento\Customer\Model\ResourceModel\Group\CollectionFactory;
1012

1113
/**
1214
* Estimate index memory size for largest composite product in catalog.
1315
*/
1416
class CompositeProductRowSizeEstimator implements IndexTableRowSizeEstimatorInterface
1517
{
1618
/**
17-
* @var IndexTableRowSizeEstimator
19+
* @var DefaultPrice
1820
*/
19-
private $indexTableRowSizeEstimator;
21+
private $indexerResource;
2022

2123
/**
22-
* @var DefaultPrice
24+
* @var WebsiteManagementInterface
2325
*/
24-
private $indexerResource;
26+
private $websiteManagement;
27+
28+
/**
29+
* @var CollectionFactory
30+
*/
31+
private $collectionFactory;
2532

2633
/**
2734
* @param DefaultPrice $indexerResource
28-
* @param IndexTableRowSizeEstimator $indexTableRowSizeEstimator
35+
* @param WebsiteManagementInterface $websiteManagement
36+
* @param CollectionFactory $collectionFactory
2937
*/
3038
public function __construct(
3139
DefaultPrice $indexerResource,
32-
IndexTableRowSizeEstimator $indexTableRowSizeEstimator
40+
WebsiteManagementInterface $websiteManagement,
41+
CollectionFactory $collectionFactory
3342
) {
3443
$this->indexerResource = $indexerResource;
35-
$this->indexTableRowSizeEstimator = $indexTableRowSizeEstimator;
44+
$this->websiteManagement = $websiteManagement;
45+
$this->collectionFactory = $collectionFactory;
3646
}
3747

3848
/**
@@ -42,6 +52,9 @@ public function __construct(
4252
*/
4353
public function estimateRowSize()
4454
{
55+
$websitesCount = $this->websiteManagement->getCount();
56+
$customerGroupCount = $this->collectionFactory->create()->getSize();
57+
4558
$connection = $this->indexerResource->getConnection();
4659
$relationSelect = $connection->select();
4760
$relationSelect->from(
@@ -61,7 +74,10 @@ public function estimateRowSize()
6174
* Calculate memory size for largest composite product in database.
6275
*
6376
* $maxRelatedProductCount - maximum number of related products
77+
* $websitesCount - active websites
78+
* $customerGroupCount - active customer groups
79+
* 200 - calculated memory size for one record in catalog_product_index_price table
6480
*/
65-
return ceil($maxRelatedProductCount * $this->indexTableRowSizeEstimator->estimateRowSize());
81+
return ceil($maxRelatedProductCount * $websitesCount * $customerGroupCount * 200);
6682
}
6783
}

app/code/Magento/Catalog/Model/ResourceModel/Product/Indexer/Price/IndexTableRowSizeEstimator.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,8 +51,8 @@ public function estimateRowSize()
5151
*
5252
* $websitesCount - active websites
5353
* $customerGroupCount - active customer groups
54-
* 90 - calculated memory size for one record in catalog_product_index_price table
54+
* 120 - calculated memory size for one record in catalog_product_index_price table
5555
*/
56-
return ceil($websitesCount * $customerGroupCount * 90);
56+
return ceil($websitesCount * $customerGroupCount * 120);
5757
}
5858
}
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Catalog\Model\ResourceModel\Product\Indexer;
8+
9+
class TemporaryTableStrategy implements \Magento\Framework\Indexer\Table\StrategyInterface
10+
{
11+
const TEMP_SUFFIX = '_temp';
12+
13+
/**
14+
* @var \Magento\Framework\Indexer\Table\Strategy
15+
*/
16+
private $strategy;
17+
18+
/**
19+
* Application resource
20+
*
21+
* @var \Magento\Framework\App\ResourceConnection
22+
*/
23+
private $resource;
24+
25+
/**
26+
* TemporaryTableStrategy constructor.
27+
* @param \Magento\Framework\Indexer\Table\Strategy $strategy
28+
* @param \Magento\Framework\App\ResourceConnection $resource
29+
*/
30+
public function __construct(
31+
\Magento\Framework\Indexer\Table\Strategy $strategy,
32+
\Magento\Framework\App\ResourceConnection $resource
33+
) {
34+
$this->strategy = $strategy;
35+
$this->resource = $resource;
36+
}
37+
38+
/**
39+
* @inheritdoc
40+
*/
41+
public function getUseIdxTable()
42+
{
43+
return $this->strategy->getUseIdxTable();
44+
}
45+
46+
/**
47+
* @inheritdoc
48+
*/
49+
public function setUseIdxTable($value = false)
50+
{
51+
return $this->strategy->setUseIdxTable($value);
52+
}
53+
54+
/**
55+
* @inheritdoc
56+
*/
57+
public function getTableName($tablePrefix)
58+
{
59+
return $this->resource->getTableName($this->prepareTableName($tablePrefix));
60+
}
61+
62+
/**
63+
* Create temporary index table based on memory table
64+
*
65+
* {@inheritdoc}
66+
*/
67+
public function prepareTableName($tablePrefix)
68+
{
69+
if ($this->getUseIdxTable()) {
70+
return $tablePrefix . self::IDX_SUFFIX;
71+
}
72+
73+
// Create temporary table
74+
$this->resource->getConnection('indexer')->createTemporaryTableLike(
75+
$this->resource->getTableName($tablePrefix . self::TEMP_SUFFIX),
76+
$this->resource->getTableName($tablePrefix . self::TMP_SUFFIX),
77+
true
78+
);
79+
return $tablePrefix . self::TEMP_SUFFIX;
80+
}
81+
}
Lines changed: 90 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,90 @@
1+
<?php
2+
/**
3+
* Copyright © 2013-2017 Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
namespace Magento\Catalog\Test\Unit\Model\ResourceModel\Product\Indexer;
8+
9+
use Magento\Catalog\Model\ResourceModel\Product\Indexer\TemporaryTableStrategy;
10+
11+
class TemporaryTableStrategyTest extends \PHPUnit_Framework_TestCase
12+
{
13+
/**
14+
* @var \Magento\Catalog\Model\ResourceModel\Product\Indexer\TemporaryTableStrategy
15+
*/
16+
private $model;
17+
18+
/**
19+
* @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\Indexer\Table\Strategy
20+
*/
21+
private $tableStrategyMock;
22+
23+
/**
24+
* @var \PHPUnit_Framework_MockObject_MockObject|\Magento\Framework\App\ResourceConnection
25+
*/
26+
private $resourceMock;
27+
28+
protected function setUp()
29+
{
30+
$this->tableStrategyMock = $this->getMock(\Magento\Framework\Indexer\Table\Strategy::class, [], [], '', false);
31+
$this->resourceMock = $this->getMock(\Magento\Framework\App\ResourceConnection::class, [], [], '', false);
32+
33+
$this->model = new \Magento\Catalog\Model\ResourceModel\Product\Indexer\TemporaryTableStrategy(
34+
$this->tableStrategyMock,
35+
$this->resourceMock
36+
);
37+
}
38+
39+
public function testGetUseIdxTable()
40+
{
41+
$this->tableStrategyMock->expects($this->once())->method('getUseIdxTable')->willReturn(true);
42+
$this->assertTrue($this->model->getUseIdxTable());
43+
}
44+
45+
public function testSetUseIdxTable()
46+
{
47+
$this->tableStrategyMock->expects($this->once())->method('setUseIdxTable')->with(true)->willReturnSelf();
48+
$this->assertEquals($this->tableStrategyMock, $this->model->setUseIdxTable(true));
49+
}
50+
51+
public function testGetTableName()
52+
{
53+
$tablePrefix = 'prefix';
54+
$expectedResult = $tablePrefix . \Magento\Framework\Indexer\Table\StrategyInterface::IDX_SUFFIX;
55+
$this->tableStrategyMock->expects($this->once())->method('getUseIdxTable')->willReturn(true);
56+
$this->resourceMock->expects($this->once())
57+
->method('getTableName')
58+
->with($expectedResult)
59+
->willReturn($expectedResult);
60+
$this->assertEquals($expectedResult, $this->model->getTableName($tablePrefix));
61+
}
62+
63+
public function testPrepareTableName()
64+
{
65+
$tablePrefix = 'prefix';
66+
$expectedResult = $tablePrefix . TemporaryTableStrategy::TEMP_SUFFIX;
67+
$tempTableName = $tablePrefix . \Magento\Framework\Indexer\Table\StrategyInterface::TMP_SUFFIX;
68+
69+
$this->tableStrategyMock->expects($this->once())->method('getUseIdxTable')->willReturn(false);
70+
$connectionMock = $this->getMock(\Magento\Framework\DB\Adapter\AdapterInterface::class);
71+
72+
$this->resourceMock->expects($this->once())
73+
->method('getConnection')
74+
->with('indexer')
75+
->willReturn($connectionMock);
76+
$this->resourceMock->expects($this->at(1))
77+
->method('getTableName')
78+
->with($expectedResult)
79+
->willReturn($expectedResult);
80+
$this->resourceMock->expects($this->at(2))
81+
->method('getTableName')
82+
->with($tempTableName)
83+
->willReturn($tempTableName);
84+
$connectionMock->expects($this->once())
85+
->method('createTemporaryTableLike')
86+
->with($expectedResult, $tempTableName, true);
87+
88+
$this->assertEquals($expectedResult, $this->model->prepareTableName($tablePrefix));
89+
}
90+
}

app/code/Magento/Catalog/etc/di.xml

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -947,4 +947,11 @@
947947
<argument name="indexerFrontendResource" xsi:type="object">Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\FrontendResource</argument>
948948
</arguments>
949949
</type>
950+
<type name="Magento\Catalog\Model\ResourceModel\Product\Indexer\TemporaryTableStrategy" shared="false" />
951+
<type name="Magento\Catalog\Model\ResourceModel\Product\Indexer\Price\DefaultPrice">
952+
<arguments>
953+
<argument name="tableStrategy" xsi:type="object">Magento\Catalog\Model\ResourceModel\Product\Indexer\TemporaryTableStrategy</argument>
954+
<argument name="connectionName" xsi:type="string">indexer</argument>
955+
</arguments>
956+
</type>
950957
</config>

app/code/Magento/ConfigurableProduct/etc/di.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -181,4 +181,10 @@
181181
</argument>
182182
</arguments>
183183
</type>
184+
<type name="Magento\ConfigurableProduct\Model\ResourceModel\Product\Indexer\Price\Configurable">
185+
<arguments>
186+
<argument name="tableStrategy" xsi:type="object">Magento\Catalog\Model\ResourceModel\Product\Indexer\TemporaryTableStrategy</argument>
187+
<argument name="connectionName" xsi:type="string">indexer</argument>
188+
</arguments>
189+
</type>
184190
</config>

app/code/Magento/Downloadable/etc/di.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -151,4 +151,10 @@
151151
</argument>
152152
</arguments>
153153
</type>
154+
<type name="Magento\Downloadable\Model\ResourceModel\Indexer\Price">
155+
<arguments>
156+
<argument name="tableStrategy" xsi:type="object">Magento\Catalog\Model\ResourceModel\Product\Indexer\TemporaryTableStrategy</argument>
157+
<argument name="connectionName" xsi:type="string">indexer</argument>
158+
</arguments>
159+
</type>
154160
</config>

0 commit comments

Comments
 (0)