# no UNIQUE constraint on UIDVALIDITY as two mailboxes may share the same value
q{UIDVALIDITY UNSIGNED INT NOT NULL CHECK (UIDVALIDITY > 0)},
q{UIDNEXT UNSIGNED INT NOT NULL}, # 0 initially
- q{HIGHESTMODSEQ UNSIGNED BIGINT NOT NULL} # 0 initially
+ q{HIGHESTMODSEQ UNSIGNED BIGINT NOT NULL} # 0 initially (/!\ converted to 8-byte signed integer)
# one-to-one correspondence between local.idx and remote.idx
],
remote => [
# no UNIQUE constraint on UIDVALIDITY as two mailboxes may share the same value
q{UIDVALIDITY UNSIGNED INT NOT NULL CHECK (UIDVALIDITY > 0)},
q{UIDNEXT UNSIGNED INT NOT NULL}, # 0 initially
- q{HIGHESTMODSEQ UNSIGNED BIGINT NOT NULL} # 0 initially
+ q{HIGHESTMODSEQ UNSIGNED BIGINT NOT NULL} # 0 initially (/!\ converted to 8-byte signed integer)
# one-to-one correspondence between local.idx and remote.idx
],
mapping => [
#############################################################################
# Synchronize messages
-# Update the HIGHESTMODSEQ.
-my $STH_UPDATE_LOCAL_HIGHESTMODSEQ = $DBH->prepare(q{UPDATE local SET HIGHESTMODSEQ = ? WHERE idx = ?});
-my $STH_UPDATE_REMOTE_HIGHESTMODSEQ = $DBH->prepare(q{UPDATE remote SET HIGHESTMODSEQ = ? WHERE idx = ?});
-
-# Update the HIGHESTMODSEQ and UIDNEXT.
-my $STH_UPDATE_LOCAL = $DBH->prepare(q{UPDATE local SET UIDNEXT = ?, HIGHESTMODSEQ = ? WHERE idx = ?});
-my $STH_UPDATE_REMOTE = $DBH->prepare(q{UPDATE remote SET UIDNEXT = ?, HIGHESTMODSEQ = ? WHERE idx = ?});
-
-# Add a new mailbox.
-my $STH_INSERT_LOCAL = $DBH->prepare(q{INSERT INTO local (idx,UIDVALIDITY,UIDNEXT,HIGHESTMODSEQ) VALUES (?,?,0,0)});
-my $STH_INSERT_REMOTE = $DBH->prepare(q{INSERT INTO remote (idx,UIDVALIDITY,UIDNEXT,HIGHESTMODSEQ) VALUES (?,?,0,0)});
-
# Download some missing UIDs from $source; returns the new allocated UIDs
sub download_missing($$$@) {
my $idx = shift;
# don't store the new UIDNEXTs before to avoid downloading these
# mails again in the event of a crash
- $STH_UPDATE_LOCAL->execute($lIMAP->get_cache( qw/UIDNEXT HIGHESTMODSEQ/), $idx) or
- msg('database', "WARNING: Can't update remote UIDNEXT/HIGHESTMODSEQ for $mailbox");
- $STH_UPDATE_REMOTE->execute($rIMAP->get_cache(qw/UIDNEXT HIGHESTMODSEQ/), $idx) or
- msg('database', "WARNING: Can't update remote UIDNEXT/HIGHESTMODSEQ for $mailbox");
+
+ state $sth_update_local = $DBH->prepare(q{
+ UPDATE local
+ SET UIDNEXT = ?, HIGHESTMODSEQ = ?
+ WHERE idx = ?
+ });
+ state $sth_update_remote = $DBH->prepare(q{
+ UPDATE remote
+ SET UIDNEXT = ?, HIGHESTMODSEQ = ?
+ WHERE idx = ?
+ });
+
+ my ($lUIDNEXT, $lHIGHESTMODSEQ) = $lIMAP->get_cache(qw/UIDNEXT HIGHESTMODSEQ/);
+ $sth_update_local->bind_param(1, $lUIDNEXT, SQL_INTEGER);
+ $sth_update_local->bind_param(2, sprintf("%lld", $lHIGHESTMODSEQ), SQL_BIGINT);
+ $sth_update_local->bind_param(3, $idx, SQL_INTEGER);
+ $sth_update_local->execute();
+
+ my ($rUIDNEXT, $rHIGHESTMODSEQ) = $rIMAP->get_cache(qw/UIDNEXT HIGHESTMODSEQ/);
+ $sth_update_remote->bind_param(1, $rUIDNEXT, SQL_INTEGER);
+ $sth_update_remote->bind_param(2, sprintf("%lld", $rHIGHESTMODSEQ), SQL_BIGINT);
+ $sth_update_remote->bind_param(3, $idx, SQL_INTEGER);
+ $sth_update_remote->execute();
+
$DBH->commit();
}
$sth->execute();
my $cache = $sth->fetchrow_hashref();
die if defined $sth->fetch(); # safety check
+ if (defined $cache) {
+ $cache->{$_} = sprintf("%llu", $cache->{$_}) foreach qw/lHIGHESTMODSEQ rHIGHESTMODSEQ/;
+ }
return $cache;
}
$lIMAP->set_cache(mbx_name(local => $row->{mailbox}),
UIDVALIDITY => $row->{lUIDVALIDITY},
UIDNEXT => $row->{lUIDNEXT},
- HIGHESTMODSEQ => $row->{lHIGHESTMODSEQ}
+ HIGHESTMODSEQ => sprintf("%llu", $row->{lHIGHESTMODSEQ})
);
$rIMAP->set_cache(mbx_name(remote => $row->{mailbox}),
UIDVALIDITY => $row->{rUIDVALIDITY},
UIDNEXT => $row->{rUIDNEXT},
- HIGHESTMODSEQ => $row->{rHIGHESTMODSEQ}
+ HIGHESTMODSEQ => sprintf("%llu", $row->{rHIGHESTMODSEQ})
);
$KNOWN_INDEXES{$row->{idx}} = 1;
}
sub loop() {
+ state $sth_insert_local = $DBH->prepare(q{
+ INSERT INTO local (idx,UIDVALIDITY,UIDNEXT,HIGHESTMODSEQ) VALUES (?,?,0,0)
+ });
+ state $sth_insert_remote = $DBH->prepare(q{
+ INSERT INTO remote (idx,UIDVALIDITY,UIDNEXT,HIGHESTMODSEQ) VALUES (?,?,0,0)
+ });
+
+ state $sth_update_local_highestmodseq = $DBH->prepare(q{
+ UPDATE local
+ SET HIGHESTMODSEQ = ?
+ WHERE idx = ?
+ });
+ state $sth_update_remote_highestmodseq = $DBH->prepare(q{
+ UPDATE remote
+ SET HIGHESTMODSEQ = ?
+ WHERE idx = ?
+ });
+
while(@MAILBOXES) {
if (defined $MAILBOX and ($lIMAP->is_dirty(mbx_name(local => $MAILBOX)) or $rIMAP->is_dirty(mbx_name(remote => $MAILBOX)))) {
# $MAILBOX is dirty on either the local or remote mailbox
select_mbx($IDX, $MAILBOX);
if (!$KNOWN_INDEXES{$IDX}) {
- $STH_INSERT_LOCAL->execute( $IDX, $lIMAP->uidvalidity($MAILBOX));
- $STH_INSERT_REMOTE->execute($IDX, $rIMAP->uidvalidity($MAILBOX));
+ my $lUIDVALIDITY = $lIMAP->uidvalidity(mbx_name(local => $MAILBOX));
+ $sth_insert_local->bind_param(1, $IDX, SQL_INTEGER);
+ $sth_insert_local->bind_param(2, $lUIDVALIDITY, SQL_INTEGER);
+ $sth_insert_local->execute();
+
+ my $rUIDVALIDITY = $rIMAP->uidvalidity(mbx_name(remote => $MAILBOX));
+ $sth_insert_remote->bind_param(1, $IDX, SQL_INTEGER);
+ $sth_insert_remote->bind_param(2, $rUIDVALIDITY, SQL_INTEGER);
+ $sth_insert_remote->execute();
# no need to commit before the first mapping (lUID,rUID)
$KNOWN_INDEXES{$IDX} = 1;
elsif (sync_known_messages($IDX, $MAILBOX)) {
# sync updates to known messages before fetching new messages
# get_cache is safe after pull_update
- $STH_UPDATE_LOCAL_HIGHESTMODSEQ->execute( $lIMAP->get_cache('HIGHESTMODSEQ'), $IDX) or
- msg('database', "WARNING: Can't update local HIGHESTMODSEQ for $MAILBOX");
- $STH_UPDATE_REMOTE_HIGHESTMODSEQ->execute($rIMAP->get_cache('HIGHESTMODSEQ'), $IDX) or
- msg('database', "WARNING: Can't update remote HIGHESTMODSEQ for $MAILBOX");
+ my $lHIGHESTMODSEQ = sprintf "%lld", $lIMAP->get_cache(qw/HIGHESTMODSEQ/);
+ $sth_update_local_highestmodseq->bind_param(1, $lHIGHESTMODSEQ, SQL_BIGINT);
+ $sth_update_local_highestmodseq->bind_param(2, $IDX, SQL_INTEGER);
+ $sth_update_local_highestmodseq->execute();
+
+ my $rHIGHESTMODSEQ = sprintf "%lld", $rIMAP->get_cache(qw/HIGHESTMODSEQ/);
+ $sth_update_remote_highestmodseq->bind_param(1, $rHIGHESTMODSEQ, SQL_BIGINT);
+ $sth_update_remote_highestmodseq->bind_param(2, $IDX, SQL_INTEGER);
+ $sth_update_remote_highestmodseq->execute();
$DBH->commit();
}
sync_messages($IDX, $MAILBOX);