diff --git a/include/class.attachment.php b/include/class.attachment.php
index b602b451c253587ff519c28419063a42ac5b44b8..5ada65726d67f65b7524992594c9ebb0cdf748e9 100644
--- a/include/class.attachment.php
+++ b/include/class.attachment.php
@@ -89,6 +89,21 @@ class Attachment {
     }
 }
 
+class AttachmentModel extends VerySimpleModel {
+    static $meta = array(
+        'table' => ATTACHMENT_TABLE,
+        'pk' => array('id'),
+        'joins' => array(
+            'thread' => array(
+                'constraint' => array(
+                    'object_id' => 'ThreadEntryModel.id',
+                    'type' => "'H'",
+                ),
+            ),
+        ),
+    );
+}
+
 class GenericAttachments {
 
     var $id;
diff --git a/include/class.orm.php b/include/class.orm.php
index 6ed7d52f164bd5f2687207ab78a1bb425759a3db..fcbe457545468fa933af42dcdc51384d09a7ad8f 100644
--- a/include/class.orm.php
+++ b/include/class.orm.php
@@ -80,7 +80,7 @@ class ModelMeta implements ArrayAccess {
                     $j['reverse']));
             foreach ($info['constraint'] as $foreign => $local) {
                 list(,$field) = explode('.', $local);
-                $constraint[$field] = "$fmodel.$foreign";
+                $constraint[$field ?: $local] = "$fmodel.$foreign";
             }
             $j['constraint'] = $constraint;
             if (!isset($j['list']))
@@ -1682,6 +1682,15 @@ class MySqlCompiler extends SqlCompiler {
                     $this->input(trim($local, '\'"'), self::SLOT_JOINS)
                 );
             }
+            // Support local constraint
+            // field_name => "'constant'"
+            elseif ($foreign[0] == "'" && !$right) {
+            die();
+                $constraints[] = sprintf("%s.%s = %s",
+                    $table, $this->quote($local),
+                    $this->input(trim($foreign, '\'"'), self::SLOT_JOINS)
+                );
+            }
             else {
                 $constraints[] = sprintf("%s.%s = %s.%s",
                     $table, $this->quote($local), $alias,
diff --git a/include/class.search.php b/include/class.search.php
index 86ebf80654aaaefe3fb23a6d71121414b5ca5855..538aa7fddf51f48650c9a8ed114c28a4ddef3b23 100644
--- a/include/class.search.php
+++ b/include/class.search.php
@@ -293,8 +293,9 @@ class MysqlSearchBackend extends SearchBackend {
                         FROM `{$P}_search` `search` WHERE $search) `search`",
                     "(select ticket_id as ticket_id from {$P}ticket
                 ) Z1 ON (Z1.ticket_id = search.object_id and search.object_type = 'T')",
-                    "(select A2.id as thread_id, A1.ticket_id from {$P}ticket A1
-                    join {$P}ticket_thread A2 on (A1.ticket_id = A2.ticket_id)
+                    "(select A3.id as thread_id, A1.ticket_id from {$P}ticket A1
+                    join {$P}thread A2 on (A1.ticket_id = A2.object_id and A2.object_type = 'T')
+                    join {$P}thread_entry A3 on (A2.id = A3.thread_id)
                 ) Z2 ON (Z2.thread_id = search.object_id and search.object_type = 'H')",
                 )
             ));
diff --git a/include/class.thread.php b/include/class.thread.php
index 3ee72e753fdb97bd68a85c3d0fcff7e91c195be1..71dc5525f4a1c41f5db5ed95f74f2053a5be62b5 100644
--- a/include/class.thread.php
+++ b/include/class.thread.php
@@ -17,6 +17,24 @@
 include_once(INCLUDE_DIR.'class.ticket.php');
 include_once(INCLUDE_DIR.'class.draft.php');
 
+class ThreadModel extends VerySimpleModel {
+    static $meta = array(
+        'table' => THREAD_TABLE,
+        'pk' => array('id'),
+        'joins' => array(
+            'ticket' => array(
+                'constraint' => array(
+                    'object_id' => 'TicketModel.ticket_id',
+                    'object_type' => "'T'",
+                ),
+            ),
+            'entries' => array(
+                'reverse' => 'ThreadEntryModel.thread',
+            ),
+        ),
+    );
+}
+
 //Ticket thread.
 class Thread {
 
@@ -204,8 +222,23 @@ class Thread {
     }
 }
 
