Ticket #1726 (closed defect: fixed)

Opened 7 months ago

Last modified 7 months ago

Limit subquery added to mysql/pgsql queries gets cached incorrectly

Reported by: chorizo Owned by: jwage
Priority: major Milestone: 1.0.6
Component: Attributes Version: 1.0.4
Severity: Keywords:
Cc: Has Test: no
Status: Pending Core Response Has Patch: yes

Description

There is a workaround to limit subqueries in mysql/pgsql that creates an IN clause with a number of IDs that are fetched from the DB in a separate query. This query then gets incorrectly cached as SQL in the query cache.

I've attached a patch that disables the query cache for queries that need this workaround. It has 2 parts. The first flags the query as not using the query cache when in the workaround modes. The second adds an additional check for caching inside the existing cache check. This is because the flag will be flipped in getSqlQuery, which happens inside the existing cache check.

Note, I've only tested this for MySQL, not Postgres, but it looked similar, so I included the cache line there too. Someone with more postgres experience should have a look.

Index: lib/Doctrine/Query.php
===================================================================
--- lib/Doctrine/Query.php      (revision 9134)
+++ lib/Doctrine/Query.php      (working copy)
@@ -1122,11 +1122,13 @@
                 $idColumnName = $table->getColumnName($table->getIdentifier());
                 switch (strtolower($this->_conn->getDriverName())) {
                     case 'mysql':
+                       $this->useQueryCache(false);
                         // mysql doesn't support LIMIT in subqueries
                         $list = $this->_conn->execute($subquery, $params)->fetchAll(Doctrine::FETCH_COLUMN);
                         $subquery = implode(', ', array_map(array($this->_conn, 'quote'), $list));
                         break;
                     case 'pgsql':
+                       $this->useQueryCache(false);
                         // pgsql needs special nested LIMIT subquery
                         $subquery = 'SELECT '
                                 . $this->_conn->quoteIdentifier('doctrine_subquery_alias.' . $idColumnName)
Index: lib/Doctrine/Query/Abstract.php
===================================================================
--- lib/Doctrine/Query/Abstract.php     (revision 9134)
+++ lib/Doctrine/Query/Abstract.php     (working copy)
@@ -921,8 +921,10 @@
                     $query = $this->_constructQueryFromCache($cached);
                 } else {
                     $query = $this->getSqlQuery($params);
-                    $serializedQuery = $this->getCachedForm($query);
-                    $queryCacheDriver->save($hash, $serializedQuery, $this->getQueryCacheLifeSpan());
+                   if ($this->_queryCache !== false && ($this->_queryCache || $this->_conn->getAttribute(Doctrine::ATTR_QUERY_CACHE))) {
+                     $serializedQuery = $this->getCachedForm($query);
+                     $queryCacheDriver->save($hash, $serializedQuery, $this->getQueryCacheLifeSpan());
+                   }
                 }
             } else {
                 $query = $this->getSqlQuery($params);

Change History

Changed 7 months ago by jwage

  • milestone set to 1.0.5

Changed 7 months ago by chorizo

This never made it into 1.0.5, but adding ->limit(1) to fetchOne queries did, which I think might expose this bug to additional people.

Changed 7 months ago by jwage

The limit(1) on fetchOne() was reversed in 1.0 until we fix the cache issue.

Changed 7 months ago by jwage

  • status changed from new to closed
  • resolution set to fixed

(In [5303]) [1.0, 1.1] Fixed issue with limit subquery algorithm queries beind cached when they should not be (closes #1726)

Changed 7 months ago by jwage

  • milestone changed from 1.0.5 to 1.0.6
Note: See TracTickets for help on using tickets.