Skip to content

Commit b16754d

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

File tree

2 files changed

+37
-5
lines changed

2 files changed

+37
-5
lines changed

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

Lines changed: 29 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
namespace Magento\Framework\DB\Logger;
99

1010
use Magento\Framework\App\ResourceConnection;
11+
use Magento\Framework\Serialize\Serializer\Json;
1112

1213
class QueryIndexAnalyzer implements QueryAnalyzerInterface
1314
{
@@ -18,12 +19,18 @@ class QueryIndexAnalyzer implements QueryAnalyzerInterface
1819
*/
1920
private int $smallTableThreshold;
2021

22+
private array $analyzerCache = [];
23+
2124
/**
2225
* @param ResourceConnection $resource
26+
* @param Json $serializer
2327
* @param int|null $smallTableThreshold
2428
*/
25-
public function __construct(private readonly ResourceConnection $resource, ?int $smallTableThreshold = null)
26-
{
29+
public function __construct(
30+
private readonly ResourceConnection $resource,
31+
private readonly Json $serializer,
32+
?int $smallTableThreshold = null
33+
) {
2734
if ($smallTableThreshold !== null) {
2835
$this->smallTableThreshold = $smallTableThreshold;
2936
} else {
@@ -45,8 +52,14 @@ public function process(string $sql, array $bindings): array
4552
throw new \InvalidArgumentException("Can't process query type");
4653
}
4754

48-
$connection = $this->resource->getConnection();
49-
$explainOutput = $connection->query('EXPLAIN ' . $sql, $bindings)->fetchAll();
55+
$cacheKey = $this->generateCacheKey($sql, $bindings);
56+
if(isset($this->analyzerCache[$cacheKey])) {
57+
$explainOutput = $this->analyzerCache[$cacheKey];
58+
} else {
59+
$connection = $this->resource->getConnection();
60+
$explainOutput = $connection->query('EXPLAIN ' . $sql, $bindings)->fetchAll();
61+
$this->analyzerCache[$cacheKey] = $explainOutput;
62+
}
5063

5164
if (empty($explainOutput)) {
5265
throw new \InvalidArgumentException("No 'explain' output available");
@@ -60,6 +73,18 @@ public function process(string $sql, array $bindings): array
6073
return array_values(array_unique($issues));
6174
}
6275

76+
/**
77+
* Generate a cache key based on the SQL query and its bindings.
78+
*
79+
* @param string $sql
80+
* @param array $bindings
81+
* @return string
82+
*/
83+
private function generateCacheKey(string $sql, array $bindings): string
84+
{
85+
return base64_encode(hash('sha256', $sql . '|' . $this->serializer->serialize($bindings), true));
86+
}
87+
6388
/**
6489
* Detects if a given SQL string is a SELECT query.
6590
*

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

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Magento\Framework\DB\Logger\QueryIndexAnalyzer;
1515
use Magento\Framework\DB\LoggerInterface;
1616
use Magento\Framework\Exception\FileSystemException;
17+
use Magento\Framework\Serialize\Serializer\Json;
1718
use PHPUnit\Framework\MockObject\Exception;
1819
use PHPUnit\Framework\MockObject\MockObject;
1920
use PHPUnit\Framework\TestCase;
@@ -30,13 +31,19 @@ class QueryIndexAnalyzerTest extends TestCase
3031
*/
3132
private QueryIndexAnalyzer $queryAnalyzer;
3233

34+
/**
35+
* @var Json|MockObject
36+
*/
37+
private Json $serializer;
38+
3339
/**
3440
* @inheritDoc
3541
*/
3642
protected function setUp(): void
3743
{
3844
$this->resource = $this->createMock(ResourceConnection::class);
39-
$this->queryAnalyzer = new QueryIndexAnalyzer($this->resource);
45+
$this->serializer = $this->createMock(Json::class);
46+
$this->queryAnalyzer = new QueryIndexAnalyzer($this->resource, $this->serializer);
4047

4148
parent::setUp();
4249
}

0 commit comments

Comments
 (0)