changeset 56:566f7a83ece1

for performance, retrieve content for all messages in a collection with a single extra query
author Myk Melez <myk@mozilla.org>
date Wed, 07 May 2008 16:53:31 -0700
parents 5e09fe613d85
children 6c14c9c02630
files extension/modules/collection.js
diffstat 1 files changed, 66 insertions(+), 9 deletions(-) [+]
line wrap: on
line diff
--- a/extension/modules/collection.js	Wed May 07 16:52:03 2008 -0700
+++ b/extension/modules/collection.js	Wed May 07 16:53:31 2008 -0700
@@ -5,18 +5,27 @@
 const Cr = Components.results;
 const Cu = Components.utils;
 
+Cu.import("resource://snowl/modules/log4moz.js");
 Cu.import("resource://snowl/modules/datastore.js");
 Cu.import("resource://snowl/modules/message.js");
 
 /**
  * A group of messages.
  */
-function SnowlCollection(aSourceID, aFilter) {
+function SnowlCollection(aSourceID, aFilter, aCurrent) {
   this._sourceID = aSourceID;
   this._filter = aFilter;
+
+  this._current = aCurrent;
 }
 
 SnowlCollection.prototype = {
+  get _log() {
+    let log = Log4Moz.Service.getLogger("Snowl.Collection");
+    this.__defineGetter__("_log", function() { return log });
+    return this._log;
+  },
+
   _sourceID: null,
 
   get sourceID() {
@@ -39,6 +48,8 @@
     this.invalidate();
   },
 
+  _current: undefined,
+
   sortProperty: "timestamp",
   sortOrder: 1,
 
@@ -49,17 +60,20 @@
       return this._messages;
 
     this._messages = [];
+    this._messageIndex = {};
 
     let statement = this._generateStatement();
     try {
-      while (statement.step())
-        this._messages.push(
-          new SnowlMessage(statement.row.id,
-                           statement.row.subject,
-                           statement.row.author,
-                           statement.row.link,
-                           statement.row.timestamp,
-                           (statement.row.read ? true : false)));
+      while (statement.step()) {
+        let message = new SnowlMessage(statement.row.id,
+                                       statement.row.subject,
+                                       statement.row.author,
+                                       statement.row.link,
+                                       statement.row.timestamp,
+                                       (statement.row.read ? true : false));
+        this._messages.push(message);
+        this._messageIndex[message.id] = message;
+      }
     }
     finally {
       statement.reset();
@@ -67,6 +81,14 @@
 
     this.sort(this.sortProperty, this.sortOrder);
 
+    // A bug in SQLite breaks relating a virtual table via a LEFT JOIN, so we
+    // can't pull content with our initial query.  Instead we do it here.
+    // FIXME: stop doing this once we upgrade to a version of SQLite that does
+    // not have this problem (i.e. 3.5.6+).
+    this._getContent();
+
+    this._log.info("Retrieved " + this._messages.length + " messages.");
+
     return this._messages;
   },
 
@@ -74,6 +96,28 @@
     this._messages = null;
   },
 
+  _getContent: function() {
+    let query = "SELECT messageID, content, contentType " +
+                "FROM parts " +
+                "WHERE parts.messageID IN (" +
+                  this._messages.map(function(v) { return v.id }).join(",") +
+                ")";
+    let statement = SnowlDatastore.createStatement(query);
+
+    try {
+      while (statement.step()) {
+        let content = Cc["@mozilla.org/feed-textconstruct;1"].
+                      createInstance(Ci.nsIFeedTextConstruct);
+        content.text = statement.row.content;
+        content.type = textConstructTypes[statement.row.contentType];
+        this._messageIndex[statement.row.messageID].content = content;
+      }
+    }
+    finally {
+      statement.reset();
+    }
+  },
+
   _generateStatement: function() {
     let query = 
       //"SELECT sources.title AS sourceTitle, subject, author, link, timestamp, content \
@@ -93,9 +137,14 @@
     if (this.filter)
       conditions.push("messages.id IN (SELECT messageID FROM parts WHERE content MATCH :filter)");
 
+    if (typeof this._current != "undefined")
+      conditions.push("current = " + (this._current ? "1" : "0"));
+
     if (conditions.length > 0)
       query += " WHERE " + conditions.join(" AND ");
 
+    this._log.info(query);
+
     let statement = SnowlDatastore.createStatement(query);
 
     if (this.sourceID)
@@ -148,3 +197,11 @@
 
   return aObject;
 }
+
+// FIXME: get this from message.js (or from something that both message.js and collection.js import).
+let textConstructTypes = {
+  "text/html": "html",
+  "application/xhtml+xml": "xhtml",
+  "text/plain": "text"
+};
+