clean up loose ends in SqliteMailbox
[org.ibex.mail.git] / src / org / ibex / mail / SqliteMailbox.java
index bcea924..384dc4d 100644 (file)
@@ -237,15 +237,38 @@ public class SqliteMailbox extends Mailbox.Default implements MailTree {
     }
     public void             insert(Message m, int flags) {
         try {
+            PreparedStatement query = conn.prepareStatement("select headers_,body_,flags_ from 'mail' where messageid_=?");
+            query.setString(1, m.messageid);
+            Log.warn("SQL", "select headers_,body_,flags_ from 'mail' where messageid_="+m.messageid);
+            ResultSet rs2 = query.executeQuery();
+            if (rs2.next()) {
+                Message m2 = Message.newMessage(Fountain.Util.concat(Fountain.Util.create(rs2.getString(1)),
+                                                                     Fountain.Util.create("\r\n\r\n"),
+                                                                     Fountain.Util.create(rs2.getString(2))));
+                StringBuffer s1 = new StringBuffer();
+                m.getBody().getStream().transcribe(s1);
+                StringBuffer s2 = new StringBuffer();
+                m2.getBody().getStream().transcribe(s2);
+                if (!s1.toString().equals(s2.toString())) {
+                    Log.error(this.toString(),
+                              "attempt to insert two messages with identical messageid ("+m.messageid+") but different bodies:\n"+
+                              "  (body length="+s1.length()+") "+m.summary()+"\n"+
+                              "  (body length="+s2.length()+") "+m2.summary()+"\n");
+                } else {
+                    Log.warn(this.toString(),
+                             "silently dropping duplicate insert() [messageids and bodies match]: " + m.summary());
+                    return;
+                }
+            }
             PreparedStatement add =
-                conn.prepareStatement("insert or replace into 'mail' ("+columns+") values (?,?,?,?,?,?,?,?)");
+                conn.prepareStatement("insert "+/*"or replace "+*/"into 'mail' ("+columns+") values (?,?,?,?,?,?,?,?)");
             add.setString(1, m.messageid+"");
             add.setString(2, m.from+"");
             add.setString(3, m.to+"");
             add.setString(4, m.date+"");
             add.setString(5, m.subject+"");
-            add.setString(6, streamToString(m.headers.getStream()));
-            add.setString(7, streamToString(m.getBody().getStream()));
+            add.setString(6, SqliteDB.streamToString(m.headers.getStream()));
+            add.setString(7, SqliteDB.streamToString(m.getBody().getStream()));
             add.setInt   (8, flags);
             add.executeUpdate();
 
@@ -265,12 +288,29 @@ public class SqliteMailbox extends Mailbox.Default implements MailTree {
         public SqliteJdbcIterator() { this(""); }
         public SqliteJdbcIterator(String whereClause) {
             try {
+                /*
+                if (whereClause.equals(""))
+                    Log.warn(this, "performance warning: empty whereClause");
+                */
                 this.whereClause = whereClause;
                 Log.warn("SQL", "select messageid_,uid_,flags_ from 'mail' "+whereClause);
                 PreparedStatement query = conn.prepareStatement("select messageid_,uid_,flags_ from 'mail' "+whereClause);
                 rs = query.executeQuery();
             } catch (Exception e) { throw new RuntimeException(e); }
         }
+        public Headers head()   {
+            if (m != null) return m.headers;
+            try {
+                PreparedStatement query = conn.prepareStatement("select headers_,flags_ from 'mail' where messageid_=?");
+                query.setString(1, rs.getString(1));
+                Log.warn("SQL", "select headers_,flags_ from 'mail' where messageid_="+rs.getString(1));
+
+                ResultSet rs2 = query.executeQuery();
+                if (!rs2.next()) { Log.error("XXX", "should not happen"); return null; }
+                flags = rs2.getInt(2);
+                return new Headers(Fountain.Util.create(rs2.getString(1)));
+            } catch (Exception e) { throw new RuntimeException(e); }
+        }
         public Message cur()    {
             try {
                 if (m!=null) return m;
@@ -295,13 +335,13 @@ public class SqliteMailbox extends Mailbox.Default implements MailTree {
                 int oldflags = rs.getInt("flags_");
                 if (oldflags==flags) return;
                 Log.info(this, "setflags (old="+oldflags+")" + "update mail set flags_="+(flags)+" where uid_="+uid()+"");
+                if ((flags & Mailbox.Flag.DELETED) != 0) Log.printStackTrace("deletion", Log.WARN);
                 PreparedStatement update = conn.prepareStatement("update mail set flags_=? where uid_=?");
                 update.setInt(1, flags);
                 update.setInt(2, uid());
                 update.executeUpdate();
             } catch (Exception e) { throw new RuntimeException(e); }
         }
-        public Headers head()       { return cur().headers; }
         public boolean next()       {
             try { m = null; uid = -1; count++;
             boolean ret = rs.next();
@@ -314,11 +354,7 @@ public class SqliteMailbox extends Mailbox.Default implements MailTree {
         }
         public int     imapNumber() {
             if ("".equals(whereClause)) return count;
-            try {
-                ResultSet rs = conn.prepareStatement("select count(*) from mail where uid_ <= " + uid()).executeQuery();
-                rs.next();
-                return rs.getInt(1);
-            } catch (Exception e) { throw new RuntimeException(e); }
+            try { return queryImapNumberCache(uid()); } catch (SQLException s) { throw new RuntimeException(s); }
         }
         public int     nntpNumber() { return uid(); }
         public void    delete()     {