From e657a33e5d7a96442feabc936c6b9d0c60c1270b Mon Sep 17 00:00:00 2001 From: Jared Hancock <gravydish@gmail.com> Date: Wed, 18 Apr 2018 20:12:37 -0500 Subject: [PATCH] queryset: Fix circular reference error This fixes an error where the ModelInstanceManager maintained a reference to the QuerySet instance, and the QuerySet instance managed a reference to the ModelInstanceManager instance (if it's the iterator for the query). Because of the circular reference, if the iterator is not exhausted, then the resource is not closed and the query remains open. This wastes memory and prevents some other queries from running after such a situation happens. This addresses the issue by removing the circular reference between the QuerySet and the ModelInstanceManager. --- include/class.orm.php | 19 +++++++++++-------- 1 file changed, 11 insertions(+), 8 deletions(-) diff --git a/include/class.orm.php b/include/class.orm.php index 7539c1445..74ecc322a 100644 --- a/include/class.orm.php +++ b/include/class.orm.php @@ -1606,15 +1606,22 @@ extends CachedResultSet { class ModelInstanceManager implements IteratorAggregate { - var $queryset; var $model; var $map; + var $resource; + var $annnotations; + var $defer; static $objectCache = array(); function __construct(QuerySet $queryset) { - $this->queryset = $queryset; $this->model = $queryset->model; + $this->resource = $queryset->getQuery(); + $cache = !$queryset->hasOption(QuerySet::OPT_NOCACHE); + $this->resource->setBuffered($cache); + $this->map = $this->resource->getMap(); + $this->annotations = $queryset->annotations; + $this->defer = $queryset->defer; } function cache($model) { @@ -1669,7 +1676,7 @@ implements IteratorAggregate { return null; } } - $annotations = $this->queryset->annotations; + $annotations = $this->annotations; $extras = array(); // For annotations, drop them from the $fields list and add them to // an $extras list. The fields passed to the root model should only @@ -1688,7 +1695,7 @@ implements IteratorAggregate { // Construct and cache the object $m = $modelClass::$meta->newInstance($fields); // XXX: defer may refer to fields not in this model - $m->__deferred__ = $this->queryset->defer; + $m->__deferred__ = $this->defer; $m->__onload(); if ($cache) $this->cache($m); @@ -1758,10 +1765,6 @@ implements IteratorAggregate { } function getIterator() { - $this->resource = $this->queryset->getQuery(); - $this->map = $this->resource->getMap(); - $cache = !$this->queryset->hasOption(QuerySet::OPT_NOCACHE); - $this->resource->setBuffered($cache); $func = ($this->map) ? 'getRow' : 'getArray'; $func = array($this->resource, $func); -- GitLab