Skip to content

Commit 2bdfa14

Browse files
authored
Merge pull request #134 from moufmouf/cache_findObjectsQueryFactory_5.1
Porting perf improvement to 5.1
2 parents f8e495e + 2e2552b commit 2bdfa14

File tree

10 files changed

+135
-34
lines changed

10 files changed

+135
-34
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919
],
2020
"require" : {
2121
"php" : ">=7.1",
22-
"mouf/magic-query" : "^1.2.8",
22+
"mouf/magic-query" : "^1.3.0",
2323
"mouf/schema-analyzer": "^1.1.4",
2424
"doctrine/dbal": "^2.9.2",
2525
"psr/log": "~1.0",

src/InnerResultIterator.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
use Doctrine\DBAL\Statement;
88
use Mouf\Database\MagicQuery;
99
use Psr\Log\LoggerInterface;
10+
use TheCodingMachine\TDBM\Utils\DbalUtils;
1011

1112
/*
1213
Copyright (C) 2006-2017 David Négrier - THE CODING MACHINE
@@ -85,7 +86,7 @@ public function __construct(string $magicSql, array $parameters, ?int $limit, ?i
8586

8687
private function getQuery(): string
8788
{
88-
$sql = $this->magicQuery->build($this->magicSql, $this->parameters);
89+
$sql = $this->magicQuery->buildPreparedStatement($this->magicSql, $this->parameters);
8990
$sql = $this->tdbmService->getConnection()->getDatabasePlatform()->modifyLimitQuery($sql, $this->limit, $this->offset);
9091
return $sql;
9192
}
@@ -96,7 +97,7 @@ protected function executeQuery(): void
9697

9798
$this->logger->debug('Running SQL request: '.$sql);
9899

99-
$this->statement = $this->tdbmService->getConnection()->executeQuery($sql, $this->parameters);
100+
$this->statement = $this->tdbmService->getConnection()->executeQuery($sql, $this->parameters, DbalUtils::generateArrayTypes($this->parameters));
100101

101102
$this->fetchStarted = true;
102103
}

src/QueryFactory/FindObjectsQueryFactory.php

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
namespace TheCodingMachine\TDBM\QueryFactory;
55

6+
use Doctrine\Common\Cache\Cache;
67
use Doctrine\DBAL\Platforms\MySqlPlatform;
78
use Doctrine\DBAL\Schema\Schema;
89
use TheCodingMachine\TDBM\OrderByAnalyzer;
@@ -16,17 +17,32 @@ class FindObjectsQueryFactory extends AbstractQueryFactory
1617
private $mainTable;
1718
private $additionalTablesFetch;
1819
private $filterString;
20+
/**
21+
* @var Cache
22+
*/
23+
private $cache;
1924

20-
public function __construct(string $mainTable, array $additionalTablesFetch, $filterString, $orderBy, TDBMService $tdbmService, Schema $schema, OrderByAnalyzer $orderByAnalyzer)
25+
public function __construct(string $mainTable, array $additionalTablesFetch, $filterString, $orderBy, TDBMService $tdbmService, Schema $schema, OrderByAnalyzer $orderByAnalyzer, Cache $cache)
2126
{
2227
parent::__construct($tdbmService, $schema, $orderByAnalyzer, $orderBy);
2328
$this->mainTable = $mainTable;
2429
$this->additionalTablesFetch = $additionalTablesFetch;
2530
$this->filterString = $filterString;
31+
$this->cache = $cache;
2632
}
2733

2834
protected function compute(): void
2935
{
36+
$key = 'FindObjectsQueryFactory_'.$this->mainTable.'__'.implode('_/_',$this->additionalTablesFetch).'__'.$this->filterString.'__'.$this->orderBy;
37+
if ($this->cache->contains($key)) {
38+
[
39+
$this->magicSql,
40+
$this->magicSqlCount,
41+
$this->columnDescList
42+
] = $this->cache->fetch($key);
43+
return;
44+
}
45+
3046
list($columnDescList, $columnsList, $orderString) = $this->getColumnsList($this->mainTable, $this->additionalTablesFetch, $this->orderBy, true);
3147

3248
$sql = 'SELECT DISTINCT '.implode(', ', $columnsList).' FROM MAGICJOIN('.$this->mainTable.')';
@@ -54,5 +70,11 @@ protected function compute(): void
5470
$this->magicSql = $sql;
5571
$this->magicSqlCount = $countSql;
5672
$this->columnDescList = $columnDescList;
73+
74+
$this->cache->save($key, [
75+
$this->magicSql,
76+
$this->magicSqlCount,
77+
$this->columnDescList,
78+
]);
5779
}
5880
}

src/ResultIterator.php

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,16 @@
33

44
namespace TheCodingMachine\TDBM;
55

