Skip to content

Commit 946da16

Browse files
committed
Move multiselect to separate class MultiSelecy
1 parent e4543eb commit 946da16

File tree

3 files changed

+112
-40
lines changed

3 files changed

+112
-40
lines changed

src/AbstractTable.php

+4-40
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Composite\DB;
44

55
use Composite\DB\MultiQuery\MultiInsert;
6+
use Composite\DB\MultiQuery\MultiSelect;
67
use Composite\Entity\Helpers\DateTimeHelper;
78
use Composite\Entity\AbstractEntity;
89
use Composite\DB\Exceptions\DbException;
@@ -225,52 +226,15 @@ protected function findOneInternal(array $where): ?array
225226
* @param array<int|string|array<string,mixed>> $pkList
226227
* @return array<array<string, mixed>>
227228
* @throws DbException
228-
* @throws EntityException
229229
* @throws \Doctrine\DBAL\Exception
230230
*/
231231
protected function findMultiInternal(array $pkList): array
232232
{
233233
if (!$pkList) {
234234
return [];
235235
}
236-
/** @var class-string<AbstractEntity> $class */
237-
$class = $this->config->entityClass;
238-
239-
$pkColumns = [];
240-
foreach ($this->config->primaryKeys as $primaryKeyName) {
241-
$pkColumns[$primaryKeyName] = $class::schema()->getColumn($primaryKeyName);
242-
}
243-
if (count($pkColumns) === 1) {
244-
if (!array_is_list($pkList)) {
245-
throw new DbException('Input argument $pkList must be list');
246-
}
247-
/** @var \Composite\Entity\Columns\AbstractColumn $pkColumn */
248-
$pkColumn = reset($pkColumns);
249-
$preparedPkValues = array_map(fn ($pk) => $pkColumn->uncast($pk), $pkList);
250-
$query = $this->select();
251-
$this->buildWhere($query, [$pkColumn->name => $preparedPkValues]);
252-
} else {
253-
$query = $this->select();
254-
$expressions = [];
255-
foreach ($pkList as $i => $pkArray) {
256-
if (!is_array($pkArray)) {
257-
throw new DbException('For tables with composite keys, input array must consist associative arrays');
258-
}
259-
$pkOrExpr = [];
260-
foreach ($pkArray as $pkName => $pkValue) {
261-
if (is_string($pkName) && isset($pkColumns[$pkName])) {
262-
$preparedPkValue = $pkColumns[$pkName]->cast($pkValue);
263-
$pkOrExpr[] = $query->expr()->eq($pkName, ':' . $pkName . $i);
264-
$query->setParameter($pkName . $i, $preparedPkValue);
265-
}
266-
}
267-
if ($pkOrExpr) {
268-
$expressions[] = $query->expr()->and(...$pkOrExpr);
269-
}
270-
}
271-
$query->where($query->expr()->or(...$expressions));
272-
}
273-
return $query->executeQuery()->fetchAllAssociative();
236+
$multiSelect = new MultiSelect($this->getConnection(), $this->config, $pkList);
237+
return $multiSelect->getQueryBuilder()->executeQuery()->fetchAllAssociative();
274238
}
275239

