From 0f9cab068c3e527e43a801de65ad023e004e7718 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