# Copyright (C) 2015 all contributors <meta@public-inbox.org>
# License: AGPLv3 or later (https://www.gnu.org/licenses/agpl-3.0.txt)
-# bidirectional Message-ID <-> Article Number mapping
+
+# bidirectional Message-ID <-> Article Number mapping for the NNTP
+# and web interfaces. This is required for implementing stable article
+# numbers for NNTP and allows prefix lookups for partial Message-IDs
+# in case URLs get truncated from copy-n-paste errors by users.
+#
+# This is maintained by ::SearchIdx
package PublicInbox::Msgmap;
use strict;
use warnings;
-use fields qw(dbh mid_insert mid_for num_for num_minmax);
use DBI;
use DBD::SQLite;
AutoCommit => 1,
RaiseError => 1,
PrintError => 0,
+ ReadOnly => !$writable,
sqlite_use_immediate_transaction => 1,
});
$dbh->do('PRAGMA case_sensitive_like = ON');
- my $self = fields::new($class);
- $self->{dbh} = $dbh;
+ my $self = bless { dbh => $dbh }, $class;
if ($writable) {
create_tables($dbh);
$dbh->last_insert_id(undef, undef, 'msgmap', 'num');
}
-use constant MID_FOR => 'SELECT mid FROM msgmap WHERE num = ? LIMIT 1';
sub mid_for {
my ($self, $num) = @_;
my $dbh = $self->{dbh};
+ use constant MID_FOR => 'SELECT mid FROM msgmap WHERE num = ? LIMIT 1';
my $sth = $self->{mid_for} ||= $dbh->prepare(MID_FOR);
$sth->bind_param(1, $num);
$sth->execute;
'val VARCHAR(255) NOT NULL)');
}
-sub each_id_batch {
- my ($self, $cb) = @_;
+sub id_batch {
+ my ($self, $num, $cb) = @_;
my $dbh = $self->{dbh};
- my $n = 0;
- my $total = 0;
- my $nr;
my $sth = $dbh->prepare('SELECT num FROM msgmap WHERE num > ? '.
'ORDER BY num ASC LIMIT 1000');
- while (1) {
- $sth->execute($n);
- my $ary = $sth->fetchall_arrayref;
- @$ary = map { $_->[0] } @$ary;
- $nr = scalar @$ary;
- last if $nr == 0;
- $total += $nr;
- $n = $ary->[-1];
- $cb->($ary);
- }
- $total;
+ $sth->execute($num);
+ my $ary = $sth->fetchall_arrayref;
+ @$ary = map { $_->[0] } @$ary;
+ my $nr = scalar @$ary;
+ $cb->($ary) if $nr;
+ $nr;
}
1;