+class ThreadEntryModel extends VerySimpleModel {
+    static $meta = array(
+        'table' => THREAD_ENTRY_TABLE,
+        'pk' => array('id'),
+        'joins' => array(
+            'thread' => array(
+                'constraint' => array('thread_id' => 'ThreadModel.id'),
+            ),
+            'attachments' => array(
+                'reverse' => 'AttachmentModel.thread',
+                'null' => true,
+            ),
+        ),
+    );
+}
 
-Class ThreadEntry {
+class ThreadEntry {
 
     var $id;
     var $ht;
diff --git a/include/class.ticket.php b/include/class.ticket.php
index 44d3d7a7dac4a5722073fe1ab521bb42333e6d70..010a52e5e258231e57ba35b53cdd341321f9a23e 100644
--- a/include/class.ticket.php
+++ b/include/class.ticket.php
@@ -74,6 +74,11 @@ class TicketModel extends VerySimpleModel {
                 'constraint' => array('topic_id' => 'Topic.topic_id'),
                 'null' => true,
             ),
+            'thread' => array(
+                'reverse' => 'ThreadModel.ticket',
+                'list' => false,
+                'null' => true,
+            ),
             'cdata' => array(
                 'reverse' => 'TicketCData.ticket',
                 'list' => false,
diff --git a/include/staff/tickets.inc.php b/include/staff/tickets.inc.php
index 076f0e9adc34a54d30060e78947b54b4623ae338..337aab7465b5a92a8c9d233d7973cc734ee77435 100644
--- a/include/staff/tickets.inc.php
+++ b/include/staff/tickets.inc.php
@@ -103,12 +103,14 @@ $tickets->filter(Q::any($visibility));
 
 // Add in annotations
 $tickets->annotate(array(
-    'collab_count' => SqlAggregate::COUNT('collaborators')
+    'collab_count' => SqlAggregate::COUNT('collaborators'),
+    'attachment_count' => SqlAggregate::COUNT('thread__entries__attachments'),
+    'thread_count' => SqlAggregate::COUNT('thread__entries'),
 ));
 
 // Select pertinent columns
 // ------------------------------------------------------------
-$tickets->values('lock__lock_id', 'staff_id', 'isoverdue', 'team_id', 'ticket_id', 'number', 'cdata__subject', 'user__default_email__address', 'source', 'cdata__:priority__priority_color', 'cdata__:priority__priority_desc', 'status_id', 'status__name', 'status__state', 'dept_id', 'dept__name', 'user__name', 'lastupdate', 'collab_count');
+$tickets->values('lock__lock_id', 'staff_id', 'isoverdue', 'team_id', 'ticket_id', 'number', 'cdata__subject', 'user__default_email__address', 'source', 'cdata__:priority__priority_color', 'cdata__:priority__priority_desc', 'status_id', 'status__name', 'status__state', 'dept_id', 'dept__name', 'user__name', 'lastupdate');
 
 // Apply requested quick filter
 
@@ -286,7 +288,7 @@ $_SESSION[':Q:tickets'] = $tickets;
                 }
                 $tid=$T['number'];
                 $subject = Format::truncate($subject_field->display($subject_field->to_php($T['cdata__subject'])),40);
-                $threadcount=$row['thread_count'];
+                $threadcount=$T['thread_count'];
                 if(!strcasecmp($T['status__state'],'open') && !$T['isanswered'] && !$T['lock__lock_id']) {
                     $tid=sprintf('<b>%s</b>',$tid);
                 }
@@ -318,7 +320,7 @@ $_SESSION[':Q:tickets'] = $tickets;
                                 class="icon-fixed-width icon-comments-alt"></i>&nbsp;';
                         if ($T['collab_count'])
                             echo '<i class="icon-fixed-width icon-group faded"></i>&nbsp;';
-                        if ($row['attachments'])
+                        if ($T['attachment_count'])
                             echo '<i class="icon-fixed-width icon-paperclip"></i>&nbsp;';
                     ?>
                 </td>