Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mview patch update 41 v 4 #30129

Closed
167 changes: 167 additions & 0 deletions app/code/Magento/Eav/Model/Mview/ChangeLogBatchWalker.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,167 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

namespace Magento\Eav\Model\Mview;

use Magento\Framework\App\ResourceConnection;
use Magento\Framework\DB\Sql\Expression;
use Magento\Framework\Exception\LocalizedException;
use Magento\Framework\Mview\View\ChangeLogBatchWalkerInterface;
use Magento\Framework\Mview\View\ChangelogInterface;

/**
* Class BatchIterator
*/
class ChangeLogBatchWalker implements ChangeLogBatchWalkerInterface
{
private const GROUP_CONCAT_MAX_VARIABLE = 'group_concat_max_len';
/** ID is defined as small int. Default size of it is 5 */
private const DEFAULT_ID_SIZE = 5;

/**
* @var ResourceConnection
*/
private $resourceConnection;

/**
* @var array
*/
private $entityTypeCodes;

/**
* @var ChangelogInterface
*/
private $changelog;
/**
* @var int
*/
private $fromVersionId;

/**
* @var int
*/
private $toVersionId;

/**
* @var int
*/
private $batchSize;

/**
* @param ResourceConnection $resourceConnection
* @param ChangelogInterface $changelog
* @param int $fromVersionId
* @param int $toVersionId
* @param int $batchSize
* @param array $entityTypeCodes
*/
public function __construct(
ResourceConnection $resourceConnection,
ChangelogInterface $changelog,
int $fromVersionId,
int $toVersionId,
int $batchSize,
array $entityTypeCodes = []
) {
$this->resourceConnection = $resourceConnection;
$this->entityTypeCodes = $entityTypeCodes;
$this->changelog = $changelog;
$this->fromVersionId = $fromVersionId;
$this->toVersionId = $toVersionId;
$this->batchSize = $batchSize;
}

/**
* @return \Generator|\Traversable
* @throws \Exception
*/
public function getIterator(): \Generator
{
while ($this->fromVersionId < $this->toVersionId) {
$ids = $this->walk();

if (empty($ids)) {
break;
}
$this->fromVersionId += $this->batchSize;
yield $ids;
}
}

/**
* Calculate EAV attributes size
*
* @param ChangelogInterface $changelog
* @return int
* @throws LocalizedException
*/
private function calculateEavAttributeSize(): int
{
$connection = $this->resourceConnection->getConnection();

if (!isset($this->entityTypeCodes[$this->changelog->getViewId()])) {
throw new LocalizedException(__('Entity type for view was not defined'));
}

$select = $connection->select();
$select->from(
$this->resourceConnection->getTableName('eav_attribute'),
new Expression('COUNT(*)')
)->joinInner(
['type' => $connection->getTableName('eav_entity_type')],
'type.entity_type_id=eav_attribute.entity_type_id'
)->where('type.entity_type_code = ?', $this->entityTypeCodes[$this->changelog->getViewId()]);

return (int) $connection->fetchOne($select);
}

/**
* Prepare group max concat
*
* @param int $numberOfAttributes
* @return void
* @throws \Exception
*/
private function setGroupConcatMax(int $numberOfAttributes): void
{
$connection = $this->resourceConnection->getConnection();
$connection->query(sprintf(
'SET SESSION %s=%s',
self::GROUP_CONCAT_MAX_VARIABLE,
$numberOfAttributes * (self::DEFAULT_ID_SIZE + 1)
));
}

/**
* @inheritdoc
* @throws \Exception
*/
private function walk()
{
$connection = $this->resourceConnection->getConnection();
$numberOfAttributes = $this->calculateEavAttributeSize();
$this->setGroupConcatMax($numberOfAttributes);
$select = $connection->select()->distinct(true)
->where(
'version_id > ?',
(int) $this->fromVersionId
)
->where(
'version_id <= ?',
$this->toVersionId
)
->group([$this->changelog->getColumnName(), 'store_id'])
->limit($this->batchSize);

$columns = [
$this->changelog->getColumnName(),
'attribute_ids' => new Expression('GROUP_CONCAT(attribute_id)'),
'store_id'
];
$select->from($this->changelog->getName(), $columns);
return $connection->fetchAll($select);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?xml version="1.0"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Module/etc/module.xsd">
<module name="Magento_TestModuleMview" active="true">
</module>
</config>
24 changes: 24 additions & 0 deletions dev/tests/integration/_files/Magento/TestModuleMview/etc/mview.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
-->
<config xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="urn:magento:framework:Mview/etc/mview.xsd">
<view id="test_view"
class="\Some\Class"
group="indexer"
walker="Magento\Eav\Model\Mview\ChangeLogBatchWalker"
>
<subscriptions>
<table name="catalog_product_entity" entity_column="entity_id" />
<table name="catalog_product_entity_varchar" entity_column="entity_id">
<additionalColumns>
<column name="store_id" cl_name="store_id" />
<column name="attribute_id" cl_name="attribute_id" />
</additionalColumns>
</table>
</subscriptions>
</view>
</config>
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

use Magento\Framework\Component\ComponentRegistrar;

$registrar = new ComponentRegistrar();
if ($registrar->getPath(ComponentRegistrar::MODULE, 'Magento_TestModuleMview') === null) {
ComponentRegistrar::register(ComponentRegistrar::MODULE, 'Magento_TestModuleMview', __DIR__);
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/

namespace Magento\Eav\Model;

use Magento\Catalog\Model\ProductRepository;
use Magento\Framework\App\ResourceConnection;

/**
* Test Class for \Magento\Framework\Mview\View\Changelog
*
* @magentoDbIsolation disabled
*/
class EnhancedMviewTest extends \PHPUnit\Framework\TestCase
{
/**
* @var \Magento\Framework\ObjectManagerInterface
*/
private $objectManager;

/**
* @var ResourceConnection
*/
private $resourceConnection;

protected function setUp(): void
{
$this->objectManager = \Magento\TestFramework\Helper\Bootstrap::getObjectManager();
$this->resourceConnection = $this->objectManager->get(ResourceConnection::class);
parent::setUp();
}

/**
* @dataProvider attributesDataProvider
* @magentoDataFixture Magento/Eav/_files/enable_mview_for_test_view.php
* @magentoDataFixture Magento/Catalog/_files/product_simple.php
* @param array $expectedAttributes
* @throws \Magento\Framework\Exception\NoSuchEntityException
*/
public function testCreateProduct(array $expectedAttributes)
{
$changelogData = $this->getChangelogData();
$attributesMapping = $this->getAttributeCodes();
$attributes = [];
foreach ($changelogData as $row) {
$this->assertArrayHasKey('store_id', $row);
$this->assertArrayHasKey('attribute_id', $row);

if ($row['store_id'] == 0 && $row['attribute_id'] !== null) {
$attributes[$attributesMapping[$row['attribute_id']]] = $attributesMapping[$row['attribute_id']];
}
}
sort($expectedAttributes);
sort($attributes);
$this->assertEquals($attributes, $expectedAttributes);

$this->assertTrue(true);
}

/**
* @return array
*/
private function getAttributeCodes(): array
{
$connection = $this->resourceConnection->getConnection();
$select = $connection->select()
->from($connection->getTableName('eav_attribute'), ['attribute_id', 'attribute_code']);
return $connection->fetchPairs($select);
}

/**
* @return array|\string[][]
*/
public function attributesDataProvider(): array
{
return [
[
'default' => [
'name',
'meta_title',
'meta_description',
'is_returnable',
'options_container'
]
]
];
}

/**
* @return array
*/
private function getChangelogData()
{
$connection = $this->resourceConnection->getConnection();
$select = $connection->select()
->from($connection->getTableName('test_view_cl'));
return $connection->fetchAll($select);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
<?php
/**
* Copyright © Magento, Inc. All rights reserved.
* See COPYING.txt for license details.
*/
declare(strict_types=1);

use Magento\TestFramework\Helper\Bootstrap;

$objectManager = Bootstrap::getObjectManager();
/** @var \Magento\Framework\Mview\View $view */
$view = $objectManager->create(\Magento\Framework\Mview\View::class);
$view->load('test_view');
$view->subscribe();
Loading