diff --git a/include/class.orm.php b/include/class.orm.php index c71f0e1e60f4e8e5e0aac99a8bfca98d89fcba8b..037966a45dc97ee717e93245a16972b867d866f5 100644 --- a/include/class.orm.php +++ b/include/class.orm.php @@ -229,6 +229,17 @@ class ModelMeta implements ArrayAccess { return $this->fields; } + function getByPath($path) { + if (is_string($path)) + $path = explode('__', $path); + $root = $this; + foreach ($path as $P) { + list($root, ) = $root['joins'][$P]['fkey']; + $root = $root::getMeta(); + } + return $root; + } + /** * Create a new instance of the model, optionally hydrating it with the * given hash table. The constructor is not called, which leaves the @@ -2246,9 +2257,22 @@ class SqlCompiler { // Handle relationship comparisons with model objects elseif ($value instanceof VerySimpleModel) { $criteria = array(); - foreach ($value->pk as $f=>$v) { - $f = $field . '__' . $f; - $criteria[$f] = $v; + // Avoid a join if possible. Use the local side of the + // relationship + if (count($value->pk) === 1) { + $path = explode('__', $field); + $relationship = array_pop($path); + $lmodel = $model::getMeta()->getByPath($path); + $local = $lmodel['joins'][$relationship]['local']; + $path = $path ? (implode('__', $path) . '__') : ''; + foreach ($value->pk as $v) { + $criteria["{$path}{$local}"] = $v; + } + } + else { + foreach ($value->pk as $f=>$v) { + $criteria["{$field}__{$f}"] = $v; + } } $filter[] = $this->compileQ(new Q($criteria), $model, $slot); }