Skip to content

Commit

Permalink
queryset: Fix circular reference error
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
greezybacon authored and protich committed May 15, 2018
1 parent f62e966 commit e657a33
Showing 1 changed file with 11 additions and 8 deletions.
19 changes: 11 additions & 8 deletions include/class.orm.php
Original file line number Diff line number Diff line change
Expand Up @@ -1606,15 +1606,22 @@ function findAll($criteria, $limit=false) {

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) {
Expand Down Expand Up @@ -1669,7 +1676,7 @@ function getOrBuild($modelClass, $fields, $cache=true) {
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
Expand All @@ -1688,7 +1695,7 @@ function getOrBuild($modelClass, $fields, $cache=true) {
// 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);
Expand Down Expand Up @@ -1758,10 +1765,6 @@ function buildModel($row, $cache=true) {
}

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);

Expand Down

0 comments on commit e657a33

Please sign in to comment.