40 #define PROG_NAME "xapian-inspect" 41 #define PROG_DESC "Inspect the contents of a glass table for development or debugging" 49 cout <<
"Usage: " PROG_NAME " [OPTIONS] TABLE\n" 50 " " PROG_NAME " [OPTIONS] -t TABLE DB\n\n" 52 " -t, --table=TABLE which table to inspect\n" 53 " --help display this help and exit\n" 54 " --version output version information and exit\n";
60 for (
unsigned char ch : data) {
61 if (ch < 32 || ch >= 127) {
63 case '\n': cout <<
"\\n";
break;
64 case '\r': cout <<
"\\r";
break;
65 case '\t': cout <<
"\\t";
break;
68 sprintf(buf,
"\\x%02x",
int(ch));
72 }
else if (ch ==
'\\') {
84 auto bslash = s.find(
'\\');
85 if (bslash == string::npos)
87 string r(s, 0, bslash);
88 for (
auto i = s.begin() + bslash; i != s.end(); ++i) {
132 cout <<
"Bad escaping in specified key value, assuming literal\n";
139 cout <<
"Commands:\n" 140 "next : Next entry (alias 'n' or '')\n" 141 "prev : Previous entry (alias 'p')\n" 142 "first : First entry (alias 'f')\n" 143 "last : Last entry (alias 'l')\n" 144 "goto K : Goto first entry with key >= K (alias 'g')\n" 145 "until K: Display entries until key >= K (alias 'u')\n" 146 "until : Display entries until end (alias 'u')\n" 147 "count K: Count entries until key >= K (alias 'c')\n" 148 "count : Count entries until end (alias 'c')\n" 149 "open T : Open table T instead (alias 'o') - e.g. open postlist\n" 150 "keys : Toggle showing keys (default: true) (alias 'k')\n" 151 "tags : Toggle showing tags (default: true) (alias 't')\n" 152 "help : Show this (alias 'h' or '?')\n" 153 "quit : Quit this utility (alias 'q')\n";
160 cout <<
"After end\n";
164 cout <<
"Before start\n";
184 cout <<
"At end already.\n";
188 if (!target.empty()) {
192 cout <<
"Already after specified key.\n";
194 cout <<
"Already at specified key.\n";
200 while (cursor.
next()) {
209 cout <<
"No exact match, stopping at entry after, " 210 "having advanced by " << count <<
" entries.\n";
214 cout <<
"Advanced by " << count <<
" entries.\n";
219 cout <<
"Reached end, having advanced by " << count <<
" entries.\n";
234 static const struct option long_opts[] = {
268 string db_path(argv[
optind]);
270 if (arg_is_directory && table_name.empty()) {
272 <<
": You need to specify a table name to inspect with " 276 int single_file_fd = -1;
277 if (table_name.empty()) {
282 db_path.resize(db_path.size() -
284 }
else if (
endswith(db_path,
'.')) {
285 db_path.resize(db_path.size() - 1);
287 size_t slash = db_path.find_last_of(
DIR_SEPS);
290 table_name.assign(db_path, slash + 1, string::npos);
291 if (slash != string::npos) {
292 db_path.resize(slash);
296 }
else if (!arg_is_directory) {
297 single_file_fd =
open(db_path.c_str(), O_RDONLY |
O_BINARY);
298 if (single_file_fd < 0) {
299 cerr << argv[0] <<
": Couldn't open file '" << db_path <<
"'" 306 if (single_file_fd < 0) {
319 open_different_table:
322 if (table_name ==
"docdata") {
324 }
else if (table_name ==
"spelling") {
326 }
else if (table_name ==
"synonym") {
328 }
else if (table_name ==
"termlist") {
330 }
else if (table_name ==
"position") {
332 }
else if (table_name ==
"postlist") {
335 cerr <<
"Unknown table: '" << table_name <<
"'\n";
340 if (single_file_fd < 0) {
341 string table_path = db_path;
343 table_path += table_name;
345 table_ptr =
new GlassTable(
"", table_path,
true);
348 table_ptr =
new GlassTable(
"", single_file_fd, offset,
true);
354 cout <<
"No entries!\n";
366 cout <<
"? " << flush;
370 if (cin.eof())
break;
373 input.resize(input.size() - 1);
375 if (input.empty() || input ==
"n" || input ==
"next") {
377 cout <<
"At end already.\n";
382 }
else if (input ==
"p" || input ==
"prev") {
384 cout <<
"Before start already.\n";
401 }
else if (input ==
"u" || input ==
"until") {
410 }
else if (input ==
"c" || input ==
"count") {
413 }
else if (input ==
"f" || input ==
"first") {
417 }
else if (input ==
"l" || input ==
"last") {
422 cout <<
"No exact match, going to entry after.\n";
427 cout <<
"No exact match, going to entry after.\n";
431 size_t trim = (input[1] ==
' ' ? 2 : 5);
432 table_name.assign(input, trim, string::npos);
434 table_name.resize(table_name.size() -
437 table_name.resize(table_name.size() - 1);
438 goto open_different_table;
439 }
else if (input ==
"t" || input ==
"tags") {
441 cout <<
"Showing tags: " << boolalpha <<
tags <<
'\n';
442 }
else if (input ==
"k" || input ==
"keys") {
444 cout <<
"Showing keys: " << boolalpha <<
keys <<
'\n';
445 }
else if (input ==
"q" || input ==
"quit") {
447 }
else if (input ==
"h" || input ==
"help" || input ==
"?") {
451 cout <<
"Unknown command.\n";
const RootInfo & get_root(Glass::table_type tbl) const
static void do_until(GlassCursor &cursor, const string &target, bool show)
bool endswith(const std::string &s, char sfx)
Wrappers to allow GNU getopt to be used cleanly from C++ code.
XAPIAN_REVISION_TYPE rev
Revision number of a database.
int gnu_getopt_long(int argc_, char *const *argv_, const char *shortopts_, const struct option *longopts_, int *optind_)
#define GLASS_BTREE_MAX_KEY_LEN
The largest possible value of a key_len.
bool empty() const
Return true if there are no entries in the table.
Class managing a Btree table in a Glass database.
void find_entry_lt(const string &key)
Position the cursor on the highest entry with key < key.
uint4 glass_revision_number_t
The revision number of a glass database.
The GlassVersion class manages the revision files.
WritableDatabase open()
Construct a WritableDatabase object for a new, empty InMemory database.
bool next()
Advance to the next key.
bool after_end() const
Determine whether cursor is off the end of table.
Utility functions for testing files.
#define GLASS_TABLE_EXTENSION
Glass table extension.
bool read_tag(bool keep_compressed=false)
Read the tag from the table and store it in current_tag.
string current_key
Current key pointed to by cursor.
Public interfaces for the Xapian library.
string current_tag
Current tag pointed to by cursor.
#define CONST_STRLEN(S)
Returns the length of a string constant.
bool startswith(const std::string &s, char pfx)
#define required_argument
void read()
Read the version file and check it's a version we understand.
bool dir_exists(const char *path)
Test if a directory exists.
bool find_entry_ge(const string &key)
Position the cursor on the lowest entry with key >= key.
A cursor pointing to a position in a Btree table, for reading several entries in order, or finding approximate matches.
std::string get_description() const
Return a string describing this object.
void open(int flags_, const RootInfo &root_info, glass_revision_number_t rev)
Open the btree.
glass_tablesize_t get_entry_count() const
Return a count of the number of entries in the table.
Interface to Btree cursors.
static string unescape(const string &s)
static void goto_last(GlassCursor &cursor)
All exceptions thrown by Xapian are subclasses of Xapian::Error.
char hex_decode(char ch1, char ch2)
Decode a pair of ASCII hex digits.
Various handy helpers which std::string really should provide.
static void display_nicely(const string &data)
int main(int argc, char **argv)
static void show_entry(GlassCursor &cursor)
glass_revision_number_t get_revision() const