diff --git a/include/class.category.php b/include/class.category.php
index a73556e16b0c707b2422cf35715c2d92e75090da..8e6be6b00e8b225b06e0d7ef9dc4b0bc2b5ab114 100644
--- a/include/class.category.php
+++ b/include/class.category.php
@@ -21,7 +21,7 @@ class Category extends VerySimpleModel {
         'ordering' => array('name'),
         'joins' => array(
             'faqs' => array(
-                'reverse' => 'FAQ.category_id'
+                'reverse' => 'FAQ.category'
             ),
         ),
     );
diff --git a/include/class.orm.php b/include/class.orm.php
index c3ff388dd6dd5461e390e7c27aa35e1f57c3a7e6..765bc7ff7cf7e701b379d26375a39c6f99fa6a03 100644
--- a/include/class.orm.php
+++ b/include/class.orm.php
@@ -28,12 +28,17 @@ class OrmConfigurationException extends Exception {}
  */
 class ModelMeta implements ArrayAccess {
 
-    var $base = array();
+    static $base = array(
+        'pk' => false,
+        'table' => false,
+        'defer' => array(),
+        'select_related' => array(),
+    );
     var $model;
 
     function __construct($model) {
         $this->model = $model;
-        $meta = $model::$meta;
+        $meta = $model::$meta + self::$base;
 
         // TODO: Merge ModelMeta from parent model (if inherited)
 
@@ -45,7 +50,7 @@ class ModelMeta implements ArrayAccess {
                 __('Model does not define meta.pk'), $model);
 
         // Ensure other supported fields are set and are arrays
-        foreach (array('pk', 'ordering', 'deferred') as $f) {
+        foreach (array('pk', 'ordering', 'defer') as $f) {
             if (!isset($meta[$f]))
                 $meta[$f] = array();
             elseif (!is_array($meta[$f]))
@@ -57,8 +62,8 @@ class ModelMeta implements ArrayAccess {
             $meta['joins'] = array();
         foreach ($meta['joins'] as $field => &$j) {
             if (isset($j['reverse'])) {
-                list($model, $key) = explode('.', $j['reverse']);
-                $info = $model::$meta['joins'][$key];
+                list($fmodel, $key) = explode('.', $j['reverse']);
+                $info = $fmodel::$meta['joins'][$key];
                 $constraint = array();
                 if (!is_array($info['constraint']))
                     throw new OrmConfigurationException(sprintf(__(
@@ -67,11 +72,12 @@ class ModelMeta implements ArrayAccess {
                         $j['reverse']));
                 foreach ($info['constraint'] as $foreign => $local) {
                     list(,$field) = explode('.', $local);
-                    $constraint[$field] = "$model.$foreign";
+                    $constraint[$field] = "$fmodel.$foreign";
                 }
                 $j['constraint'] = $constraint;
                 if (!isset($j['list']))
                     $j['list'] = true;
+                $j['null'] = $info['null'] ?: false;
             }
             // XXX: Make this better (ie. composite keys)
             $keys = array_keys($j['constraint']);
@@ -79,6 +85,7 @@ class ModelMeta implements ArrayAccess {
             $j['fkey'] = explode('.', $foreign);
             $j['local'] = $keys[0];
         }
+        unset($j);
         $this->base = $meta;
     }
 
@@ -150,7 +157,7 @@ class VerySimpleModel {
             if (isset($this->ht[$j['local']])
                     && isset($j['list']) && $j['list']) {
                 $fkey = $j['fkey'];
-                $v = $this->ht[$name] = new InstrumentedList(
+                $v = $this->ht[$field] = new InstrumentedList(
                     // Send Model, Foriegn-Field, Local-Id
                     array($fkey[0], $fkey[1], $this->get($j['local']))
                 );
@@ -203,6 +210,7 @@ class VerySimpleModel {
     function set($field, $value) {
         // Update of foreign-key by assignment to model instance
         if (isset(static::$meta['joins'][$field])) {
+            static::_inspect();
             $j = static::$meta['joins'][$field];
             if ($j['list'] && ($value instanceof InstrumentedList)) {
                 // Magic list property
@@ -222,7 +230,8 @@ class VerySimpleModel {
             }
             else
                 throw new InvalidArgumentException(
-                    sprintf(__('Expecting NULL or instance of %s'), $j['fkey'][0]));
+                    sprintf(__('Expecting NULL or instance of %s. Got a %s instead'),
+                    $j['fkey'][0], get_class($value)));
 
             // Capture the foreign key id value
             $field = $j['local'];
@@ -323,6 +332,8 @@ class VerySimpleModel {
     function save($refetch=false) {
         if (count($this->dirty) === 0)
             return true;
+        elseif ($this->__deleted__)
+            throw new OrmException('Trying to update a deleted object');
 
         $ex = DbEngine::save($this);
         try {
@@ -342,6 +353,7 @@ class VerySimpleModel {
                 $this->ht[$pk[0]] = $ex->insert_id();
             $this->__new__ = false;
             Signal::send('model.created', $this);
+            $this->__onload();
         }
         else {
             $data = array('dirty' => $this->dirty);
@@ -380,14 +392,20 @@ class VerySimpleModel {
 }
 
 class SqlFunction {
+    var $alias;
+
     function SqlFunction($name) {
         $this->func = $name;
         $this->args = array_slice(func_get_args(), 1);
     }
 
-    function toSql($compiler=false) {
-        $args = (count($this->args)) ? implode(',', db_input($this->args)) : "";
-        return sprintf('%s(%s)', $this->func, $args);
+    function toSql($compiler, $model=false, $alias=false) {
+        return sprintf('%s(%s)%s', $this->func, implode(',', $this->args),
+            $alias && $this->alias ? ' AS '.$compiler->quote($this->alias) : '');
+    }
+
+    function setAlias($alias) {
+        $this->alias = $alias;
     }
 
     static function __callStatic($func, $args) {
@@ -397,6 +415,18 @@ class SqlFunction {
     }
 }
 
+class Aggregate extends SqlFunction {
+    function toSql($compiler, $model=false, $alias=false) {
+        list($field) = $compiler->getField($this->args[0], $model);
+        return sprintf('%s(%s)%s', $this->func, $field,
+            $alias && $this->alias ? ' AS '.$compiler->quote($this->alias) : '');
+    }
+
+    function getFieldName() {
+        return strtolower(sprintf('%s__%s', $this->args[0], $this->func));
+    }
+}
+
 class QuerySet implements IteratorAggregate, ArrayAccess {
     var $model;
 
@@ -407,6 +437,7 @@ class QuerySet implements IteratorAggregate, ArrayAccess {
     var $related = array();
     var $values = array();
     var $defer = array();
+    var $annotations = array();
     var $lock = false;
 
     const LOCK_EXCLUSIVE = 1;
@@ -424,20 +455,16 @@ class QuerySet implements IteratorAggregate, ArrayAccess {
 
     function filter() {
         // Multiple arrays passes means OR
-        $filter = array();
         foreach (func_get_args() as $Q) {
-            $filter[] = $Q instanceof Q ? $Q : new Q($Q);
+            $this->constraints[] = $Q instanceof Q ? $Q : new Q($Q);
         }
-        $this->constraints[] = new Q($filter, Q::ANY);
         return $this;
     }
 
     function exclude() {
-        $filter = array();
         foreach (func_get_args() as $Q) {
-            $filter[] = $Q instanceof Q ? $Q->negate() : Q::not($Q);
+            $this->constraints[] = $Q instanceof Q ? $Q->negate() : Q::not($Q);
         }
-        $this->constraints[] = new Q($filter, Q::ANY);
         return $this;
     }
 
@@ -475,12 +502,16 @@ class QuerySet implements IteratorAggregate, ArrayAccess {
     function values() {
         $this->values = func_get_args();
         $this->iterator = 'HashArrayIterator';
+        // This disables related models
+        $this->related = false;
         return $this;
     }
 
     function values_flat() {
         $this->values = func_get_args();
         $this->iterator = 'FlatArrayIterator';
+        // This disables related models
+        $this->related = false;
         return $this;
     }
 
@@ -503,7 +534,7 @@ class QuerySet implements IteratorAggregate, ArrayAccess {
                 .sprintf('In fact, there are %d matching objects.', count($list))
             );
         // TODO: Throw error if more than one result from database
-        return $this[0];
+        return $list[0];
     }
 
     function count() {
@@ -512,6 +543,20 @@ class QuerySet implements IteratorAggregate, ArrayAccess {
         return $compiler->compileCount($this);
     }
 
+    function annotate($annotations) {
+        if (!is_array($annotations))
+            $annotations = func_get_args();
+        foreach ($annotations as $name=>$A) {
+            if ($A instanceof Aggregate) {
+                if (is_int($name))
+                    $name = $A->getFieldName();
+                $A->setAlias($name);
+                $this->annotations[$name] = $A;
+            }
+        }
+        return $this;
+    }
+
     function exists() {
         return $this->count() > 0;
     }
@@ -571,6 +616,10 @@ class QuerySet implements IteratorAggregate, ArrayAccess {
         $model = $this->model;
         if (!$this->ordering && isset($model::$meta['ordering']))
             $this->ordering = $model::$meta['ordering'];
+        if (!$this->related && $model::$meta['select_related'])
+            $this->related = $model::$meta['select_related'];
+        if (!$this->defer && $model::$meta['defer'])
+            $this->defer = $model::$meta['defer'];
 
         $class = $this->compiler;
         $compiler = new $class($options);
@@ -587,7 +636,7 @@ abstract class ResultSet implements Iterator, ArrayAccess {
     var $resource;
     var $position = 0;
     var $queryset;
-    var $cache;
+    var $cache = array();
 
     function __construct($queryset=false) {
         $this->queryset = $queryset;
@@ -702,14 +751,13 @@ class ModelInstanceManager extends ResultSet {
      * object prior to using this method. The $map is assumed to have this
      * configuration:
      *
-     * array(array(<modelClass>, <fieldCount>, <relativePath>, <alias>))
+     * array(array(<fieldNames>, <modelClass>, <relativePath>))
      *
      * Where $modelClass is the name of the foreign (with respect to the
-     * root model ($this->model), $fieldCount is the number of fields in the
-     * row for this model, $relativePath is the path that describes the
-     * relationship between the root model and this model, 'user__account'
-     * for instance, and <alias> is the alias for the model in the databse
-     * query — the field names should all start with <alias>_
+     * root model ($this->model), $fieldNames is the number and names of
+     * fields in the row for this model, $relativePath is the path that
+     * describes the relationship between the root model and this model,
+     * 'user__account' for instance.
      */
     function buildModel($row) {
         // TODO: Traverse to foreign keys
@@ -719,27 +767,24 @@ class ModelInstanceManager extends ResultSet {
 
             $offset = 0;
             foreach ($this->map as $info) {
-                @list($count, $model_class, $path, $alias) = $info;
-                $fields = array_slice($row, $offset, $count);
+                @list($fields, $model_class, $path) = $info;
+                $values = array_slice($row, $offset, count($fields));
+                $record = array_combine($fields, $values);
                 if (!$path) {
                     // Build the root model
-                    $model = $this->getOrBuild($this->model, $fields);
-                    $model->__onload();
+                    $model = $this->getOrBuild($this->model, $record);
                 }
                 else {
-                    foreach ($fields as $name=>$val) {
-                        $fields[substr($name, strlen($alias)+1)] = $val;
-                        unset($fields[$name]);
-                    }
-                    // Link the related model
+                    $i = 0;
+                    // Traverse the declared path and link the related model
                     $tail = array_pop($path);
                     $m = $model;
                     foreach ($path as $field) {
                         $m = $m->get($field);
                     }
-                    $m->set($tail, $this->getOrBuild($model_class, $fields));
+                    $m->set($tail, $this->getOrBuild($model_class, $record));
                 }
-                $offset += $count;
+                $offset += count($fields);
             }
         }
         else {
@@ -749,8 +794,9 @@ class ModelInstanceManager extends ResultSet {
     }
 
     function fillTo($index) {
+        $func = ($this->map) ? 'getRow' : 'getArray';
         while ($this->resource && $index >= count($this->cache)) {
-            if ($row = $this->resource->getArray()) {
+            if ($row = $this->resource->{$func}()) {
                 $this->cache[] = $this->buildModel($row);
             } else {
                 $this->resource->close();
@@ -842,6 +888,17 @@ class InstrumentedList extends ModelInstanceManager {
         $this->cache[$a]->delete();
         $this->add($b, $a);
     }
+
+    // QuerySet overriedes
+    function filter() {
+        return call_user_func_array(array($this->objects(), 'filter'), func_get_args());
+    }
+    function order_by() {
+        return call_user_func_array(array($this->objects(), 'order_by'), func_get_args());
+    }
+    function limit($how) {
+        return $this->objects()->limit($how);
+    }
 }
 
 class SqlCompiler {
@@ -936,13 +993,14 @@ class SqlCompiler {
             // Call pushJoin for each segment in the join path. A new
             // JOIN fragment will need to be emitted and/or cached
             foreach ($parts as $p) {
-                $path[] = $p;
-                $tip = implode('__', $path);
+                $model::_inspect();
                 if (!($info = $model::$meta['joins'][$p])) {
                     throw new OrmException(sprintf(
                        'Model `%s` does not have a relation called `%s`',
                         $model, $p));
                 }
+                $path[] = $p;
+                $tip = implode('__', $path);
                 $alias = $this->pushJoin($crumb, $tip, $model, $info);
                 // Roll to foreign model
                 foreach ($info['constraint'] as $local => $foreign) {
@@ -955,6 +1013,8 @@ class SqlCompiler {
         }
         if (isset($options['table']) && $options['table'])
             $field = $alias;
+        elseif (isset($this->annotations[$field]))
+            $field = $this->annotations[$field];
         elseif ($alias)
             $field = $alias.'.'.$this->quote($field);
         else
@@ -1006,18 +1066,28 @@ class SqlCompiler {
 
     function compileQ(Q $Q, $model) {
         $filter = array();
+        $type = CompiledExpression::TYPE_WHERE;
         foreach ($Q->constraints as $field=>$value) {
             if ($value instanceof Q) {
-                $filter[] = $this->compileQ($value, $model);
+                $filter[] = $T = $this->compileQ($value, $model);
+                // Bubble up HAVING constraints
+                if ($T instanceof CompiledExpression
+                        && $T->type == CompiledExpression::TYPE_HAVING)
+                    $type = $T->type;
             }
             else {
                 list($field, $op) = $this->getField($field, $model);
+                if ($field instanceof Aggregate) {
+                    $field = $field->toSql($this, $model);
+                    // This clause has to go in the HAVING clause
+                    $type = CompiledExpression::TYPE_HAVING;
+                }
                 if ($value === null)
                     $filter[] = sprintf('%s IS NULL', $field);
                 // Allow operators to be callable rather than sprintf
                 // strings
                 elseif (is_callable($op))
-                    $filter[] = call_user_func($op, $field, $value);
+                    $filter[] = call_user_func($op, $field, $value, $model);
                 else
                     $filter[] = sprintf($op, $field, $this->input($value));
             }
@@ -1028,7 +1098,7 @@ class SqlCompiler {
             $clause = '(' . $clause . ')';
         if ($Q->isNegated())
             $clause = ' NOT '.$clause;
-        return $clause;
+        return new CompiledExpression($clause, $type);
     }
 
     function compileConstraints($where, $model) {
@@ -1036,7 +1106,7 @@ class SqlCompiler {
         foreach ($where as $Q) {
             $constraints[] = $this->compileQ($Q, $model);
         }
-        return implode(' AND ', $constraints);
+        return $constraints;
     }
 
     function getParams() {
@@ -1058,6 +1128,22 @@ class SqlCompiler {
     }
 }
 
+class CompiledExpression /* extends SplString */ {
+    const TYPE_WHERE =   0x0001;
+    const TYPE_HAVING =  0x0002;
+
+    var $text = '';
+
+    function __construct($clause, $type=self::TYPE_WHERE) {
+        $this->text = $clause;
+        $this->type = $type;
+    }
+
+    function __toString() {
+        return $this->text;
+    }
+}
+
 class DbEngine {
 
     static $compiler = 'MySqlCompiler';
@@ -1183,18 +1269,27 @@ class MySqlCompiler extends SqlCompiler {
      * called before ::getJoins(), because it may add joins into the
      * statement based on the relationships used in the where clause
      */
-    protected function getWhereClause($queryset) {
+    protected function getWhereHavingClause($queryset) {
         $model = $queryset->model;
-        $where = $this->compileConstraints($queryset->constraints, $model);
+        $constraints = $this->compileConstraints($queryset->constraints, $model);
+        $where = $having = array();
+        foreach ($constraints as $C) {
+            if ($C->type == CompiledExpression::TYPE_WHERE)
+                $where[] = $C;
+            else
+                $having[] = $C;
+        }
         if ($where)
-            $where = ' WHERE '.$where;
-        return $where ?: '';
+            $where = ' WHERE '.implode(' AND ', $where);
+        if ($having)
+            $having = ' HAVING '.implode(' AND ', $having);
+        return array($where ?: '', $having ?: '');
     }
 
     function compileCount($queryset) {
         $model = $queryset->model;
         $table = $model::$meta['table'];
-        $where = $this->getWhereClause($queryset);
+        list($where, $having) = $this->getWhereHavingClause($queryset);
         $joins = $this->getJoins();
         $sql = 'SELECT COUNT(*) AS count FROM '.$this->quote($table).$joins.$where;
         $exec = new MysqlExecutor($sql, $this->params);
@@ -1207,8 +1302,10 @@ class MySqlCompiler extends SqlCompiler {
         // Use an alias for the root model table
         $table = $model::$meta['table'];
         $this->joins[''] = array('alias' => ($rootAlias = $this->nextAlias()));
+
         // Compile the WHERE clause
-        $where = $this->getWhereClause($queryset);
+        $this->annotations = $queryset->annotations ?: array();
+        list($where, $having) = $this->getWhereHavingClause($queryset);
 
         $sort = '';
         if ($queryset->ordering && !isset($this->options['nosort'])) {
@@ -1231,7 +1328,7 @@ class MySqlCompiler extends SqlCompiler {
         // Handle related tables
         if ($queryset->related) {
             $count = 0;
-            $fieldMap = array();
+            $fieldMap = $theseFields = array();
             $defer = $queryset->defer ?: array();
             // Add local fields first
             $model::_inspect();
@@ -1240,11 +1337,13 @@ class MySqlCompiler extends SqlCompiler {
                 if (isset($defer[$f]))
                     continue;
                 $fields[] = $rootAlias . '.' . $this->quote($f);
+                $theseFields[] = $f;
             }
-            $count = count($fields);
-            $fieldMap[] = array($count, $model);
+            $fieldMap[] = array($theseFields, $model);
             // Add the JOINs to this query
             foreach ($queryset->related as $sr) {
+                // XXX: Sort related by the paths so that the shortest paths
+                //      are resolved first when building out the models.
                 $full_path = '';
                 $parts = array();
                 // Track each model traversal and fetch data for each of the
@@ -1252,6 +1351,7 @@ class MySqlCompiler extends SqlCompiler {
                 foreach (explode('__', $sr) as $field) {
                     $full_path .= $field;
                     $parts[] = $field;
+                    $theseFields = array();
                     list($alias, $fmodel) = $this->getField($full_path, $model,
                         array('table'=>true, 'model'=>true));
                     $fmodel::_inspect();
@@ -1259,37 +1359,54 @@ class MySqlCompiler extends SqlCompiler {
                         // Handle deferreds
                         if (isset($defer[$sr . '__' . $f]))
                             continue;
-                        $fields[] = $alias . '.' . $this->quote($f) . " AS {$alias}_$f";
+                        $fields[] = $alias . '.' . $this->quote($f);
+                        $theseFields[] = $f;
                     }
-                    $fieldMap[] = array(count($fields) - $count, $fmodel, $parts, $alias);
+                    $fieldMap[] = array($theseFields, $fmodel, $parts);
                     $full_path .= '__';
-                    $count = count($fields);
                 }
             }
         }
         // Support retrieving only a list of values rather than a model
         elseif ($queryset->values) {
             foreach ($queryset->values as $v) {
-                list($fields[]) = $this->getField($v, $model);
+                list($f) = $this->getField($v, $model);
+                if ($f instanceof SqlFunction)
+                    $fields[] = $f->toSql($this, $model);
+                else
+                    $fields[] = $f;
             }
         }
         // Simple selection from one table
         else {
             if ($queryset->defer) {
+                $model::_inspect();
                 foreach ($model::$meta['fields'] as $f) {
                     if (isset($queryset->defer[$f]))
                         continue;
-                    $fields[] = $this->quote($f);
+                    $fields[] = $rootAlias .'.'. $this->quote($f);
                 }
             }
             else {
                 $fields[] = $rootAlias.'.*';
             }
         }
+        // Add in annotations
+        if ($queryset->annotations) {
+            foreach ($queryset->annotations as $A) {
+                $fields[] = $A->toSql($this, $model, true);
+                // TODO: Add to last fieldset in fieldMap
+            }
+            $group_by = array();
+            foreach ($model::$meta['pk'] as $pk)
+                $group_by[] = $rootAlias .'.'. $pk;
+            if ($group_by)
+                $group_by = ' GROUP BY '.implode(',', $group_by);
+        }
 
         $joins = $this->getJoins();
         $sql = 'SELECT '.implode(', ', $fields).' FROM '
-            .$table.$joins.$where.$sort;
+            .$table.$joins.$where.$group_by.$having.$sort;
         if ($queryset->limit)
             $sql .= ' LIMIT '.$queryset->limit;
         if ($queryset->offset)
@@ -1351,7 +1468,7 @@ class MySqlCompiler extends SqlCompiler {
     function compileBulkDelete($queryset) {
         $model = $queryset->model;
         $table = $model::$meta['table'];
-        $where = $this->getWhereClause($queryset);
+        list($where, $having) = $this->getWhereHavingClause($queryset);
         $joins = $this->getJoins();
         $sql = 'DELETE '.$this->quote($table).'.* FROM '
             .$this->quote($table).$joins.$where;
@@ -1365,7 +1482,7 @@ class MySqlCompiler extends SqlCompiler {
         foreach ($what as $field=>$value)
             $set[] = sprintf('%s = %s', $this->quote($field), $this->input($value));
         $set = implode(', ', $set);
-        $where = $this->getWhereClause($queryset);
+        list($where, $having) = $this->getWhereHavingClause($queryset);
         $joins = $this->getJoins();
         $sql = 'UPDATE '.$this->quote($table).' SET '.$set.$joins.$where;
         return new MysqlExecutor($sql, $this->params);
@@ -1566,7 +1683,7 @@ class Q {
     }
 
     static function any(array $constraints) {
-        return new static($constraints, self::ORED);
+        return new static($constraints, self::ANY);
     }
 }
 ?>
diff --git a/include/class.user.php b/include/class.user.php
index f94b585cc2f92db7ee58243677b7dfca871ed6c8..08b54cce6303ad6d62ffc6e33199d051d39efa7c 100644
--- a/include/class.user.php
+++ b/include/class.user.php
@@ -76,6 +76,7 @@ class UserModel extends VerySimpleModel {
                 'reverse' => 'UserAccount.user',
             ),
             'org' => array(
+                'null' => true,
                 'constraint' => array('org_id' => 'Organization.id')
             ),
             'default_email' => array(