Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
26 changes: 17 additions & 9 deletions lib/Doctrine/DBAL/Cache/ResultCacheStatement.php
Original file line number Diff line number Diff line change
Expand Up @@ -52,24 +52,29 @@ class ResultCacheStatement implements IteratorAggregate, ResultStatement, Result
/** @var ResultStatement */
private $statement;

/** @var array<string,mixed>|null */
private $fetchedData;

/** @var array<int,array<string,mixed>>|null */
private $data;

/** @var int */
private $defaultFetchMode = FetchMode::MIXED;

/**
* @param string $cacheKey
* @param string $realKey
* @param int $lifetime
* @param string $cacheKey
* @param string $realKey
* @param int $lifetime
* @param array<string,mixed>|null $fetchedData
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this new argument become mandatory in 3.0.x?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think, yes.
However, the class is renamed to CachingResult in 3.0

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why don't we implement a proper fix in 3.0.x first and then backport in a BC-way? Otherwise, it's not clear what the new intended logic is.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't know how you releasing process is working. I consider this bug as a minor so it doesn't make sense to break backward compatibility.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's at least make it clear in the parameter description that this parameter will be mandatory in 3.0. Otherwise, it's not clear why fetching the data has to be implemented twice.

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I feel confused about how to do it all in 2.11.

I have opened the new #4189 for 3.0.x version with BC Break and mandatory $fetchedData field.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not that well familiar with the design of the caching layer and I still don't get the design: instead of fetching the data from the result, why does the result now use the fetched data and still can fetch from the result via fetch*() methods? Is this still necessary?

Copy link
Author

@k0ka k0ka Jul 24, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The result cache is fetched in ResultCacheStatement only if no fetchedData is provided to the constructor. It is done for backward compatibility - someone could use ResultCacheStatement before and it should continue working without the last parameter.

DBAL uses this class only in one place and it always sends fetchedData. So, result cache won't be fetched 2 times if DBAL is used ordinarily.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The result cache is fetched in ResultCacheStatement only if no fetchedData is provided to the constructor.

Let's then continue the discussion in #4189 where BC is of no concern. The new class still depends on the Result.

*/
public function __construct(ResultStatement $stmt, Cache $resultCache, $cacheKey, $realKey, $lifetime)
public function __construct(ResultStatement $stmt, Cache $resultCache, $cacheKey, $realKey, $lifetime, ?array $fetchedData = null)
{
$this->statement = $stmt;
$this->resultCache = $resultCache;
$this->cacheKey = $cacheKey;
$this->realKey = $realKey;
$this->lifetime = $lifetime;
$this->fetchedData = $fetchedData;
}

/**
Expand Down Expand Up @@ -336,13 +341,16 @@ private function saveToCache(): void
return;
}

$data = $this->resultCache->fetch($this->cacheKey);
if (! $data) {
$data = [];
if ($this->fetchedData === null) {
$this->fetchedData = $this->resultCache->fetch($this->cacheKey);
}

if (! $this->fetchedData) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please avoid implicit conversion to boolean. It's not allowed in newer branches.

Copy link
Author

@k0ka k0ka Jul 23, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok. This line was written before me - I've just change the variable name.

$this->fetchedData = [];
}

$data[$this->realKey] = $this->data;
$this->fetchedData[$this->realKey] = $this->data;

$this->resultCache->save($this->cacheKey, $data, $this->lifetime);
$this->resultCache->save($this->cacheKey, $this->fetchedData, $this->lifetime);
}
}
11 changes: 10 additions & 1 deletion lib/Doctrine/DBAL/Connection.php
Original file line number Diff line number Diff line change
Expand Up @@ -1207,10 +1207,19 @@ public function executeCacheQuery($sql, $params, $types, QueryCacheProfile $qcp)
} elseif (array_key_exists($realKey, $data)) {
$stmt = new ArrayStatement([]);
}
} else {
$data = [];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this needed?

Copy link
Author

@k0ka k0ka Jul 23, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is needed to distinguish "data from query cache is not loaded" and "data from query cache is loaded and empty".
This data was be set to empty array in ResultCacheStatement before -

}

if (! isset($stmt)) {
$stmt = new ResultCacheStatement($this->executeQuery($sql, $params, $types), $resultCache, $cacheKey, $realKey, $qcp->getLifetime());
$stmt = new ResultCacheStatement(
$this->executeQuery($sql, $params, $types),
$resultCache,
$cacheKey,
$realKey,
$qcp->getLifetime(),
$data
);
}

$stmt->setFetchMode($this->defaultFetchMode);
Expand Down