-
Notifications
You must be signed in to change notification settings - Fork 2.5k
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
DDC-3174: Query Cache not correct working when using SQLFilter #3955
Comments
Comment created by @Ocramius: I'm not sure if this case should be contemplated by the ORM. Filters are low-level and supposed to be stateless (services). |
Comment created by benno: OK, we can disable the query cache for this case. But then should at least the documentation be updated, which explicitly mentions to use filter for locales, which are also not stateless: http://doctrine-orm.readthedocs.org/en/latest/reference/filters.html#example-filter-class Also in the query cache chapter: http://doctrine-orm.readthedocs.org/en/latest/reference/caching.html#query-cache |
Comment created by @Ocramius: [~benno] can you eventually provide a pull request? |
Comment created by jamesblizzardbrowserlondon: I would just like to say that we're having exactly the same issue. I'd love some method (official or not) of having filters being taken into account in this situation. |
Comment created by telegu: I have the same problem when is generated QueryCacheId It consider only the name of active filters and not the value of the filter
|
Comment created by odiaseo: I also have the same issue, there are circumstances where filters are dynamic and not stateless particularly when dealing with multi-site / multi-lingual platforms. Is there an appetite for the ORM to take this into consideration. |
Comment created by bramstroker: I have the same issue. We are using SQL filters a lot to filter entities by website and locale. It would be nice if the filter values can be taken into account as well. For now I disabled the query cache in the concerning repositories. |
Comment created by csolis: Same issue here, we are using filters for soft deletion and it would be nice if we can use query cache. |
Comment created by tom.pryor: We are currently working around this by naming the filter based on the value we apply in the filter. So in the agency_id example if we were filtering on an agency_id of 5 we'd name the filter something like 'agency_filter_5'. Would be good if Doctrine took into account the parameter values of the filters when generating the cache id though. |
Hello, Old issue, I know, but I have the same issue. For now i just disabled the query cache. |
Unless I misunderstood the issue, I believe this has been fixed. Doctrine takes into account the parameters that are passed to the filter when the query cache is enabled. However, you have to pass those parameters via the filter's # Enable the Doctrine SQL filter for entity locales
$filter = $this->em->getFilters()->enable('localeFilter');
$filter->setParameter('locale', $request->getLocale()); Then, in your filter constraint, you can get the value with the public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias)
{
$locale = $this->getParameter('locale');
return sprintf('%1$s.locale = %2$s OR %1$s.locale = "" OR %1$s.locale IS NULL', $targetTableAlias, $locale);
} |
@beberlei is query cache really usable with doctrine filters as of now (think also about softdeletable filter with no parameter) ? |
@DamienHarper Does the example of @EmilePerron not work? |
@SenseException No it still doesn't work for me. |
The fix here is to introduce a new final method Tricky bit is probably, how to handle case where parameter is an object, because serializing that would be expensive, and since its part of the query cache, must be stable across multiple requests. |
Geez, this was a fun bug to run into. Luckily it hasn't been too dangerous, but could have been much worse, executing queries on wrong records. Why is We're just going to have to leave query cache disabled until this issue is resolved. Any other insights into this would be appreciated. |
I ran into the same issue, looks like disabling cache is the current way to fix this. My problem was while adding a filter to add Here's how to reproduce the problem on a Symfony 5.1 with ApiPlatform v2.4 <?php
namespace App\Doctrine\Filter;
use App\Doctrine\Annotation\CompanyAware;
use App\Entity\User;
use Doctrine\Common\Annotations\Reader;
use Doctrine\ORM\Mapping\ClassMetadata;
use Doctrine\ORM\Query\Filter\SQLFilter;
use Symfony\Component\Security\Core\Security;
class CompanyFilter extends SQLFilter
{
private ?Reader $reader = null;
private ?Security $security = null;
public function addFilterConstraint(ClassMetadata $targetEntity, $targetTableAlias): string
{
$companyAware = $this->reader->getClassAnnotation($targetEntity->getReflectionClass(), CompanyAware::class);
if (!$companyAware) {
return '';
}
/** @var User $user */
$user = $this->security->getUser();
return sprintf('%s.company_id = %s', $targetTableAlias, $user->getCompany()->getId());
}
public function setSecurity(Security $security): void
{
$this->security = $security;
}
public function setAnnotationReader(Reader $reader): void
{
$this->reader = $reader;
}
} class CompanyFilterConfigurator
{
private EntityManagerInterface $em;
private Reader $reader;
private Security $security;
public function __construct(EntityManagerInterface $em, Security $security, Reader $reader)
{
$this->em = $em;
$this->reader = $reader;
$this->security = $security;
}
public function onKernelRequest(): void
{
/** @var CompanyFilter $filter */
$filter = $this->em->getFilters()->enable('company_filter');
$filter->setAnnotationReader($this->reader);
$filter->setSecurity($this->security);
}
} doctrine configuration : doctrine:
orm:
auto_generate_proxy_classes: false
metadata_cache_driver:
type: service
id: doctrine.system_cache_provider
query_cache_driver:
type: service
id: doctrine.system_cache_provider
result_cache_driver:
type: service
id: doctrine.result_cache_provider
services:
doctrine.result_cache_provider:
class: Symfony\Component\Cache\DoctrineProvider
public: false
arguments:
- '@doctrine.result_cache_pool'
doctrine.system_cache_provider:
class: Symfony\Component\Cache\DoctrineProvider
public: false
arguments:
- '@doctrine.system_cache_pool'
framework:
cache:
pools:
doctrine.result_cache_pool:
adapter: cache.app
doctrine.system_cache_pool:
adapter: cache.system
|
@oojacoboo @FabienPapet see my last comment please, it explains what the problem is and it details how this can be fixed. It should be relatively simple if you want to give it a try. |
… queries. Issue: doctrine#3955 (cherry picked from commit 398ea44)
… queries. Issue: doctrine#3955 (cherry picked from commit 398ea44)
… queries. Issue: doctrine#3955 (cherry picked from commit 398ea44)
… queries. Issue: doctrine#3955 (cherry picked from commit 398ea44)
… queries. Issue: doctrine#3955 (cherry picked from commit 398ea44)
… queries. Issue: doctrine#3955 (cherry picked from commit 398ea44)
Hello, |
Remarks @beberlei regarding the suggestion in #3955 (comment): 1. RemarkHere is how the query cache ID is calculated for orm/lib/Doctrine/ORM/Query.php Lines 792 to 803 in 152c04c
In that part, parameters (from The parameters used for filters are from a different set, namely That is – for every different parameter value combination set for filters, different query cache entries will be used. When the filter is something like a soft delete with only two possible parameter values (on/off), that might not be a big deal. When it does something like filtering by Probably there is no easy way to fix this, since the filter returns "raw" SQL and has no way of adding parameters for the final query execution. Would require more investigation to find out how/if parameters could be returned from the filter and passed on into the Executor.
2. Remark
So, maybe the suggested |
@MalteWunsch just pointed out to me that orm/lib/Doctrine/ORM/Query/FilterCollection.php Lines 193 to 195 in 152c04c
Since orm/lib/Doctrine/ORM/Query/Filter/SQLFilter.php Lines 178 to 181 in 152c04c
... the solution described by @beberlei should effectively be in place for a long time already? |
With an activate query cache, queries will be cached at a key generated in https://github.com/doctrine/orm/blob/152c04c03d68d39f485d367713dd69dec0f4106d/lib/Doctrine/ORM/Query.php#L792-L803 . If a SQLFilter does not produce static SQL but dynamic SQL, you need to call SQLFilter->setParameter for the dynamic parts, in order for them to be considered for the cache key: https://github.com/doctrine/orm/blob/152c04c03d68d39f485d367713dd69dec0f4106d/lib/Doctrine/ORM/Query/Filter/SQLFilter.php#L178-L181 . I.e. without setParameter() calls, the first generated query was cached and whatever visibility value the FilterStrategy had determined was reused for future requests. @see doctrine/orm#3955
… queries. Issue: doctrine#3955 (cherry picked from commit 398ea44)
Jira issue originally created by user benno:
We have an SQLFilter to filter on entities with a specific Trait implemented. The filter is very easy:
bq. $res = $targetTableAlias . '.agency_id = ' . $this->getCurrentAgencyId();
On our system we have the query cache enabled, this works as long the "AgencyId" doesn't change. When the ID changes, the query cache seems to return the wrong (old cache) query.
The text was updated successfully, but these errors were encountered: