Skip to content

Commit 7327dc0

Browse files
ENGCOM-8474: #21853: Allow mview indexers to use different entity columns. #21857
- Merge Pull Request #21857 from nikunjkotecha/magento2:21853 - Merged commits: 1. 891198c 2. 7da4940 3. b59fc5a 4. 4035ec0 5. 320ced7 6. 0d1ac3a 7. 6cbf85f 8. 7c2d2a6 9. 8388a90 10. 3f67ed8 11. 873b814 12. 392dbf6 13. ff56be5 14. e16f2c2 15. 922e029 16. 330d595 17. 4c1094a 18. 69cee97 19. 46429a4 20. 4ad7aae 21. 8a9b768 22. db4cf23 23. 094decc 24. 910eb41 25. be3f84b
2 parents 5fa09cc + be3f84b commit 7327dc0

File tree

2 files changed

+100
-48
lines changed

2 files changed

+100
-48
lines changed

lib/internal/Magento/Framework/Mview/Test/Unit/View/SubscriptionTest.php

+44-16
Original file line numberDiff line numberDiff line change
@@ -207,7 +207,7 @@ public function testCreate()
207207
->method('getColumnName')
208208
->willReturn('entity_id');
209209

210-
$this->viewMock->expects($this->exactly(3))
210+
$this->viewMock->expects($this->atLeastOnce())
211211
->method('getChangelog')
212212
->willReturn($changelogMock);
213213

@@ -243,20 +243,23 @@ public function testCreate()
243243
$otherViewMock->expects($this->exactly(1))
244244
->method('getId')
245245
->willReturn('other_id');
246-
$otherViewMock->expects($this->exactly(1))
246+
$otherViewMock->expects($this->exactly(4))
247247
->method('getSubscriptions')
248-
->willReturn([['name' => $this->tableName], ['name' => 'otherTableName']]);
249-
$otherViewMock->expects($this->exactly(3))
248+
->willReturn(
249+
[
250+
$this->tableName => ['name' => $this->tableName, 'column' => 'columnName'],
251+
'otherTableName' => ['name' => 'otherTableName', 'column' => 'columnName']
252+
]
253+
);
254+
$otherViewMock->expects($this->atLeastOnce())
250255
->method('getChangelog')
251256
->willReturn($otherChangelogMock);
252257

253258
$this->viewMock->expects($this->any())
254259
->method('getId')
255260
->willReturn('this_id');
256-
$this->viewMock->expects($this->never())
257-
->method('getSubscriptions');
258261

259-
$this->viewCollectionMock->expects($this->exactly(1))
262+
$this->viewCollectionMock->expects($this->once())
260263
->method('getViewsByStateMode')
261264
->with(StateInterface::MODE_ENABLED)
262265
->willReturn([$this->viewMock, $otherViewMock]);
@@ -268,6 +271,16 @@ public function testCreate()
268271
$this->connectionMock->expects($this->exactly(3))
269272
->method('createTrigger')
270273
->with($triggerMock);
274+
275+
$this->viewMock->expects($this->exactly(3))
276+
->method('getSubscriptions')
277+
->willReturn(
278+
[
279+
$this->tableName => ['name' => $this->tableName, 'column' => 'columnName'],
280+
'otherTableName' => ['name' => 'otherTableName', 'column' => 'columnName']
281+
]
282+
);
283+
271284
$this->model->create();
272285
}
273286

@@ -319,21 +332,24 @@ public function testRemove()
319332
true,
320333
[]
321334
);
322-
$otherViewMock->expects($this->exactly(1))
335+
$otherViewMock->expects($this->atLeastOnce())
323336
->method('getId')
324337
->willReturn('other_id');
325-
$otherViewMock->expects($this->exactly(1))
326-
->method('getSubscriptions')
327-
->willReturn([['name' => $this->tableName], ['name' => 'otherTableName']]);
328-
$otherViewMock->expects($this->exactly(3))
338+
$otherViewMock->expects($this->atLeastOnce())
329339
->method('getChangelog')
330340
->willReturn($otherChangelogMock);
331341