276240
/**
@@ -395,7 +359,7 @@ protected function select(string $select = '*'): QueryBuilder
395359
/**
396360
* @param array<string, mixed> $where
397361
*/
398-
private function buildWhere(QueryBuilder $query, array $where): void
362+
private function buildWhere(\Doctrine\DBAL\Query\QueryBuilder $query, array $where): void
399363
{
400364
foreach ($where as $column => $value) {
401365
if ($value === null) {

src/MultiQuery/MultiSelect.php

+64
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
<?php declare(strict_types=1);
2+
3+
namespace Composite\DB\MultiQuery;
4+
5+
use Composite\DB\Exceptions\DbException;
6+
use Composite\DB\TableConfig;
7+
use Composite\Entity\AbstractEntity;
8+
use Doctrine\DBAL\Connection;
9+
use Doctrine\DBAL\Query\QueryBuilder;
10+
11+
class MultiSelect
12+
{
13+
private readonly QueryBuilder $queryBuilder;
14+
15+
public function __construct(
16+
Connection $connection,
17+
TableConfig $tableConfig,
18+
array $condition,
19+
) {
20+
$query = $connection->createQueryBuilder()->select('*')->from($tableConfig->tableName);
21+
/** @var class-string<AbstractEntity> $class */
22+
$class = $tableConfig->entityClass;
23+
24+
$pkColumns = [];
25+
foreach ($tableConfig->primaryKeys as $primaryKeyName) {
26+
$pkColumns[$primaryKeyName] = $class::schema()->getColumn($primaryKeyName);
27+
}
28+
29+
if (count($pkColumns) === 1) {
30+
if (!array_is_list($condition)) {
31+
throw new DbException('Input argument $pkList must be list');
32+
}
33+
/** @var \Composite\Entity\Columns\AbstractColumn $pkColumn */
34+
$pkColumn = reset($pkColumns);
35+
$preparedPkValues = array_map(fn ($pk) => $pkColumn->uncast($pk), $condition);
36+
$query->andWhere($query->expr()->in($pkColumn->name, $preparedPkValues));
37+
} else {
38+
$expressions = [];
39+
foreach ($condition as $i => $pkArray) {
40+
if (!is_array($pkArray)) {
41+
throw new DbException('For tables with composite keys, input array must consist associative arrays');
42+
}
43+
$pkOrExpr = [];
44+
foreach ($pkArray as $pkName => $pkValue) {
45+
if (is_string($pkName) && isset($pkColumns[$pkName])) {
46+
$preparedPkValue = $pkColumns[$pkName]->cast($pkValue);
47+
$pkOrExpr[] = $query->expr()->eq($pkName, ':' . $pkName . $i);
48+
$query->setParameter($pkName . $i, $preparedPkValue);
49+
}
50+
}
51+
if ($pkOrExpr) {
52+
$expressions[] = $query->expr()->and(...$pkOrExpr);
53+
}
54+
}
55+
$query->where($query->expr()->or(...$expressions));
56+
}
57+
$this->queryBuilder = $query;
58+
}
59+
60+
public function getQueryBuilder(): QueryBuilder
61+
{
62+
return $this->queryBuilder;
63+
}
64+
}

tests/Table/AbstractTableTest.php

+44
Original file line numberDiff line numberDiff line change
@@ -101,4 +101,48 @@ public function test_illegalCreateEntity(): void
101101
$empty = $table->buildEntities(['abc']);
102102
$this->assertEmpty($empty);
103103
}
104+
105+
/**
106+
* @dataProvider buildWhere_dataProvider
107+
*/
108+
public function test_buildWhere($where, $expectedSQL, $expectedParams)
109+
{
110+
$table = new Tables\TestStrictTable();
111+
112+
$selectReflection = new \ReflectionMethod($table, 'select');
113+
$selectReflection->setAccessible(true);
114+
115+
$queryBuilder = $selectReflection->invoke($table);
116+
117+
$buildWhereReflection = new \ReflectionMethod($table, 'buildWhere');
118+
$buildWhereReflection->setAccessible(true);
119+
120+
$buildWhereReflection->invokeArgs($table, [$queryBuilder, $where]);
121+
122+
$this->assertEquals($expectedSQL, $queryBuilder->getSQL());
123+
}
124+
125+
public static function buildWhere_dataProvider(): array
126+
{
127+
return [
128+
// Test when value is null
129+
[
130+
['column1' => null],
131+
'SELECT * FROM Strict WHERE column1 IS NULL',
132+
[]
133+
],
134+
// Test when value is an array
135+
[
136+
['column1' => [1, 2, 3]],
137+
'SELECT * FROM Strict WHERE column1 IN (1, 2, 3)',
138+
[1, 2, 3]
139+
],
140+
// Test when value is a single value
141+
[
142+
['column1' => 'value1'],
143+
'SELECT * FROM Strict WHERE column1 = :column1',
144+
['value1']
145+
],
146+
];
147+
}
104148
}

0 commit comments

Comments
 (0)