Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Changing the position of the emptied variable #3997

Closed
wants to merge 14 commits into from

Conversation

dfrnks
Copy link

@dfrnks dfrnks commented May 6, 2020

When use fetch or fetchColumn and don't pass for all registers if while they don't close the cursor and don't save in the cache

Q A
Type bug
BC Break no
Fixed issues

Summary

@greg0ire
Copy link
Member

greg0ire commented May 8, 2020

When use fetch or fetchColumn and don't pass for all registers if while they don't close the cursor and don't save in the cache

I do not understand. Can you please elaborate?

@dfrnks
Copy link
Author

dfrnks commented May 8, 2020

When use fetch or fetchColumn and don't pass for all registers if while they don't close the cursor and don't save in the cache

I do not understand. Can you please elaborate?

When this query is made

    $qb = $db
        ->createQueryBuilder()
        ->select('*')
        ->from("base_config");

    $stmt   = $db->executeCacheQuery($qb, [], [], new QueryCacheProfile(3600));
    $config = $stmt->fetch();
    $stmt->closeCursor();

It is not saved in the cache, because it has not been passed in all registers and the variable $emptied in lib/Doctrine/DBAL/Cache/ResultCacheStatement.php is never true when we call closeCursor.

It will only be true if you pass all registers with while for example and then will save in the cache when we call closeCursor.

But is not the case of this query, this query only need the first register. And otherwise it will not influence if someone needs to pass all the registers, it will save in the cache too.

Co-authored-by: Claudio Zizza <859964+SenseException@users.noreply.github.com>
@greg0ire
Copy link
Member

greg0ire commented May 8, 2020

Pardon my ignorance but… what is a register? What are you referring to?

@dfrnks
Copy link
Author

dfrnks commented May 8, 2020

Pardon my ignorance but… what is a register? What are you referring to?

Sorry, I mean, without this pull request you need to do like this for save the cache using the fetch method

    while ($row = $stmt->fetch()) {
        $data[] = $row;
    }
   $stmt->closeCursor();

You need get all rows.

If you get just the first $row, they don't save the cache.

    $row = $stmt->fetch();
    $stmt->closeCursor();

And I think don't matter if you get one row or all rows to save the cache, it necessary save in the cache always.

@dfrnks dfrnks requested a review from SenseException May 8, 2020 19:32
Copy link
Member

@SenseException SenseException left a comment

Choose a reason for hiding this comment

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

👍

@greg0ire I haven't checked all tests in the repository, but is it possible that we don't have a test that checks the cache behaviour with parameters?

@@ -165,7 +165,7 @@ public function testDontFinishNoCache() : void

$this->hydrateStmt($stmt, FetchMode::NUMERIC);

self::assertCount(2, $this->sqlLogger->queries);
self::assertCount(1, $this->sqlLogger->queries);
Copy link
Member

Choose a reason for hiding this comment

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

Wait, isn't this test supposed to have 2 queries executed?

Copy link
Author

Choose a reason for hiding this comment

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

Not really, a second query he took from the cache

Copy link
Member

Choose a reason for hiding this comment

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

It previously expected 2 queries in the test and I want to know what's the reason for this test. I'll need help from @beberlei, who implemented this test in #69 a long time ago.

Copy link
Author

Choose a reason for hiding this comment

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

The test was incorrect because, just will save the query in $this->sqlLogger->queries when the query are execute in the database.

$logger = $this->_config->getSQLLogger();
if ($logger) {
$logger->startQuery($query, $params, $types);
}

When the query are in the cache, they return before

public function executeQuery($query, array $params = [], $types = [], ?QueryCacheProfile $qcp = null)
{
if ($qcp !== null) {
return $this->executeCacheQuery($query, $params, $types, $qcp);
}
$connection = $this->getWrappedConnection();
$logger = $this->_config->getSQLLogger();
if ($logger) {
$logger->startQuery($query, $params, $types);
}

The reason are the cache doesn't work before, when we use fetch

Copy link
Member

Choose a reason for hiding this comment

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

I agree, which is why I approved if at first, but if there's another reason why @beberlei expected 2 in the past, I want to know and would like to be on the save side.

Copy link
Member

Choose a reason for hiding this comment

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

This was recently changed in #4048. It's an improvement, not a bugfix, so this change shouldn't be made in 2.10.x..

@greg0ire
Copy link
Member

@SenseException what do you mean by "with parameters"?

@SenseException
Copy link
Member

@greg0ire Every Connection::executeQuery() with a QueryCacheProfile has an empty array for $params. Depending on an omitted key in QueryCacheProfile the $params are also used for the cache key creation and I wonder if this caching is covered by an integration test. This has nothing to do with this PR, but maybe needs to be covered by another PR. Or I haven't found an existing test covering this case yet.

Copy link
Member

@morozov morozov left a comment

Choose a reason for hiding this comment

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

This is likely resolved by #4048.

@@ -931,9 +931,10 @@ public function executeQuery($query, array $params = [], $types = [], ?QueryCach
* @param int[]|string[] $types The types the previous parameters are in.
* @param QueryCacheProfile $qcp The query cache profile.
*
* @return ResultStatement
* @return ResultCacheStatement|ArrayStatement
Copy link
Member

Choose a reason for hiding this comment

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

Please revert. The type hint should refer to an interface, not to a specific implementation.


$iterator = $stmt->getIterator();

self::assertCount(1, $iterator);
Copy link
Member

Choose a reason for hiding this comment

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

This is not a valid behavior to expect. The fact that the iterator internally calls fetchAll() is a bug (see #2718) and shouldn't be relied upon to expect that the statement is cached just because an iterator over its results was instantiated.

@dfrnks
Copy link
Author

dfrnks commented Jun 8, 2020

With I understanding, my pull request isn't necessary anymore because they are resolved the other way in #4048 right? @morozov

@morozov
Copy link
Member

morozov commented Jun 8, 2020

@dfrnks I believe so. You can check your case using the 2.11.x branch.

@morozov morozov changed the base branch from 2.10.x to 2.12.x November 29, 2020 21:34
@morozov morozov closed this Apr 21, 2021
@morozov morozov deleted the branch doctrine:2.12.x April 21, 2021 16:25
@github-actions github-actions bot locked as resolved and limited conversation to collaborators Jul 22, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants