Skip to content

Commit 8389f7a

Browse files
🔃 [EngCom] Public Pull Requests - 2.2-develop
Accepted Public Pull Requests: - magento-engcom/magento2ce#1110: GitHub 12804: Performance: Improve attribute deletion to take advantage of indexes (by @serhii-balko) Fixed GitHub Issues: - #12804: Performance: Improve attribute deletion to take advantage of indexes (reported by @nei) has been fixed in magento-engcom/magento2ce#1110 by @serhii-balko in 2.2-develop branch Related commits: 1. 16575d9 2. 25fc7e8 3. 11da0ea 4. 0b01926 5. 4fb932f
2 parents 5685fce + 89dde97 commit 8389f7a

File tree

3 files changed

+176
-13
lines changed

3 files changed

+176
-13
lines changed

app/code/Magento/Catalog/Model/ResourceModel/Attribute.php

Lines changed: 9 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -141,19 +141,15 @@ public function deleteEntity(\Magento\Framework\Model\AbstractModel $object)
141141
->getMetadata(ProductInterface::class)
142142
->getLinkField();
143143

144-
$select = $this->getConnection()->select()->from(
145-
$attribute->getEntity()->getEntityTable(),
146-
$linkField
147-
)->where(
148-
'attribute_set_id = ?',
149-
$result['attribute_set_id']
150-
);
151-
152-
$clearCondition = [
153-
'attribute_id =?' => $attribute->getId(),
154-
$linkField . ' IN (?)' => $select,
155-
];
156-
$this->getConnection()->delete($backendTable, $clearCondition);
144+
$select = $this->getConnection()->select()
145+
->from(['b' => $backendTable])
146+
->join(
147+
['e' => $attribute->getEntity()->getEntityTable()],
148+
"b.$linkField = e.$linkField"
149+
)->where('b.attribute_id = ?', $attribute->getId())
150+
->where('e.attribute_set_id = ?', $result['attribute_set_id']);
151+
152+
$this->getConnection()->query($select->deleteFromSelect('b'));
157153
}
158154
}
159155

