Skip to content

Commit 334c3e3

Browse files
committed
fix(cache): Fixed issue with cache middleware and serialization of the query result.
1 parent a008397 commit 334c3e3

File tree

5 files changed

+66
-256
lines changed

5 files changed

+66
-256
lines changed

src/RunOpenCode/Bundle/QueryResourcesLoader/Cache/CacheMiddleware.php

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,8 @@ public function __invoke(string $query, Parameters $parameters, Options $options
7070
* @var CacheIdentityInterface $identity
7171
*/
7272
$item->expiresAfter($identity->getTtl());
73-
74-
if (method_exists($item, 'tag')) {
73+
74+
if (\method_exists($item, 'tag')) {
7575
$item->tag(\array_merge(
7676
$identity->getTags(),
7777
[self::TAG]

src/RunOpenCode/Bundle/QueryResourcesLoader/Executor/Dbal/ArrayResult.php

Lines changed: 29 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,9 @@
55
namespace RunOpenCode\Bundle\QueryResourcesLoader\Executor\Dbal;
66

77
use Doctrine\DBAL\Driver\FetchUtils;
8-
use Doctrine\DBAL\Driver\Result;
8+
use Doctrine\DBAL\Driver\Result as DbalDriverResult;
99
use Doctrine\DBAL\Exception\InvalidColumnIndex;
10+
use Doctrine\DBAL\Result as DbalResult;
1011

1112
/**
1213
* @psalm-suppress InternalClass, InternalMethod
@@ -15,7 +16,7 @@
1516
*
1617
* @internal
1718
*/
18-
final class ArrayResult implements Result
19+
final class ArrayResult implements DbalDriverResult
1920
{
2021
private int $num = 0;
2122

@@ -26,10 +27,33 @@ final class ArrayResult implements Result
2627
*/
2728
public function __construct(
2829
private readonly array $columnNames,
29-
private array $rows,
30+
private array $rows,
3031
) {
3132
}
3233

34+
public static function create(DbalDriverResult|DbalResult $result): self
35+
{
36+
// A new implementation of Dbal, let's leverage it.
37+
if (\method_exists($result, 'getColumnName')) {
38+
$rows = $result->fetchAllNumeric();
39+
$columnNames = \array_map(fn(int $index): string => $result->getColumnName($index), \range(0, $result->columnCount() - 1));
40+
41+
return new self($columnNames, $rows);
42+
}
43+
44+
// A legacy implementation of Dbal, let's use the old way.
45+
$data = $result->fetchAllAssociative();
46+
47+
if (0 === \count($data)) {
48+
return new self([], []);
49+
}
50+
51+
$columnNames = \array_keys($data[0]);
52+
$rows = \array_map(fn(array $row): array => \array_values($row), $data);
53+
54+
return new self($columnNames, $rows);
55+
}
56+
3357
public function fetchNumeric(): array|false
3458
{
3559
return $this->fetch();
@@ -107,28 +131,16 @@ public function __serialize(): array
107131
return [$this->columnNames, $this->rows];
108132
}
109133

110-
/** @param mixed[] $data */
134+
/** @param array{list<string>, list<list<mixed>>} $data */
111135
public function __unserialize(array $data): void
112136
{
113-
// Handle objects serialized with DBAL 4.1 and earlier.
114-
if (isset($data["\0" . self::class . "\0data"])) {
115-
/** @var list<array<string, mixed>> $legacyData */
116-
$legacyData = $data["\0" . self::class . "\0data"];
117-
118-
$this->columnNames = \array_keys($legacyData[0] ?? []);
119-
$this->rows = \array_map(array_values(...), $legacyData);
120-
121-
return;
122-
}
123-
124-
// @phpstan-ignore-next-line
125137
[$this->columnNames, $this->rows] = $data;
126138
}
127139

128140
/** @return list<mixed>|false */
129141
private function fetch(): array|false
130142
{
131-
if (! isset($this->rows[$this->num])) {
143+
if (!isset($this->rows[$this->num])) {
132144
return false;
133145
}
134146

src/RunOpenCode/Bundle/QueryResourcesLoader/Executor/Dbal/DoctrineDbalExecutionResult.php

Lines changed: 30 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@
44

55
namespace RunOpenCode\Bundle\QueryResourcesLoader\Executor\Dbal;
66

7-
use Doctrine\DBAL\Driver\Result;
8-
use Doctrine\DBAL\Result as ExecutionResult;
7+
use Doctrine\DBAL\Driver\Result as DbalDriverResult;
8+
use Doctrine\DBAL\Result as DbalResult;
99
use RunOpenCode\Bundle\QueryResourcesLoader\Contract\ExecutionResultInterface;
1010
use RunOpenCode\Bundle\QueryResourcesLoader\Exception\NonUniqueResultException;
1111
use RunOpenCode\Bundle\QueryResourcesLoader\Exception\NoResultException;
@@ -20,13 +20,12 @@
2020
*
2121
* @psalm-suppress InternalMethod, InternalClass
2222
*/
23-
final readonly class DoctrineDbalExecutionResult implements \IteratorAggregate, ExecutionResultInterface, Result
23+
final class DoctrineDbalExecutionResult implements \IteratorAggregate, ExecutionResultInterface, DbalDriverResult
2424
{
25-
private ResultProxy $result;
26-
27-
public function __construct(ExecutionResult|ArrayResult $result)
28-
{
29-
$this->result = new ResultProxy($result);
25+
public function __construct(
26+
private DbalDriverResult|DbalResult $result
27+
) {
28+
// noop.
3029
}
3130

3231
/**
@@ -208,7 +207,7 @@ public function free(): void
208207
*/
209208
public function rowCount(): int
210209
{
211-
return $this->result->rowCount();
210+
return (int)$this->result->rowCount();
212211
}
213212

214213
/**
@@ -226,6 +225,27 @@ public function getIterator(): \Traversable
226225
*/
227226
public function count(): int
228227
{
229-
return $this->result->count();
228+
if (0 === $this->columnCount()) {
229+
return $this->rowCount();
230+
}
231+
232+
$count = $this->rowCount();
233+
234+
if ($count > 0) {
235+
return $count;
236+
}
237+
238+
$this->__sleep();
239+
240+
return $this->rowCount();
241+
}
242+
243+
public function __sleep(): array
244+
{
245+
if (!$this->result instanceof ArrayResult) {
246+
$this->result = ArrayResult::create($this->result);
247+
}
248+
249+
return ['result'];
230250
}
231251
}

src/RunOpenCode/Bundle/QueryResourcesLoader/Executor/Dbal/ResultProxy.php

Lines changed: 0 additions & 226 deletions
This file was deleted.

0 commit comments

Comments
 (0)