332-
$this->viewMock->expects($this->any())
342+
$this->viewMock->expects($this->atLeastOnce())
333343
->method('getId')
334344
->willReturn('this_id');
335-
$this->viewMock->expects($this->never())
336-
->method('getSubscriptions');
345+
$otherViewMock->expects($this->atLeastOnce())
346+
->method('getSubscriptions')
347+
->willReturn(
348+
[
349+
$this->tableName => ['name' => $this->tableName, 'column' => 'columnName'],
350+
'otherTableName' => ['name' => 'otherTableName', 'column' => 'columnName']
351+
]
352+
);
337353

338354
$this->viewCollectionMock->expects($this->exactly(1))
339355
->method('getViewsByStateMode')
@@ -411,6 +427,18 @@ public function testBuildStatementIgnoredColumnSubscriptionLevel(): void
411427
->method('getColumnName')
412428
->willReturn('entity_id');
413429

430+
$this->viewMock->expects($this->once())
431+
->method('getSubscriptions')
432+
->willReturn(
433+
[
434+
$this->tableName => ['name' => $this->tableName, 'column' => 'columnName'],
435+
'cataloginventory_stock_item' => ['name' => 'otherTableName', 'column' => 'columnName']
436+
]
437+
);
438+
$this->viewMock->expects($this->atLeastOnce())
439+
->method('getChangeLog')
440+
->willReturn($otherChangelogMock);
441+
414442
$model = new Subscription(
415443
$this->resourceMock,
416444
$this->triggerFactoryMock,
@@ -425,7 +453,7 @@ public function testBuildStatementIgnoredColumnSubscriptionLevel(): void
425453

426454
$method = new \ReflectionMethod($model, 'buildStatement');
427455
$method->setAccessible(true);
428-
$statement = $method->invoke($model, Trigger::EVENT_UPDATE, $otherChangelogMock);
456+
$statement = $method->invoke($model, Trigger::EVENT_UPDATE, $this->viewMock);
429457

430458
$this->assertStringNotContainsString($ignoredColumnName, $statement);
431459
$this->assertStringContainsString($notIgnoredColumnName, $statement);

lib/internal/Magento/Framework/Mview/View/Subscription.php

+56-32
Original file line numberDiff line numberDiff line change
@@ -8,29 +8,31 @@
88

99
use Magento\Framework\App\ObjectManager;
1010
use Magento\Framework\App\ResourceConnection;
11+
use Magento\Framework\DB\Adapter\AdapterInterface;
1112
use Magento\Framework\DB\Ddl\Trigger;
13+
use Magento\Framework\DB\Ddl\TriggerFactory;
1214
use Magento\Framework\Mview\Config;
13-
use Magento\Framework\Mview\View\StateInterface;
15+
use Magento\Framework\Mview\ViewInterface;
1416

1517
/**
16-
* Class Subscription for handling partial indexation triggers
18+
* Mview subscription.
1719
*/
1820
class Subscription implements SubscriptionInterface
1921
{
2022
/**
2123
* Database connection
2224
*
23-
* @var \Magento\Framework\DB\Adapter\AdapterInterface
25+
* @var AdapterInterface
2426
*/
2527
protected $connection;
2628

2729
/**
28-
* @var \Magento\Framework\DB\Ddl\TriggerFactory
30+
* @var TriggerFactory
2931
*/
3032
protected $triggerFactory;
3133

3234
/**
33-
* @var \Magento\Framework\Mview\View\CollectionInterface
35+
* @var CollectionInterface
3436
*/
3537
protected $viewCollection;
3638

@@ -62,7 +64,7 @@ class Subscription implements SubscriptionInterface
6264
*
6365
* @var array
6466
*/
65-
private $ignoredUpdateColumns = [];
67+
private $ignoredUpdateColumns;
6668

6769
/**
6870
* List of columns that can be updated in a specific subscribed table
@@ -74,16 +76,17 @@ class Subscription implements SubscriptionInterface
7476
* @var Resource
7577
*/
7678
protected $resource;
79+
7780
/**
7881
* @var Config
7982
*/
8083
private $mviewConfig;
8184

8285
/**
8386
* @param ResourceConnection $resource
84-
* @param \Magento\Framework\DB\Ddl\TriggerFactory $triggerFactory
85-
* @param \Magento\Framework\Mview\View\CollectionInterface $viewCollection
86-
* @param \Magento\Framework\Mview\ViewInterface $view
87+
* @param TriggerFactory $triggerFactory
88+
* @param CollectionInterface $viewCollection
89+
* @param ViewInterface $view
8790
* @param string $tableName
8891
* @param string $columnName
8992
* @param array $ignoredUpdateColumns
@@ -92,9 +95,9 @@ class Subscription implements SubscriptionInterface
9295
*/
9396
public function __construct(
9497
ResourceConnection $resource,
95-
\Magento\Framework\DB\Ddl\TriggerFactory $triggerFactory,
96-
\Magento\Framework\Mview\View\CollectionInterface $viewCollection,
97-
\Magento\Framework\Mview\ViewInterface $view,
98+
TriggerFactory $triggerFactory,
99+
CollectionInterface $viewCollection,
100+
ViewInterface $view,
98101
$tableName,
99102
$columnName,
100103
$ignoredUpdateColumns = [],
@@ -114,9 +117,9 @@ public function __construct(
114117
}
115118

116119
/**
117-
* Create subsciption
120+
* Create subscription
118121
*
119-
* @return \Magento\Framework\Mview\View\SubscriptionInterface
122+
* @return SubscriptionInterface
120123
*/
121124
public function create()
122125
{
@@ -129,12 +132,12 @@ public function create()
129132
->setEvent($event)
130133
->setTable($this->resource->getTableName($this->tableName));
131134

132-
$trigger->addStatement($this->buildStatement($event, $this->getView()->getChangelog()));
135+
$trigger->addStatement($this->buildStatement($event, $this->getView()));
133136

134137
// Add statements for linked views
135138
foreach ($this->getLinkedViews() as $view) {
136-
/** @var \Magento\Framework\Mview\ViewInterface $view */
137-
$trigger->addStatement($this->buildStatement($event, $view->getChangelog()));
139+
/** @var ViewInterface $view */
140+
$trigger->addStatement($this->buildStatement($event, $view));
138141
}
139142

140143
$this->connection->dropTrigger($trigger->getName());
@@ -147,7 +150,7 @@ public function create()
147150
/**
148151
* Remove subscription
149152
*
150-
* @return \Magento\Framework\Mview\View\SubscriptionInterface
153+
* @return SubscriptionInterface
151154
*/
152155
public function remove()
153156
{
@@ -162,8 +165,8 @@ public function remove()
162165

163166
// Add statements for linked views
164167
foreach ($this->getLinkedViews() as $view) {
165-
/** @var \Magento\Framework\Mview\ViewInterface $view */
166-
$trigger->addStatement($this->buildStatement($event, $view->getChangelog()));
168+
/** @var ViewInterface $view */
169+
$trigger->addStatement($this->buildStatement($event, $view));
167170
}
168171

169172
$this->connection->dropTrigger($trigger->getName());
@@ -188,7 +191,7 @@ protected function getLinkedViews()
188191
$viewList = $this->viewCollection->getViewsByStateMode(StateInterface::MODE_ENABLED);
189192

190193
foreach ($viewList as $view) {
191-
/** @var \Magento\Framework\Mview\ViewInterface $view */
194+
/** @var ViewInterface $view */
192195
// Skip the current view
193196
if ($view->getId() == $this->getView()->getId()) {
194197
continue;
@@ -208,21 +211,22 @@ protected function getLinkedViews()
208211
/**
209212
* Prepare columns for trigger statement. Should be protected in order to serve new approach
210213
*
211-
* @param ChangelogInterface $changelog
214+
* @param ViewInterface $view
212215
* @param string $event
213216
* @return array
214217
* @throws \Exception
215218
*/
216-
protected function prepareColumns(ChangelogInterface $changelog, string $event): array
219+
protected function prepareColumns(ViewInterface $view, string $event): array
217220
{
221+
$changelog = $view->getChangelog();
218222
$prefix = $event === Trigger::EVENT_DELETE ? 'OLD.' : 'NEW.';
219223
$subscriptionData = $this->mviewConfig->getView($changelog->getViewId())['subscriptions'][$this->getTableName()];
220224
$columns = [
221225
'column_names' => [
222226
'entity_id' => $this->connection->quoteIdentifier($changelog->getColumnName())
223227
],
224228
'column_values' => [
225-
'entity_id' => $this->getEntityColumn($prefix)
229+
'entity_id' => $this->getEntityColumn($prefix, $view)
226230
]
227231
];
228232

@@ -241,12 +245,14 @@ protected function prepareColumns(ChangelogInterface $changelog, string $event):
241245
* Build trigger statement for INSERT, UPDATE, DELETE events
242246
*
243247
* @param string $event
244-
* @param \Magento\Framework\Mview\View\ChangelogInterface $changelog
248+
* @param ViewInterface $view
245249
* @return string
246250
*/
247-
protected function buildStatement($event, $changelog)
251+
protected function buildStatement(string $event, ViewInterface $view): string
248252
{
249253
$trigger = "%sINSERT IGNORE INTO %s (%s) VALUES (%s);";
254+
$changelog = $view->getChangelog();
255+
250256
switch ($event) {
251257
case Trigger::EVENT_UPDATE:
252258
$tableName = $this->resource->getTableName($this->getTableName());
@@ -279,13 +285,14 @@ protected function buildStatement($event, $changelog)
279285
}
280286
break;
281287
}
282-
$columns = $this->prepareColumns($changelog, $event);
288+
$columns = $this->prepareColumns($view, $event);
289+
283290
return sprintf(
284291
$trigger,
285292
$this->getProcessor()->getPreStatements(),
286293
$this->connection->quoteIdentifier($this->resource->getTableName($changelog->getName())),
287-
implode(", " , $columns['column_names']),
288-
implode(", ", $columns['column_values'])
294+
implode(', ', $columns['column_names']),
295+
implode(', ', $columns['column_values'])
289296
);
290297
}
291298

@@ -312,11 +319,28 @@ private function getProcessor(): AdditionalColumnProcessorInterface
312319

313320
/**
314321
* @param string $prefix
322+
* @param ViewInterface $view
323+
* @return string
324+
*/
325+
public function getEntityColumn(string $prefix, ViewInterface $view): string
326+
{
327+
return $prefix . $this->connection->quoteIdentifier($this->getSubscriptionColumn($view));
328+
}
329+
330+
/**
331+
* Returns subscription column name by view
332+
*
333+
* @param ViewInterface $view
315334
* @return string
316335
*/
317-
public function getEntityColumn(string $prefix): string
336+
private function getSubscriptionColumn(ViewInterface $view): string
318337
{
319-
return $prefix . $this->connection->quoteIdentifier($this->getColumnName());
338+
$subscriptions = $view->getSubscriptions();
339+
if (!isset($subscriptions[$this->getTableName()]['column'])) {
340+
throw new \RuntimeException(sprintf('Column name for view with id "%s" doesn\'t exist', $view->getId()));
341+
}
342+
343+
return $subscriptions[$this->getTableName()]['column'];
320344
}
321345

322346
/**
@@ -338,7 +362,7 @@ private function getAfterEventTriggerName($event)
338362
/**
339363
* Retrieve View related to subscription
340364
*
341-
* @return \Magento\Framework\Mview\ViewInterface
365+
* @return ViewInterface
342366
* @codeCoverageIgnore
343367
*/
344368
public function getView()

0 commit comments

Comments
 (0)