Skip to content

Commit d4e7d53

Browse files
committed
ACP2E-4094: Add index check for queries when loggging mode is enabled.
1 parent d5ee334 commit d4e7d53

File tree

4 files changed

+40
-19
lines changed

4 files changed

+40
-19
lines changed

lib/internal/Magento/Framework/DB/Logger/LoggerAbstract.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -158,8 +158,8 @@ private function buildDebugMessage(
158158
if ($this->logIndexCheck) {
159159
try {
160160
$message .= $this->processIndexCheck($sql, $bind) . self::LINE_DELIMITER;
161-
} catch (\InvalidArgumentException|QueryAnalyzerException) {
162-
$message .= 'INDEX CHECK: NA' . self::LINE_DELIMITER;
161+
} catch (QueryAnalyzerException $e) {
162+
$message .= 'INDEX CHECK: ' . strtoupper($e->getMessage()) . self::LINE_DELIMITER;
163163
}
164164
}
165165
break;
@@ -181,6 +181,7 @@ private function buildDebugMessage(
181181
* @param string $sql
182182
* @param array $bind
183183
* @return string
184+
* @throws QueryAnalyzerException
184185
*/
185186
private function processIndexCheck(string $sql, array $bind): string
186187
{

lib/internal/Magento/Framework/DB/Logger/QueryAnalyzerInterface.php

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,14 +17,15 @@ interface QueryAnalyzerInterface
1717

1818
public const DEPENDENT_SUBQUERY = 'DEPENDENT SUBQUERY';
1919

20-
public const PARTIAL_INDEX = 'PARTIAL INDEX USED';
20+
public const PARTIAL_INDEX = 'PARTIAL INDEX';
2121

2222
/**
2323
* Analyze query
2424
*
2525
* @param string $sql
2626
* @param array $bindings
2727
* @return array
28+
* @throws QueryAnalyzerException
2829
*/
2930
public function process(string $sql, array $bindings): array;
3031
}

lib/internal/Magento/Framework/DB/Logger/QueryIndexAnalyzer.php

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,9 @@ public function __construct(
3434
private readonly Json $serializer,
3535
?int $smallTableThreshold = null
3636
) {
37-
if ($smallTableThreshold !== null) {
38-
$this->smallTableThreshold = $smallTableThreshold;
39-
} else {
40-
$this->smallTableThreshold = self::DEFAULT_SMALL_TABLE_THRESHOLD;
41-
}
37+
$this->smallTableThreshold = ((int) $smallTableThreshold > 0)
38+
? (int) $smallTableThreshold
39+
: self::DEFAULT_SMALL_TABLE_THRESHOLD;
4240
}
4341

4442
/**
@@ -47,12 +45,12 @@ public function __construct(
4745
* @param string $sql
4846
* @param array $bindings
4947
* @return array
50-
* @throws \Zend_Db_Statement_Exception|\InvalidArgumentException|QueryAnalyzerException
48+
* @throws \Zend_Db_Statement_Exception|QueryAnalyzerException
5149
*/
5250
public function process(string $sql, array $bindings): array
5351
{
5452
if (!$this->isSelectQuery($sql)) {
55-
throw new \InvalidArgumentException("Can't process query type");
53+
throw new QueryAnalyzerException("Can't process query type");
5654
}
5755

5856
$cacheKey = $this->generateCacheKey($sql, $bindings);
@@ -65,7 +63,7 @@ public function process(string $sql, array $bindings): array
6563
}
6664

6765
if (empty($explainOutput)) {
68-
throw new \InvalidArgumentException("No 'explain' output available");
66+
throw new QueryAnalyzerException("No 'explain' output available");
6967
}
7068

7169
$issues = $this->analyzeQueries($explainOutput);

lib/internal/Magento/Framework/DB/Test/Unit/Logger/QueryIndexAnalyzerTest.php

Lines changed: 29 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
use Magento\Framework\DB\Adapter\AdapterInterface;
1212
use Magento\Framework\DB\Logger\File;
1313
use Magento\Framework\DB\Logger\QueryAnalyzerException;
14+
use Magento\Framework\DB\Logger\QueryAnalyzerInterface;
1415
use Magento\Framework\DB\Logger\QueryIndexAnalyzer;
1516
use Magento\Framework\DB\LoggerInterface;
1617
use Magento\Framework\Exception\FileSystemException;
@@ -51,18 +52,27 @@ protected function setUp(): void
5152
/**
5253
* @param string $sql
5354
* @param array $bind
55+
* @param int $serializeCall
5456
* @param string $explainResult
5557
* @param mixed $expectedResult
5658
* @return void
57-
* @throws Exception|\Magento\Framework\DB\Logger\QueryAnalyzerException|\Zend_Db_Statement_Exception
59+
* @throws Exception
60+
* @throws QueryAnalyzerException
61+
* @throws \Zend_Db_Statement_Exception
62+
* @testdox $sql with bindings $bind to get $expectedResult
5863
* @dataProvider statsDataProvider
5964
*/
6065
public function testProcess(
6166
string $sql,
6267
array $bind,
68+
int $serializeCall,
6369
string $explainResult,
6470
mixed $expectedResult
6571
): void {
72+
$this->serializer->expects($this->exactly($serializeCall))
73+
->method('serialize')
74+
->with($bind)
75+
->willReturn(json_encode($bind));
6676
$statement = $this->createMock(\Zend_Db_Statement_Interface::class);
6777
$statement->expects($this->any())->method('fetchAll')->willReturn(json_decode($explainResult, true));
6878
$connection = $this->createMock(AdapterInterface::class);
@@ -91,29 +101,33 @@ public static function statsDataProvider(): array
91101
'no-stats-for-update-query' => [
92102
"UPDATE `admin_user_session` SET `updated_at` = '2025-07-23 14:42:02' WHERE (id=5)",
93103
[],
104+
0,
94105
'{}',
95-
new \InvalidArgumentException("Can't process query type")
106+
new QueryAnalyzerException("Can't process query type")
96107
],
97108
'no-stats-for-insert-query' => [
98109
"INSERT INTO `table_logging_event` (`ip`, `x_forwarded_ip`, `event_code`, `time`, `action`, `info`,
99110
`status`, `user`, `user_id`, `fullaction`, `error_message`) VALUES
100111
(?, ?, ?, '2025-07-23 14:42:02', ?, ?, ?, ?, ?, ?, ?)",
101112
[],
113+
0,
102114
'{}',
103-
new \InvalidArgumentException("Can't process query type")
115+
new QueryAnalyzerException("Can't process query type")
104116
],
105117
'no-stats-for-delete-query' => [
106118
"DELETE FROM `sales_order_grid` WHERE (entity_id IN
107119
(SELECT `magento_sales_order_grid_archive`.`entity_id`
108120
FROM `magento_sales_order_grid_archive`))",
109121
[],
122+
0,
110123
'{}',
111-
new \InvalidArgumentException("Can't process query type")
124+
new QueryAnalyzerException("Can't process query type")
112125
],
113126
'small-table-query' => [
114127
"SELECT `main_table`.* FROM `admin_system_messages` AS `main_table`
115128
ORDER BY severity ASC, created_at DESC",
116129
[],
130+
1,
117131
'[{"id":"1","select_type":"SIMPLE","table":"admin_system_messages","partitions":null,"type":"ALL",
118132
"possible_keys":null,"key":null,"key_len":null,"ref":null,"rows":"1","filtered":"100.00",
119133
"Extra":"Using filesort"}]',
@@ -130,6 +144,7 @@ public static function statsDataProvider(): array
130144
)) AS `status` FROM `magento_bulk` AS `main_table` WHERE (`user_id` = '1')
131145
ORDER BY FIELD(status, 2,3,0,4,1), start_time DESC",
132146
[],
147+
1,
133148
'[{"id":"1","select_type":"PRIMARY","table":"main_table","partitions":null,"type":"ref",
134149
"possible_keys":"MAGENTO_BULK_USER_ID","key":"MAGENTO_BULK_USER_ID","key_len":"5","ref":"const",
135150
"rows":"1","filtered":"100.00","Extra":"Using filesort"},{"id":"3","select_type":"DEPENDENT SUBQUERY",
@@ -140,18 +155,23 @@ public static function statsDataProvider(): array
140155
"type":"ref","possible_keys":"MAGENTO_OPERATION_BULK_UUID_ERROR_CODE","key":
141156
"MAGENTO_OPERATION_BULK_UUID_ERROR_CODE","key_len":"42","ref":
142157
"magento24i2.main_table.uuid","rows":"1","filtered":"100.00","Extra":"Using index"}]',
143-
['FILESORT', 'PARTIAL INDEX USED', 'DEPENDENT SUBQUERY']
158+
[
159+
QueryAnalyzerInterface::FILESORT,
160+
QueryAnalyzerInterface::PARTIAL_INDEX,
161+
QueryAnalyzerInterface::DEPENDENT_SUBQUERY
162+
]
144163
],
145-
'simple-qeury-partial-index' => [
164+
'simple-query-partial-index' => [
146165
"SELECT `o`.`product_type`, COUNT(*) FROM `sales_order_item` AS `o` WHERE (o.order_id='67') AND
147166
(o.product_id IS NOT NULL) AND ((o.product_type NOT IN
148167
('simple', 'virtual', 'bundle', 'downloadable', 'configurable', 'grouped')))
149168
GROUP BY `o`.`product_type`",
150169
[],
170+
1,
151171
'[{"id":1,"select_type":"SIMPLE","table":"o","partitions":null,"type":"ref","possible_keys":
152172
"SALES_ORDER_ITEM_ORDER_ID","key":"SALES_ORDER_ITEM_ORDER_ID","key_len":"4","ref":"const",
153173
"rows":2,"filtered":45,"Extra":"Using where; Using temporary"}]',
154-
['PARTIAL INDEX USED']
174+
[QueryAnalyzerInterface::PARTIAL_INDEX]
155175
],
156176
'full-table-scan-no-index' => [
157177
"SELECT `main_table`.`entity_type_id`, `main_table`.`attribute_code`, `main_table`.`attribute_model`,
@@ -165,13 +185,14 @@ public static function statsDataProvider(): array
165185
OR (`is_visible_in_advanced_search` = '1') OR (((`is_filterable` = '1') OR (`is_filterable` = '2')))
166186
OR (`is_filterable_in_search` = '1'))",
167187
[],
188+
1,
168189
'[{"id":1,"select_type":"SIMPLE","table":"additional_table","partitions":null,"type":"ALL",
169190
"possible_keys":"PRIMARY","key":null,"key_len":null,"ref":null,"rows":170,"filtered":40.95,"Extra":
170191
"Using where"},{"id":1,"select_type":"SIMPLE","table":"main_table","partitions":null,"type":"eq_ref",
171192
"possible_keys":"PRIMARY,EAV_ATTRIBUTE_ENTITY_TYPE_ID_ATTRIBUTE_CODE","key":"PRIMARY",
172193
"key_len":"2","ref":"magento24i2.additional_table.attribute_id","rows":1,"filtered":58.72,
173194
"Extra":"Using where"}]',
174-
['FULL TABLE SCAN', 'NO INDEX']
195+
[QueryAnalyzerInterface::FULL_TABLE_SCAN, QueryAnalyzerInterface::NO_INDEX]
175196
],
176197
];
177198
}

0 commit comments

Comments
 (0)