New Inbox messages aren't saved

This fixes a nasty little bug I noticed today where Geary would
load new messages from the server, but if you closed and re-opened
Geary, they wouldn't appear until it had connected to the server
again.

It turned out the local database wasn't updating the last_seen_total
value (very important when loading messages before connecting to
the server) due to an issue where SQLite cannot bind NULL to WHERE
clauses in prepared statements.
This commit is contained in:
Jim Nelson 2012-09-03 17:57:05 -07:00
parent 47f3f266bf
commit 9f80cfde4c
4 changed files with 39 additions and 18 deletions

View file

@ -202,7 +202,8 @@ public class Geary.Db.Statement : Geary.Db.Context {
* index is zero-based.
*
* This will bind the value to the column as an int64 unless it's INVALID_ROWID, in which case
* the column is bound as NULL.
* the column is bound as NULL. WARNING: This does *not* work in WHERE clauses. For WHERE, you
* must use "field IS NULL".
*/
public Statement bind_rowid(int index, int64 rowid) throws DatabaseError {
return (rowid != Db.INVALID_ROWID) ? bind_int64(index, rowid) : bind_null(index);
@ -210,6 +211,8 @@ public class Geary.Db.Statement : Geary.Db.Context {
/**
* index is zero-based.
*
* WARNING: This does *not* work in WHERE clauses. For WHERE, you must use "field IS NULL".
*/
public Statement bind_null(int index) throws DatabaseError {
throw_on_error("Statement.bind_null", stmt.bind_null(index + 1));

View file

@ -140,17 +140,31 @@ private class Geary.ImapDB.Account : Object {
return Db.TransactionOutcome.ROLLBACK;
}
Db.Statement stmt = cx.prepare(
"UPDATE FolderTable SET last_seen_total=?, uid_validity=?, uid_next=?, attributes=? "
+ "WHERE parent_id=? AND name=?");
stmt.bind_int(0, properties.messages);
stmt.bind_int64(1, (properties.uid_validity != null) ? properties.uid_validity.value
: Imap.UIDValidity.INVALID);
stmt.bind_int64(2, (properties.uid_next != null) ? properties.uid_next.value
: Imap.UID.INVALID);
stmt.bind_string(3, properties.attrs.serialize());
stmt.bind_rowid(4, parent_id);
stmt.bind_string(4, path.basename);
Db.Statement stmt;
if (parent_id != Db.INVALID_ROWID) {
stmt = cx.prepare(
"UPDATE FolderTable SET last_seen_total=?, uid_validity=?, uid_next=?, attributes=? "
+ "WHERE parent_id=? AND name=?");
stmt.bind_int(0, properties.messages);
stmt.bind_int64(1, (properties.uid_validity != null) ? properties.uid_validity.value
: Imap.UIDValidity.INVALID);
stmt.bind_int64(2, (properties.uid_next != null) ? properties.uid_next.value
: Imap.UID.INVALID);
stmt.bind_string(3, properties.attrs.serialize());
stmt.bind_rowid(4, parent_id);
stmt.bind_string(5, path.basename);
} else {
stmt = cx.prepare(
"UPDATE FolderTable SET last_seen_total=?, uid_validity=?, uid_next=?, attributes=? "
+ "WHERE parent_id IS NULL AND name=?");
stmt.bind_int(0, properties.messages);
stmt.bind_int64(1, (properties.uid_validity != null) ? properties.uid_validity.value
: Imap.UIDValidity.INVALID);
stmt.bind_int64(2, (properties.uid_next != null) ? properties.uid_next.value
: Imap.UID.INVALID);
stmt.bind_string(3, properties.attrs.serialize());
stmt.bind_string(4, path.basename);
}
stmt.exec();
@ -375,7 +389,7 @@ private class Geary.ImapDB.Account : Object {
// drop from folder references table, all cleaned up
folder_refs.unset(folder_ref.path);
}
private void clear_duplicate_folders() {
int count = 0;

View file

@ -64,6 +64,8 @@ private class Geary.ImapDB.Folder : Object, Geary.ReferenceSemantics {
internal Folder(ImapDB.Database db, Geary.FolderPath path, ContactStore contact_store,
string account_owner_email, int64 folder_id, Geary.Imap.FolderProperties? properties) {
assert(folder_id != Db.INVALID_ROWID);
this.db = db;
this.path = path;
this.contact_store = contact_store;

View file

@ -970,11 +970,13 @@ private class Geary.ImapEngine.GenericFolder : Geary.AbstractFolder, Geary.Folde
assert(remote_count >= 0);
if (remote_count < local_count) {
debug("remote_position_to_local_position: remote_count=%d < local_count=%d",
remote_count, local_count);
} else if (remote_pos > remote_count) {
debug("remote_position_to_local_position: remote_pos=%d > remote_count=%d",
remote_pos, remote_count);
debug("remote_position_to_local_position: remote_count=%d < local_count=%d (remote_pos=%d)",
remote_count, local_count, remote_pos);
}
if (remote_pos > remote_count) {
debug("remote_position_to_local_position: remote_pos=%d > remote_count=%d (local_count=%d)",
remote_pos, remote_count, local_count);
}
return (remote_pos <= remote_count) ? remote_pos - (remote_count - local_count) : -1;