From 97bcc3a948bbcd7afd8665489216584953a6299f Mon Sep 17 00:00:00 2001 From: Greg Bowler Date: Tue, 26 May 2026 22:48:29 +0100 Subject: [PATCH 1/2] test: isolate issue #409 --- test/phpunit/Query/QueryFactoryTest.php | 63 +++++++++++++++++++++++++ 1 file changed, 63 insertions(+) diff --git a/test/phpunit/Query/QueryFactoryTest.php b/test/phpunit/Query/QueryFactoryTest.php index 1d8fb0f..e57c261 100644 --- a/test/phpunit/Query/QueryFactoryTest.php +++ b/test/phpunit/Query/QueryFactoryTest.php @@ -402,4 +402,67 @@ public function testFindQueryFilePathPrefersSupportedExtensionOverEditorBackup() Helper::deleteDir($basePath); } } + + public function testFindQueryFilePathCachesResolvedPaths():void { + $basePath = Helper::getTmpDir(); + $queryDirectory = implode(DIRECTORY_SEPARATOR, [ + $basePath, + "query", + ]); + mkdir($queryDirectory, 0775, true); + file_put_contents("$queryDirectory/report.sql", "select 1"); + + try { + $sut = $this->createCountingQueryFactory($queryDirectory); + + $firstPath = $sut->findQueryFilePath("report"); + $secondPath = $sut->findQueryFilePath("report"); + + self::assertSame($firstPath, $secondPath); + self::assertSame(1, $sut->directoryScanCount); + } + finally { + Helper::deleteDir($basePath); + } + } + + public function testCreateCachesResolvedPathsBetweenCalls():void { + $basePath = Helper::getTmpDir(); + $queryDirectory = implode(DIRECTORY_SEPARATOR, [ + $basePath, + "query", + ]); + mkdir($queryDirectory, 0775, true); + file_put_contents("$queryDirectory/report.sql", "select 1"); + + try { + $sut = $this->createCountingQueryFactory($queryDirectory); + + $firstQuery = $sut->create("report"); + $secondQuery = $sut->create("report"); + + self::assertSame($firstQuery->getFilePath(), $secondQuery->getFilePath()); + self::assertSame(1, $sut->directoryScanCount); + } + finally { + Helper::deleteDir($basePath); + } + } + + private function createCountingQueryFactory(string $queryDirectory):QueryFactory { + return new class( + $queryDirectory, + new Driver(new DefaultSettings()) + ) extends QueryFactory { + public int $directoryScanCount = 0; + + protected function findQueryFilePathInDirectory( + string $directory, + string $name, + ):?string { + $this->directoryScanCount++; + return parent::findQueryFilePathInDirectory($directory, $name); + } + }; + } } From 21f420371f576023740ded0296a0faea2fb7a65a Mon Sep 17 00:00:00 2001 From: Greg Bowler Date: Tue, 26 May 2026 22:50:04 +0100 Subject: [PATCH 2/2] fix: implement caching of query files fixes #409 --- src/Query/QueryFactory.php | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/src/Query/QueryFactory.php b/src/Query/QueryFactory.php index 608072c..398d729 100644 --- a/src/Query/QueryFactory.php +++ b/src/Query/QueryFactory.php @@ -14,6 +14,8 @@ class QueryFactory { "sql" => SqlQuery::class, "php" => PhpQuery::class, ]; + /** @var array */ + protected array $queryFilePathCache = []; public function __construct( protected string $queryHolder, @@ -21,13 +23,17 @@ public function __construct( ) {} public function findQueryFilePath(string $name):string { + if(isset($this->queryFilePathCache[$name])) { + return $this->queryFilePathCache[$name]; + } + if(is_dir($this->queryHolder)) { $queryFilePath = $this->findQueryFilePathInDirectory( $this->queryHolder, $name ); if($queryFilePath) { - return $queryFilePath; + return $this->queryFilePathCache[$name] = $queryFilePath; } } elseif(is_file($this->queryHolder)) { @@ -46,11 +52,11 @@ public function findQueryFilePath(string $name):string { ); } - return $queryFilePath; + return $this->queryFilePathCache[$name] = $queryFilePath; } } - return "$this->queryHolder::$name"; + return $this->queryFilePathCache[$name] = "$this->queryHolder::$name"; } throw new QueryNotFoundException($this->queryHolder . ", " . $name);