6+
use function array_map;
7+
use Doctrine\DBAL\Connection;
68
use Doctrine\DBAL\Statement;
9+
use function is_array;
10+
use function is_int;
711
use Mouf\Database\MagicQuery;
812
use TheCodingMachine\TDBM\QueryFactory\QueryFactory;
913
use Porpaginas\Result;
1014
use Psr\Log\LoggerInterface;
15+
use TheCodingMachine\TDBM\Utils\DbalUtils;
1116
use Traversable;
1217

1318
/*
@@ -82,9 +87,9 @@ public function __construct(QueryFactory $queryFactory, array $parameters, Objec
8287

8388
protected function executeCountQuery(): void
8489
{
85-
$sql = $this->magicQuery->build($this->queryFactory->getMagicSqlCount(), $this->parameters);
90+
$sql = $this->magicQuery->buildPreparedStatement($this->queryFactory->getMagicSqlCount(), $this->parameters);
8691
$this->logger->debug('Running count query: '.$sql);
87-
$this->totalCount = (int) $this->tdbmService->getConnection()->fetchColumn($sql, $this->parameters);
92+
$this->totalCount = (int) $this->tdbmService->getConnection()->fetchColumn($sql, $this->parameters, 0, DbalUtils::generateArrayTypes($this->parameters));
8893
}
8994

9095
/**

src/TDBMService.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -403,7 +403,7 @@ public function buildFilterFromFilterBag($filter_bag, AbstractPlatform $platform
403403
} else {
404404
$paramName = 'tdbmparam'.$counter;
405405
if (is_array($value)) {
406-
$sqlParts[] = $platform->quoteIdentifier($column).' IN :'.$paramName;
406+
$sqlParts[] = $platform->quoteIdentifier($column).' IN (:'.$paramName.')';
407407
} else {
408408
$sqlParts[] = $platform->quoteIdentifier($column).' = :'.$paramName;
409409
}
@@ -1134,7 +1134,7 @@ public function findObjects(string $mainTable, $filter = null, array $parameters
11341134

11351135
$parameters = array_merge($parameters, $additionalParameters);
11361136

1137-
$queryFactory = new FindObjectsQueryFactory($mainTable, $additionalTablesFetch, $filterString, $orderString, $this, $this->tdbmSchemaAnalyzer->getSchema(), $this->orderByAnalyzer);
1137+
$queryFactory = new FindObjectsQueryFactory($mainTable, $additionalTablesFetch, $filterString, $orderString, $this, $this->tdbmSchemaAnalyzer->getSchema(), $this->orderByAnalyzer, $this->cache);
11381138

11391139
return new ResultIterator($queryFactory, $parameters, $this->objectStorage, $className, $this, $this->magicQuery, $mode, $this->logger);
11401140
}

src/UncheckedOrderBy.php

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,4 +35,12 @@ public function getOrderBy() : string
3535
{
3636
return $this->orderBy;
3737
}
38+
39+
/**
40+
* @return string
41+
*/
42+
public function __toString()
43+
{
44+
return 'UncheckedOrderBy_'.$this->orderBy;
45+
}
3846
}

src/Utils/DbalUtils.php

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
<?php
2+
3+
4+
namespace TheCodingMachine\TDBM\Utils;
5+
6+
use Doctrine\DBAL\Connection;
7+
use function is_array;
8+
use function is_int;
9+
10+
/**
11+
* Utility class to ease the use of DBAL types.
12+
*/
13+
class DbalUtils
14+
{
15+
/**
16+
* If a parameter is an array (used in a "IN" statement), we need to tell Doctrine about it.
17+
* @see https://www.doctrine-project.org/projects/doctrine-dbal/en/2.9/reference/data-retrieval-and-manipulation.html#list-of-parameters-conversion
18+
* @param array<string, mixed> $parameters
19+
* @return array<string, int>
20+
*/
21+
public static function generateArrayTypes(array $parameters): array
22+
{
23+
$types = [];
24+
foreach ($parameters as $key => $value) {
25+
if (is_array($value)) {
26+
foreach ($value as $val) {
27+
if (!is_int($val)) {
28+
$types[$key] = Connection::PARAM_STR_ARRAY;
29+
continue 2;
30+
}
31+
}
32+
$types[$key] = Connection::PARAM_INT_ARRAY;
33+
}
34+
}
35+
36+
return $types;
37+
}
38+
}

tests/Utils/DbalUtilsTest.php

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
<?php
2+
3+
namespace TheCodingMachine\TDBM\Utils;
4+
5+
use Doctrine\DBAL\Connection;
6+
use PHPUnit\Framework\TestCase;
7+
8+
class DbalUtilsTest extends TestCase
9+
{
10+
11+
public function testGenerateArrayTypes()
12+
{
13+
$params = [
14+
'key1' => 'foo',
15+
'key2' => [1,2,3],
16+
'key3' => [1,2,'baz'],
17+
];
18+
19+
$this->assertSame(['key2'=>Connection::PARAM_INT_ARRAY, 'key3'=>Connection::PARAM_STR_ARRAY], DbalUtils::generateArrayTypes($params));
20+
}
21+
}

vendor-bin/couscous/composer.lock

Lines changed: 21 additions & 18 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)