17
17
class Collection extends \Magento \Catalog \Model \ResourceModel \Product \Collection implements
18
18
\Magento \Search \Model \SearchCollectionInterface
19
19
{
20
+ /**
21
+ * @var array
22
+ */
23
+ private $ indexUsageEnforcements ;
24
+
20
25
/**
21
26
* Attribute collection
22
27
*
@@ -61,6 +66,7 @@ class Collection extends \Magento\Catalog\Model\ResourceModel\Product\Collection
61
66
* @param \Magento\Customer\Api\GroupManagementInterface $groupManagement
62
67
* @param \Magento\Catalog\Model\ResourceModel\Product\Attribute\CollectionFactory $attributeCollectionFactory
63
68
* @param \Magento\Framework\DB\Adapter\AdapterInterface $connection
69
+ * @param array $indexUsageEnforcements
64
70
* @SuppressWarnings(PHPMD.ExcessiveParameterList)
65
71
*/
66
72
public function __construct (
@@ -84,7 +90,8 @@ public function __construct(
84
90
\Magento \Framework \Stdlib \DateTime $ dateTime ,
85
91
\Magento \Customer \Api \GroupManagementInterface $ groupManagement ,
86
92
\Magento \Catalog \Model \ResourceModel \Product \Attribute \CollectionFactory $ attributeCollectionFactory ,
87
- \Magento \Framework \DB \Adapter \AdapterInterface $ connection = null
93
+ \Magento \Framework \DB \Adapter \AdapterInterface $ connection = null ,
94
+ array $ indexUsageEnforcements = []
88
95
) {
89
96
$ this ->_attributeCollectionFactory = $ attributeCollectionFactory ;
90
97
parent ::__construct (
@@ -109,6 +116,7 @@ public function __construct(
109
116
$ groupManagement ,
110
117
$ connection
111
118
);
119
+ $ this ->indexUsageEnforcements = $ indexUsageEnforcements ;
112
120
}
113
121
114
122
/**
@@ -197,6 +205,35 @@ protected function _hasAttributeOptionsAndSearchable($attribute)
197
205
return false ;
198
206
}
199
207
208
+ /**
209
+ * Prepare table names for the index enforcements
210
+ *
211
+ * @return array
212
+ */
213
+ private function prepareIndexEnforcements () : array
214
+ {
215
+ $ result = [];
216
+ foreach ($ this ->indexUsageEnforcements as $ table => $ index ) {
217
+ $ table = $ this ->getTable ($ table );
218
+ if ($ this ->isIndexExists ($ table , $ index )) {
219
+ $ result [$ table ] = $ index ;
220
+ }
221
+ }
222
+ return $ result ;
223
+ }
224
+
225
+ /**
226
+ * Check if index exists in the table
227
+ *
228
+ * @param string $table
229
+ * @param string $index
230
+ * @return bool
231
+ */
232
+ private function isIndexExists (string $ table , string $ index ) : bool
233
+ {
234
+ return array_key_exists ($ index , $ this ->_conn ->getIndexList ($ table ));
235
+ }
236
+
200
237
/**
201
238
* Retrieve SQL for search entities
202
239
*
@@ -208,6 +245,7 @@ protected function _getSearchEntityIdsSql($query, $searchOnlyInCurrentStore = tr
208
245
{
209
246
$ tables = [];
210
247
$ selects = [];
248
+ $ preparedIndexEnforcements = $ this ->prepareIndexEnforcements ();
211
249
212
250
$ likeOptions = ['position ' => 'any ' ];
213
251
@@ -249,23 +287,56 @@ protected function _getSearchEntityIdsSql($query, $searchOnlyInCurrentStore = tr
249
287
250
288
$ ifValueId = $ this ->getConnection ()->getIfNullSql ('t2.value ' , 't1.value ' );
251
289
foreach ($ tables as $ table => $ attributeIds ) {
252
- $ selects [] = $ this ->getConnection ()->select ()->from (
253
- ['t1 ' => $ table ],
254
- $ linkField
255
- )->joinLeft (
256
- ['t2 ' => $ table ],
257
- $ joinCondition ,
258
- []
259
- )->where (
260
- 't1.attribute_id IN (?) ' ,
261
- $ attributeIds ,
262
- \Zend_Db::INT_TYPE
263
- )->where (
264
- 't1.store_id = ? ' ,
265
- 0
266
- )->where (
267
- $ this ->_resourceHelper ->getCILike ($ ifValueId , $ this ->_searchQuery , $ likeOptions )
268
- );
290
+ if (!empty ($ preparedIndexEnforcements [$ table ])) {
291
+ $ condition1 = $ this ->_conn ->quoteInto (
292
+ '`t1`.`attribute_id` IN (?) ' ,
293
+ $ attributeIds ,
294
+ \Zend_Db::INT_TYPE
295
+ );
296
+ $ condition2 = '`t1`.`store_id` = 0 ' ;
297
+ $ quotedField = $ this ->_conn ->quoteIdentifier ($ ifValueId );
298
+ $ condition3 = $ this ->_conn ->quoteInto (
299
+ $ quotedField . ' LIKE ? ' ,
300
+ $ this ->_resourceHelper ->addLikeEscape ($ this ->_searchQuery , $ likeOptions )
301
+ );
302
+
303
+ //force index statement not implemented in framework
304
+ // phpcs:ignore Magento2.SQL.RawQuery
305
+ $ select = sprintf (
306
+ 'SELECT `t1`.`%s` FROM `%s` AS `t1` FORCE INDEX(%s)
307
+ LEFT JOIN `%s` AS `t2` FORCE INDEX(%s)
308
+ ON %s WHERE %s AND %s AND (%s) ' ,
309
+ $ linkField ,
310
+ $ table ,
311
+ $ preparedIndexEnforcements [$ table ],
312
+ $ table ,
313
+ $ preparedIndexEnforcements [$ table ],
314
+ $ joinCondition ,
315
+ $ condition1 ,
316
+ $ condition2 ,
317
+ $ condition3
318
+ );
319
+ } else {
320
+ $ select = $ this ->getConnection ()->select ();
321
+ $ select ->from (
322
+ ['t1 ' => $ table ],
323
+ $ linkField
324
+ )->joinLeft (
325
+ ['t2 ' => $ table ],
326
+ $ joinCondition ,
327
+ []
328
+ )->where (
329
+ 't1.attribute_id IN (?) ' ,
330
+ $ attributeIds ,
331
+ \Zend_Db::INT_TYPE
332
+ )->where (
333
+ 't1.store_id = ? ' ,
334
+ 0
335
+ )->where (
336
+ $ this ->_resourceHelper ->getCILike ($ ifValueId , $ this ->_searchQuery , $ likeOptions )
337
+ );
338
+ }
339
+ $ selects [] = $ select ;
269
340
}
270
341
271
342
$ sql = $ this ->_getSearchInOptionSql ($ query );
0 commit comments