root / tags / 1.0.8 / xapian-core / examples / delve.cc

Revision 9248, 7.9 kB (checked in by olly, 16 months ago)

examples/delve.cc,examples/simpleexpand.cc,net/tcpserver.cc,
queryparser/queryparser.cc,queryparser/queryparser.lemony: Add more
missing "#include <string.h>" instances.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1/* delve.cc: Allow inspection of the contents of a Xapian database
2 *
3 * Copyright 1999,2000,2001 BrightStation PLC
4 * Copyright 2002 Ananova Ltd
5 * Copyright 2002,2003,2004,2006,2007 Olly Betts
6 *
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of the
10 * License, or (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301
20 * USA
21 */
22
23#include <config.h>
24
25#include <xapian.h>
26
27#include <algorithm>
28#include <iostream>
29#include <vector>
30
31#include "gnu_getopt.h"
32
33#include <string.h>
34
35using namespace Xapian;
36using namespace std;
37
38static char separator = ' ';
39
40static bool verbose = false;
41static bool showvalues = false;
42static bool showdocdata = false;
43
44#define PROG_NAME "delve"
45#define PROG_DESC "Inspect the contents of a Xapian database"
46
47static void show_usage() {
48    cout << "Usage: "PROG_NAME" [OPTIONS] DATABASE...\n\n"
49"Options:\n"
50"  -r <recno>            for term list(s)\n"
51"  -t <term>             for posting list(s)\n"
52"  -t <term> -r <recno>  for position list(s)\n"
53"  -s, --stemmer=LANG    set the stemming language, the default is 'none'\n"
54"  -1                    output one list entry per line\n"
55"  -V                    output values for each document referred to\n"
56"  -V<valueno>           output value valueno for each document in the database\n"
57"  -d                    output document data for each document referred to\n"
58"  -v                    extra info (wdf and len for postlist;\n"
59"                        wdf termfreq for termlist; number of terms for db)\n"
60"      --help            display this help and exit\n"
61"      --version         output version information and exit" << endl;
62}
63
64static void
65show_db_stats(Database &db)
66{
67    // Display a few database stats.
68    cout << "number of documents = " << db.get_doccount() << endl;
69    cout << "average document length = " << db.get_avlength() << endl;
70    if (verbose) {
71        // To find the number of terms, we have to count them!
72        // This will take a few seconds or minutes, so only do it if -v
73        // was specified.
74        termcount terms = 0;
75        TermIterator t = db.allterms_begin();
76        const TermIterator end = db.allterms_end();
77        while (t != end) {
78            ++terms;
79            ++t;
80        }
81        cout << "number of unique terms = " << terms << endl;
82    }
83}
84
85static void
86show_values(Database &db, docid docid, char sep)
87{
88    Document doc = db.get_document(docid);
89    ValueIterator v = doc.values_begin();
90    ValueIterator vend = doc.values_end();
91    while (v != vend) {
92        cout << sep << v.get_valueno() << ':' << *v;
93        ++v;
94    }
95}
96
97static void
98show_values(Database &db,
99            vector<docid>::const_iterator i,
100            vector<docid>::const_iterator end)
101{
102    while (i != end) {
103        cout << "Values for record #" << *i << ':';
104        show_values(db, *i, separator);
105        cout << endl;
106        ++i;
107    }
108}
109
110static void
111show_docdata(Database &db, docid docid, char sep)
112{
113    cout << sep << "[" << db.get_document(docid).get_data() << ']';
114}
115
116static void
117show_docdata(Database &db,
118             vector<docid>::const_iterator i,
119             vector<docid>::const_iterator end)
120{
121    while (i != end) {
122        cout << "Data for record #" << *i << ':' << endl;
123        cout << db.get_document(*i).get_data() << endl;
124        ++i;
125    }
126}
127
128static void
129show_termlists(Database &db,
130               vector<docid>::const_iterator i,
131               vector<docid>::const_iterator end)
132{
133    // Display termlists
134    while (i != end) {
135        TermIterator t = db.termlist_begin(*i);
136        TermIterator tend = db.termlist_end(*i);
137        cout << "Term List for record #" << *i << ':';
138        while (t != tend) {
139            cout << separator << *t;
140            if (verbose) {
141                cout << ' ' << t.get_wdf() << ' ' << t.get_termfreq();
142            }
143            ++t;
144        }
145        cout << endl;
146        ++i;
147    }
148}
149
150static Stem stemmer;
151
152int
153main(int argc, char **argv)
154{
155    if (argc > 1 && argv[1][0] == '-') {
156        if (strcmp(argv[1], "--help") == 0) {
157            cout << PROG_NAME" - "PROG_DESC"\n\n";
158            show_usage();
159            exit(0);
160        }
161        if (strcmp(argv[1], "--version") == 0) {
162            cout << PROG_NAME" - "PACKAGE_STRING << endl;
163            exit(0);
164        }
165    }
166
167    vector<docid> recnos;
168    vector<string> terms;
169    vector<string> dbs;
170
171    valueno valno = 0; // Avoid "may be used uninitialised" warnings.
172    bool valno_set = false;
173
174    int c;
175    while ((c = gnu_getopt(argc, argv, "r:t:s:1vkV::d")) != EOF) {
176        switch (c) {
177            case 'r':
178                recnos.push_back(atoi(optarg));
179                break;
180            case 't':
181                terms.push_back(optarg);
182                break;
183            case 's':
184                stemmer = Stem(optarg);
185                break;
186            case '1':
187                separator = '\n';
188                break;
189            case 'V': case 'k': /* -k for backward compatibility */
190                showvalues = true;
191                if (optarg) {
192                    valno = atoi(optarg);
193                    valno_set = true;
194                }
195                break;
196            case 'd':
197                showdocdata = true;
198                break;
199            case 'v':
200                verbose = true;
201                break;
202            default:
203                show_usage();
204                exit(1);
205        }
206    }
207
208    while (argv[optind]) dbs.push_back(argv[optind++]);
209
210    if (dbs.empty()) {
211        show_usage();
212        exit(1);
213    }
214
215    std::sort(recnos.begin(), recnos.end());
216
217    Database db;
218    {
219        vector<string>::const_iterator i;
220        for (i = dbs.begin(); i != dbs.end(); i++) {
221            try {
222                db.add_database(Database(*i));
223            } catch (const Error &e) {
224                cout << "Error opening database `" << *i << "': ";
225                cout << e.get_description() << endl;
226                return 1;
227            }
228        }
229    }
230
231    try {
232        if (terms.empty() && recnos.empty() && !valno_set) {
233            show_db_stats(db);
234            return 0;
235        }
236
237        if (!recnos.empty()) {
238            if (showvalues) {
239                show_values(db, recnos.begin(), recnos.end());
240            }
241
242            if (showdocdata) {
243                show_docdata(db, recnos.begin(), recnos.end());
244            }
245        }
246
247        if (valno_set) {
248            doccount n = db.get_doccount();
249            docid did = 0;
250            docid hwm = db.get_lastdocid();
251            cout << "Value " << valno << " for each document:";
252            while (n && did != hwm) {
253                try {
254                    Document doc = db.get_document(++did);
255                    string val = doc.get_value(valno);
256                    if (!val.empty())
257                        cout << separator << did << ':' << doc.get_value(valno);
258                    --n;
259                } catch (DocNotFoundError &) {
260                }
261            }
262            cout << endl;
263        }
264
265        if (terms.empty()) {
266            show_termlists(db, recnos.begin(), recnos.end());
267            return 0;
268        }
269
270        vector<string>::const_iterator i;
271        for (i = terms.begin(); i != terms.end(); i++) {
272            string term = stemmer(*i);
273            PostingIterator p = db.postlist_begin(term);
274            PostingIterator pend = db.postlist_end(term);
275            if (p == pend) {
276                cout << "term `" << term << "' not in database\n";
277                continue;
278            }
279            if (recnos.empty()) {
280                // Display posting list
281                cout << "Posting List for term `" << term << "':";
282                while (p != pend) {
283                    cout << separator << *p;
284                    if (verbose) {
285                        cout << ' ' << p.get_wdf()
286                            << ' ' << p.get_doclength();
287                    }
288                    if (showvalues) show_values(db, *p, ' ');
289                    if (showdocdata) show_docdata(db, *p, ' ');
290                    p++;
291                }
292                cout << endl;
293            } else {
294                // Display position lists
295                vector<docid>::const_iterator j;
296                for (j = recnos.begin(); j != recnos.end(); j++) {
297                    p.skip_to(*j);
298                    if (p == pend || *p != *j) {
299                        cout << "term `" << term <<
300                            "' doesn't index document #" << *j << endl;
301                    } else {
302                        cout << "Position List for term `" << term
303                            << "', record #" << *j << ':';
304                        try {
305                            PositionIterator pos = p.positionlist_begin();
306                            PositionIterator posend = p.positionlist_end();
307                            while (pos != posend) {
308                                cout << separator << *pos;
309                                ++pos;
310                            }
311                            cout << endl;
312                        } catch (const Error &e) {
313                            cout << "Error: " << e.get_description() << endl;
314                        }
315                    }
316                }
317            }
318        }
319    } catch (const Error &e) {
320        cout << "\nError: " << e.get_description() << endl;
321        return 1;
322    }
323}
Note: See TracBrowser for help on using the browser.