diff options
Diffstat (limited to 'lib/PublicInbox/Over.pm')
-rw-r--r-- | lib/PublicInbox/Over.pm | 70 |
1 files changed, 55 insertions, 15 deletions
diff --git a/lib/PublicInbox/Over.pm b/lib/PublicInbox/Over.pm index 19da056a..3b7d49f5 100644 --- a/lib/PublicInbox/Over.pm +++ b/lib/PublicInbox/Over.pm @@ -1,4 +1,4 @@ -# Copyright (C) 2018-2021 all contributors <meta@public-inbox.org> +# Copyright (C) all contributors <meta@public-inbox.org> # License: AGPL-3.0+ <https://www.gnu.org/licenses/agpl-3.0.txt> # for XOVER, OVER in NNTP, and feeds/homepage/threads in PSGI @@ -12,15 +12,17 @@ use DBD::SQLite; use PublicInbox::Smsg; use Compress::Zlib qw(uncompress); use constant DEFAULT_LIMIT => 1000; +use List::Util (); # for max sub dbh_new { my ($self, $rw) = @_; my $f = delete $self->{filename}; - if (!-f $f) { # SQLite defaults mode to 0644, we want 0666 + if (!-s $f) { # SQLite defaults mode to 0644, we want 0666 if ($rw) { - require PublicInbox::Spawn; + require PublicInbox::Syscall; + my ($dir) = ($f =~ m!(.+)/[^/]+\z!); + PublicInbox::Syscall::nodatacow_dir($dir); open my $fh, '+>>', $f or die "failed to open $f: $!"; - PublicInbox::Spawn::nodatacow_fd(fileno($fh)); } else { $self->{filename} = $f; # die on stat() below: } @@ -80,7 +82,13 @@ sub dbh_close { } } -sub dbh ($) { $_[0]->{dbh} //= $_[0]->dbh_new } # dbh_new may be subclassed +sub dbh ($) { + my ($self) = @_; + $self->{dbh} // do { + my $dbh = $self->dbh_new; # dbh_new may be subclassed + $self->{dbh} = $dbh; + } +} sub load_from_row ($;$) { my ($smsg, $cull) = @_; @@ -106,8 +114,8 @@ sub do_get { } sub query_xover { - my ($self, $beg, $end) = @_; - do_get($self, <<'', {}, $beg, $end); + my ($self, $beg, $end, $opt) = @_; + do_get($self, <<'', $opt, $beg, $end); SELECT num,ts,ds,ddd FROM over WHERE num >= ? AND num <= ? ORDER BY num ASC @@ -192,15 +200,22 @@ ORDER BY $sort_col DESC # TODO separate strict and loose matches here once --reindex # is fixed to preserve `tid' properly push @$msgs, @$loose; + + # we wanted to retrieve the latest loose messages; but preserve + # chronological ordering for threading /$INBOX/$MSGID/[tT]/ + $sort_col eq 'ds' and + @$msgs = sort { $a->{ds} <=> $b->{ds} } @$msgs; } ($nr, $msgs); } # strict `tid' matches, only, for thread-expanded mbox.gz search results -# and future CLI interface +# and lei # returns true if we have IDs, undef if not sub expand_thread { my ($self, $ctx) = @_; + # previous maxuid for LeiSavedSearch is our min: + my $lss_min = $ctx->{min} // 0; my $dbh = dbh($self); do { defined(my $num = $ctx->{ids}->[0]) or return; @@ -213,7 +228,7 @@ SELECT num FROM over WHERE tid = ? AND num > ? ORDER BY num ASC LIMIT 1000 my $xids = $dbh->selectcol_arrayref($sql, undef, $tid, - $ctx->{prev} // 0); + List::Util::max($ctx->{prev} // 0, $lss_min)); if (scalar(@$xids)) { $ctx->{prev} = $xids->[-1]; $ctx->{xids} = $xids; @@ -252,9 +267,12 @@ SELECT ts,ds,ddd FROM over WHERE $s sub get_art { my ($self, $num) = @_; # caching $sth ourselves is faster than prepare_cached - my $sth = $self->{-get_art} //= dbh($self)->prepare(<<''); + my $sth = $self->{-get_art} // do { + my $sth = dbh($self)->prepare(<<''); SELECT num,tid,ds,ts,ddd FROM over WHERE num = ? LIMIT 1 + $self->{-get_art} = $sth; + }; $sth->execute($num); my $smsg = $sth->fetchrow_hashref; $smsg ? load_from_row($smsg) : undef; @@ -272,13 +290,35 @@ SELECT ibx_id,xnum,oidbin FROM xref3 WHERE docid = ? ORDER BY ibx_id,xnum ASC my $eidx_key_sth = $dbh->prepare_cached(<<'', undef, 1); SELECT eidx_key FROM inboxes WHERE ibx_id = ? - [ map { - my $r = $_; + for my $r (@$rows) { $eidx_key_sth->execute($r->[0]); my $eidx_key = $eidx_key_sth->fetchrow_array; $eidx_key //= "missing://ibx_id=$r->[0]"; - "$eidx_key:$r->[1]:".unpack('H*', $r->[2]); - } @$rows ]; + $r = "$eidx_key:$r->[1]:".unpack('H*', $r->[2]); + } + $rows; +} + +sub mid2tid { + my ($self, $mid) = @_; + my $dbh = dbh($self); + + my $sth = $dbh->prepare_cached(<<'', undef, 1); +SELECT id FROM msgid WHERE mid = ? LIMIT 1 + + $sth->execute($mid); + my $id = $sth->fetchrow_array or return; + $sth = $dbh->prepare_cached(<<'', undef, 1); +SELECT num FROM id2num WHERE id = ? AND num > ? +ORDER BY num ASC LIMIT 1 + + $sth->execute($id, 0); + my $num = $sth->fetchrow_array or return; + $sth = $dbh->prepare(<<''); +SELECT tid FROM over WHERE num = ? LIMIT 1 + + $sth->execute($num); + $sth->fetchrow_array; } sub next_by_mid { @@ -287,7 +327,7 @@ sub next_by_mid { unless (defined $$id) { my $sth = $dbh->prepare_cached(<<'', undef, 1); - SELECT id FROM msgid WHERE mid = ? LIMIT 1 +SELECT id FROM msgid WHERE mid = ? LIMIT 1 $sth->execute($mid); $$id = $sth->fetchrow_array; |