Lines changed: 153 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,153 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
namespace Magento\Catalog\Model\ResourceModel;
7+
8+
use Magento\Catalog\Api\Data\ProductInterface;
9+
use Magento\Catalog\Api\ProductRepositoryInterface;
10+
use Magento\Eav\Model\Entity\Attribute as EavAttribute;
11+
use Magento\Framework\EntityManager\MetadataPool;
12+
13+
/**
14+
* Test class for Catalog attribute resource model.
15+
*
16+
* @see Magento\Catalog\Model\ResourceModel\Attribute
17+
*/
18+
class AttributeTest extends \PHPUnit\Framework\TestCase
19+
{
20+
/**
21+
* @var \Magento\Catalog\Model\ResourceModel\Attribute
22+
*/
23+
private $model;
24+
25+
/**
26+
* @var \Magento\Catalog\Model\ResourceModel\Product
27+
*/
28+
protected $productResource;
29+
30+
/**
31+
* @var ProductRepositoryInterface
32+
*/
33+
private $productRepository;
34+
35+
/**
36+
* @var MetadataPool
37+
*/
38+
private $metadataPool;
39+
40+
/**
41+
* @var \Magento\Framework\ObjectManagerInterface
42+
*/
43+
protected $objectManager;
44+
45+
protected function setUp()
46+
{
47+
$this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
48+
$this->model = $this->objectManager->get(
49+
\Magento\Catalog\Model\ResourceModel\Attribute::class
50+
);
51+
$this->productResource = $this->objectManager->get(
52+
\Magento\Catalog\Model\ResourceModel\Product::class
53+
);
54+
$this->productRepository = $this->objectManager->create(ProductRepositoryInterface::class);
55+
$this->metadataPool = $this->objectManager->get(MetadataPool::class);
56+
}
57+
58+
/**
59+
* Test to delete catalog eav attribute entity.
60+
*
61+
* @magentoDataFixture Magento/Catalog/_files/product_eav_attribute.php
62+
*/
63+
public function testDeleteEntity()
64+
{
65+
/* @var EavAttribute $attribute */
66+
$attribute = $this->objectManager->get(EavAttribute::class);
67+
$attribute->loadByCode(\Magento\Catalog\Model\Product::ENTITY, 'text_attribute');
68+
$product = $this->productRepository->get('simple');
69+
70+
$entityEavAttributeRow = $this->getEavEntityAttributeRow(
71+
$attribute->getEntityTypeId(),
72+
4,
73+
$attribute->getId()
74+
);
75+
$this->assertNotEmpty(
76+
$entityEavAttributeRow['entity_attribute_id'],
77+
'The record is absent in table `eav_entity_attribute` for `test_attribute`'
78+
);
79+
80+
$entityAttributeValues = $this->getProductAttributeValues(
81+
$attribute,
82+
$product
83+
);
84+
$this->assertNotEmpty(
85+
$entityAttributeValues,
86+
'The attribute value is absent for product with ID = 1'
87+
);
88+
89+
$attribute->setData('entity_attribute_id', $entityEavAttributeRow['entity_attribute_id']);
90+
$this->model->deleteEntity($attribute);
91+
92+
$entityEavAttributeRow = $this->getEavEntityAttributeRow(
93+
$attribute->getEntityTypeId(),
94+
4,
95+
$attribute->getId()
96+
);
97+
$this->assertEmpty(
98+
$entityEavAttributeRow,
99+
'The record is not remove from table `eav_entity_attribute` for `test_attribute`'
100+
);
101+
102+
$entityAttributeValues = $this->getProductAttributeValues(
103+
$attribute,
104+
$product
105+
);
106+
$this->assertEmpty(
107+
$entityAttributeValues,
108+
'The attribute value is not remove for product with ID = 1'
109+
);
110+
}
111+
112+
/**
113+
* Retrieve eav attribute row.
114+
*
115+
* @param int $entityTypeId
116+
* @param int $attributeSetId
117+
* @param int $attributeId
118+
* @return array|false
119+
*/
120+
private function getEavEntityAttributeRow($entityTypeId, $attributeSetId, $attributeId)
121+
{
122+
$connection = $this->productResource->getConnection();
123+
$select = $connection->select()
124+
->from($this->productResource->getTable('eav_entity_attribute'))
125+
->where('attribute_set_id=?', $attributeSetId)
126+
->where('attribute_id=?', $attributeId)
127+
->where('entity_type_id=?', $entityTypeId);
128+
129+
return $connection->fetchRow($select);
130+
}
131+
132+
/**
133+
* Retrieve product attribute values.
134+
*
135+
* @param EavAttribute $attribute
136+
* @param ProductInterface $product
137+
* @return array
138+
*/
139+
private function getProductAttributeValues($attribute, $product)
140+
{
141+
$backendTable = $attribute->getBackend()->getTable();
142+
$linkField = $this->metadataPool->getMetadata(ProductInterface::class)->getLinkField();
143+
$linkFieldValue = $product->getData($linkField);
144+
145+
$connection = $this->productResource->getConnection();
146+
$select = $connection->select()
147+
->from($this->productResource->getTable($backendTable))
148+
->where('attribute_id=?', $attribute->getId())
149+
->where($linkField . '=?', $linkFieldValue);
150+
151+
return $connection->fetchAll($select);
152+
}
153+
}
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
<?php
2+
/**
3+
* Copyright © Magento, Inc. All rights reserved.
4+
* See COPYING.txt for license details.
5+
*/
6+
7+
require __DIR__ . '/../../Catalog/_files/product_text_attribute.php';
8+
require __DIR__ . '/../../Catalog/_files/product_simple.php';
9+
10+
$product->setData('text_attribute', 'test value');
11+
12+
/** @var \Magento\Catalog\Api\ProductRepositoryInterface $productRepositoryFactory $productRepository */
13+
$productRepository = $objectManager->create(\Magento\Catalog\Api\ProductRepositoryInterface::class);
14+
$productRepository->save($product);

0 commit comments

Comments
 (0)