]> Sergey Matveev's repositories - public-inbox.git/commitdiff
msgmap: mid_insert: use plain "INSERT" to detect duplicates
authorEric Wong <e@80x24.org>
Mon, 24 Jun 2019 23:29:37 +0000 (23:29 +0000)
committerEric Wong <e@80x24.org>
Mon, 24 Jun 2019 23:45:01 +0000 (23:45 +0000)
"INSERT OR IGNORE" still bumps the auto-increment counter in
SQLite, which causes gaps to appear in NNTP article numbering.

This bug appeared in v2 repos where V2Writable may call ->add
repeatedly on the same message.  This bug is apparent with
public-inbox-watch and work-in-progress IMAP watchers which may
rescan and (attempt to) reinsert the same message on mailbox
changes.

Most uses of public-inbox-mda were not affected, unless the
same message is actually delivered multiple times to the mda.
v1 is not affected, either, since deduplication is only based
on Message-ID and msgmap never sees the duplicate.

Reported-by: "Eric W. Biederman" <ebiederm@xmission.com>
lib/PublicInbox/Msgmap.pm
t/msgmap.t
t/v2writable.t

index 0035c9e3dc1ad8ff5bad1d3201ab06ecf9105032..5a89b85a51e297660291f0c4e5477bd2865608da 100644 (file)
@@ -126,9 +126,9 @@ sub mid_insert {
        my ($self, $mid) = @_;
        my $dbh = $self->{dbh};
        my $sth = $dbh->prepare_cached(<<'');
-INSERT OR IGNORE INTO msgmap (mid) VALUES (?)
+INSERT INTO msgmap (mid) VALUES (?)
 
-       return if $sth->execute($mid) == 0;
+       return unless eval { $sth->execute($mid) };
        my $num = $dbh->last_insert_id(undef, undef, 'msgmap', 'num');
        $self->num_highwater($num) if defined($num);
        $num;
index 4dddd0a81852b22c60601b1965d1e7b11224897c..20985ce8cb56be0b9d280660a75eaca6ac27739f 100644 (file)
@@ -30,6 +30,9 @@ $@ = undef;
 my $ret = $d->mid_insert('a@b');
 is($ret, undef, 'duplicate mid_insert in undef result');
 is($d->num_for('a@b'), $mid2num{'a@b'}, 'existing number not clobbered');
+my $next = (sort(keys %num2mid))[-1];
+is($d->mid_insert('ok@unique'), $next + 1,
+       'got expected num after failing mid_insert');
 
 foreach my $n (keys %num2mid) {
        is($d->mid_for($n), $num2mid{$n}, "num:$n maps correctly");
index 88df2d64a30a065dd057f36f6568b8644693f58f..8f32fbe5d9c42e9abfd31e33ce70200c46ca03b6 100644 (file)
@@ -118,6 +118,8 @@ if ('ensure git configs are correct') {
        $mime->header_set('References', '<zz-mid@b>');
        ok($im->add($mime), 'message with multiple Message-ID');
        $im->done;
+       my ($total, undef) = $ibx->over->recent;
+       is($ibx->mm->num_highwater, $total, 'got expected highwater value');
        my $srch = $ibx->search;
        my $mset1 = $srch->reopen->query('m:abcde@1', { mset => 1 });
        is($mset1->size, 1, 'message found by first MID');