Tweak to cope with different DB file names
[debian-cd-search.git] / find_file_db.pl
1 #!/usr/bin/perl
2 #
3 # find_file_db.pl
4 #
5 # Look through a provided database to find which CD/DVD image(s)
6 # contain a specified Debian package or source file.
7
8 # Copyright (c) 2011-2017 Steve McIntyre <93sam@debian.org>
9
10 # This program is free software; you can redistribute it and/or modify
11 # it under the terms of the GNU General Public License as published by
12 # the Free Software Foundation; either version 2 of the License, or
13 # (at your option) any later version.
14 #
15 # This program is distributed in the hope that it will be useful,
16 # but WITHOUT ANY WARRANTY; without even the implied warranty of
17 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18 # GNU General Public License for more details.
19 #
20 # You should have received a copy of the GNU General Public License
21 # along with this program; if not, write to the Free Software
22 # Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA
23
24 use strict;
25 use warnings;
26 use threads;
27 use DB_File;
28 use DBI;
29 use DBD::SQLite;
30
31 my $dbdir = "/home/steve/debian/debian-cd/search-db";
32 my @AREAS;
33 my %num_files;
34 my %fileinfo;
35 my %imageinfo;
36 my %results;
37 my $max_count = 1000;
38 my $dbtype = "sqlite";
39
40 # Borrowed from Ikiwiki.pm
41 sub glob2re ($) {
42     my $re=quotemeta(shift);
43     $re=~s/\\\*/.*/g;
44     $re=~s/\\\?/./g;
45     return qr/^$re$/i;
46 }
47
48 chdir($dbdir) || die "Failed to cd to $dbdir: $!\n";
49 opendir(my $dh, ".") || die "Failed to open $dbdir: $!\n";
50 while (defined($_ = readdir($dh))) {
51     if ($dbtype eq "hash") {
52         m/(.*)\.db$/ and push (@AREAS, $1);
53     } else {
54         m/(.*)\.db\.sqlite$/ and push (@AREAS, $1);
55     }
56 }
57 closedir($dh);
58
59 my $query_term = shift;
60
61 if (!defined($query_term) || !length($query_term)) {
62     die "No query term specified!\n";
63 }
64
65 sub keepalive_thread () {
66     $SIG{'KILL'} = sub { threads->exit(); };
67     while(1) {
68         sleep 10;
69         print "<!-- processing, please wait... ->\n"
70     }
71 }
72
73 my $count = 0;
74 my $count_images = 0;
75 my $re_search = glob2re($query_term);
76 my $start_time = time();
77
78 # Now start the keepalive thread to print something every few seconds
79 #my $thr = threads->create(\&keepalive_thread);
80
81 if ($dbtype eq "hash") {
82     foreach my $area (@AREAS) {
83         print "Looking in area $area\n";
84         my $db_file_name = "$dbdir/$area.db";
85         dbmopen(%fileinfo, "$db_file_name", 0000) || 
86             die "Failed to open db file: $!\n";
87
88         if ($query_term =~ /[\*\?]/) {
89             # Will need to search through all the keys to allow for glob
90             foreach my $file (keys %fileinfo) {
91                 if ($file =~ $re_search) {
92                     $count++;
93                     $count_images += scalar (split / /, $fileinfo{$file});
94                     $results{$file} = $fileinfo{$file};
95                     if ($count >= $max_count) {
96                         last;
97                     }
98                 }
99             }
100         } else {
101             # We've been given an exact name - do the exact key lookup \o/
102             if (defined($fileinfo{$query_term})) {
103                 $results{$query_term} = $fileinfo{$query_term};
104                 $count_images += scalar (split / /, $fileinfo{$query_term});
105                 $count++;
106             }
107         }
108         if ($count >= $max_count) {
109             last;
110         }
111         dbmclose %fileinfo;
112     }
113 } else {
114     foreach my $area (@AREAS) {
115         print "Looking in area $area\n";
116         my $sth;
117         my @db_results;
118         my $db_file_name = "$dbdir/$area.db.sqlite";
119         my $dbh = DBI->connect("dbi:SQLite:dbname=$db_file_name","","", {
120             sqlite_open_flags => DBD::SQLite::OPEN_READONLY,
121                                }) or die "Failed to open DB file $db_file_name: $!\n";
122         $dbh->do("PRAGMA synchronous = OFF");
123
124         if ($query_term =~ /[\*\?]/) {
125             # Will need to use sql LIKE and SQL wildcards
126             my $sql_term = $query_term;
127             $sql_term =~ s,\*,\%,g;
128             $sql_term =~ s,\?,\_,g;
129             $sth = $dbh->prepare("SELECT * FROM entries WHERE filename LIKE ? ORDER BY filename ASC, jigdo ASC");
130             $sth->execute($sql_term);
131         } else {
132             # We've been given an exact name - do the exact lookup
133             $sth = $dbh->prepare("SELECT * FROM entries WHERE filename=? ORDER BY filename ASC");
134             $sth->execute($query_term);
135         }
136         while (@db_results = $sth->fetchrow_array) {
137             my $file = $db_results[0];
138             my $image = $db_results[1];
139             if (defined($results{$file})) {
140                 $results{$file} = "$results{$file} $image";
141                 $count_images++;
142             } else {
143                 $results{$file} = "$image";
144                 $count++;
145                 $count_images++;
146             }
147             #                   print "@results\n";
148             if ($count >= $max_count) {
149                 last;
150             }
151         }
152         $dbh->disconnect();
153     }
154 }
155 # Kill the keepalive thread
156 #$thr->kill('KILL')->join();
157
158 my $end_time = time();
159 my $time_taken = $end_time - $start_time;
160
161 print "Using $dbtype database, took $time_taken seconds:\n";
162 if ($count >= $max_count) {
163     print "More than $max_count results for \"$query_term\", showing the first $count only\n";
164 } else {   
165     print "$count result(s), $count_images image(s) for \"$query_term\":\n";
166 }
167
168 foreach my $found (sort (keys %results)) {
169     my @list = split(' ', $results{$found});
170     print "  $found:\n";
171     foreach my $image (sort(@list)) {
172         print "    $image\n";
173     }
174 }
175