39 #define PROG_NAME "xapian-inspect" 40 #define PROG_DESC "Inspect the contents of a glass table for development or debugging" 48 cout <<
"Usage: " PROG_NAME " [OPTIONS] TABLE\n" 49 " " PROG_NAME " [OPTIONS] -t TABLE DB\n\n" 51 " -t, --table=TABLE which table to inspect\n" 52 " --help display this help and exit\n" 53 " --version output version information and exit\n";
59 for (
unsigned char ch : data) {
60 if (ch < 32 || ch >= 127) {
62 case '\n': cout <<
"\\n";
break;
63 case '\r': cout <<
"\\r";
break;
64 case '\t': cout <<
"\\t";
break;
67 <<
"0123456789abcdef"[ch >> 4]
68 <<
"0123456789abcdef"[ch & 0x0f];
71 }
else if (ch ==
'\\') {
83 auto bslash = s.find(
'\\');
84 if (bslash == string::npos)
86 string r(s, 0, bslash);
87 for (
auto i = s.begin() + bslash; i != s.end(); ++i) {
131 cout <<
"Bad escaping in specified key value, assuming literal\n";
138 cout <<
"Commands:\n" 139 "next : Next entry (alias 'n' or '')\n" 140 "prev : Previous entry (alias 'p')\n" 141 "first : First entry (alias 'f')\n" 142 "last : Last entry (alias 'l')\n" 143 "goto K : Goto first entry with key >= K (alias 'g')\n" 144 "until K: Display entries until key >= K (alias 'u')\n" 145 "until : Display entries until end (alias 'u')\n" 146 "count K: Count entries until key >= K (alias 'c')\n" 147 "count : Count entries until end (alias 'c')\n" 148 "open T : Open table T instead (alias 'o') - e.g. open postlist\n" 149 "keys : Toggle showing keys (default: true) (alias 'k')\n" 150 "tags : Toggle showing tags (default: true) (alias 't')\n" 151 "help : Show this (alias 'h' or '?')\n" 152 "quit : Quit this utility (alias 'q')\n";
159 cout <<
"After end\n";
163 cout <<
"Before start\n";
183 cout <<
"At end already.\n";
187 if (!target.empty()) {
191 cout <<
"Already after specified key.\n";
193 cout <<
"Already at specified key.\n";
199 while (cursor.
next()) {
208 cout <<
"No exact match, stopping at entry after, " 209 "having advanced by " << count <<
" entries.\n";
213 cout <<
"Advanced by " << count <<
" entries.\n";
218 cout <<
"Reached end, having advanced by " << count <<
" entries.\n";
233 static const struct option long_opts[] = {
267 string db_path(argv[
optind]);
269 if (arg_is_directory && table_name.empty()) {
271 <<
": You need to specify a table name to inspect with " 275 int single_file_fd = -1;
276 if (table_name.empty()) {
281 db_path.resize(db_path.size() -
283 }
else if (
endswith(db_path,
'.')) {
284 db_path.resize(db_path.size() - 1);
286 size_t slash = db_path.find_last_of(
DIR_SEPS);
289 table_name.assign(db_path, slash + 1, string::npos);
290 if (slash != string::npos) {
291 db_path.resize(slash);
295 }
else if (!arg_is_directory) {
296 single_file_fd =
open(db_path.c_str(), O_RDONLY |
O_BINARY);
297 if (single_file_fd < 0) {
298 cerr << argv[0] <<
": Couldn't open file '" << db_path <<
"'" 305 if (single_file_fd < 0) {
318 open_different_table:
321 if (table_name ==
"docdata") {
323 }
else if (table_name ==
"spelling") {
325 }
else if (table_name ==
"synonym") {
327 }
else if (table_name ==
"termlist") {
329 }
else if (table_name ==
"position") {
331 }
else if (table_name ==
"postlist") {
334 cerr <<
"Unknown table: '" << table_name <<
"'\n";
339 if (single_file_fd < 0) {
340 string table_path = db_path;
342 table_path += table_name;
344 table_ptr =
new GlassTable(
"", table_path,
true);
347 table_ptr =
new GlassTable(
"", single_file_fd, offset,
true);
353 cout <<
"No entries!\n";
365 cout <<
"? " << flush;
369 if (cin.eof())
break;
372 input.resize(input.size() - 1);
374 if (input.empty() || input ==
"n" || input ==
"next") {
376 cout <<
"At end already.\n";
381 }
else if (input ==
"p" || input ==
"prev") {
383 cout <<
"Before start already.\n";
400 }
else if (input ==
"u" || input ==
"until") {
409 }
else if (input ==
"c" || input ==
"count") {
412 }
else if (input ==
"f" || input ==
"first") {
416 }
else if (input ==
"l" || input ==
"last") {
421 cout <<
"No exact match, going to entry after.\n";
426 cout <<
"No exact match, going to entry after.\n";
430 size_t trim = (input[1] ==
' ' ? 2 : 5);
431 table_name.assign(input, trim, string::npos);
433 table_name.resize(table_name.size() -
436 table_name.resize(table_name.size() - 1);
437 goto open_different_table;
438 }
else if (input ==
"t" || input ==
"tags") {
440 cout <<
"Showing tags: " << boolalpha <<
tags <<
'\n';
441 }
else if (input ==
"k" || input ==
"keys") {
443 cout <<
"Showing keys: " << boolalpha <<
keys <<
'\n';
444 }
else if (input ==
"q" || input ==
"quit") {
446 }
else if (input ==
"h" || input ==
"help" || input ==
"?") {
450 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