00001
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include <config.h>
00022
00023 #include <xapian.h>
00024
00025 #include <iomanip>
00026 #include <iostream>
00027
00028 #include <cmath>
00029 #include <cstdlib>
00030 #include <cstring>
00031
00032 using namespace std;
00033
00034 #define PROG_NAME "copydatabase"
00035 #define PROG_DESC "Perform a document-by-document copy of one or more Xapian databases"
00036
00037 static void
00038 show_usage(int rc)
00039 {
00040 cout << "Usage: "PROG_NAME" SOURCE_DATABASE... DESTINATION_DATABASE\n\n"
00041 "Options:\n"
00042 " --no-renumber Preserve the numbering of document ids (useful if you have\n"
00043 " external references to them, or have set them to match\n"
00044 " unique ids from an external source). If multiple source\n"
00045 " databases are specified and the same docid occurs in more\n"
00046 " one, the last occurrence will be the one which ends up in\n"
00047 " the destination database.\n"
00048 " --help display this help and exit\n"
00049 " --version output version information and exit" << endl;
00050 exit(rc);
00051 }
00052
00053 int
00054 main(int argc, char **argv)
00055 try {
00056 bool renumber = true;
00057 if (argc > 1 && argv[1][0] == '-') {
00058 if (strcmp(argv[1], "--help") == 0) {
00059 cout << PROG_NAME" - "PROG_DESC"\n\n";
00060 show_usage(0);
00061 }
00062 if (strcmp(argv[1], "--version") == 0) {
00063 cout << PROG_NAME" - "PACKAGE_STRING << endl;
00064 exit(0);
00065 }
00066 if (strcmp(argv[1], "--no-renumber") == 0) {
00067 renumber = false;
00068 argv[1] = argv[0];
00069 ++argv;
00070 --argc;
00071 }
00072 }
00073
00074
00075
00076 if (argc < 3) show_usage(1);
00077
00078
00079
00080
00081 const char *dest = argv[argc - 1];
00082 Xapian::WritableDatabase db_out(dest, Xapian::DB_CREATE);
00083
00084 for (int i = 1; i < argc - 1; ++i) {
00085 char * src = argv[i];
00086 if (*src) {
00087
00088 char & ch = src[strlen(src) - 1];
00089 if (ch == '/' || ch == '\\') ch = '\0';
00090 }
00091
00092
00093 Xapian::Database db_in(src);
00094
00095
00096 const char * leaf = strrchr(src, '/');
00097 #if defined __WIN32__ || defined __EMX__
00098 if (!leaf) leaf = strrchr(src, '\\');
00099 #endif
00100 if (leaf) ++leaf; else leaf = src;
00101
00102
00103 Xapian::doccount dbsize = db_in.get_doccount();
00104 if (dbsize == 0) {
00105 cout << leaf << ": empty!" << endl;
00106 } else {
00107
00108 int width = static_cast<int>(log10(double(dbsize))) + 1;
00109
00110 Xapian::doccount c = 0;
00111 Xapian::PostingIterator it = db_in.postlist_begin(string());
00112 while (it != db_in.postlist_end(string())) {
00113 Xapian::docid did = *it;
00114 if (renumber) {
00115 db_out.add_document(db_in.get_document(did));
00116 } else {
00117 db_out.replace_document(did, db_in.get_document(did));
00118 }
00119
00120
00121
00122
00123
00124 ++c;
00125 if (c <= 10 || (dbsize - c) % 13 == 0) {
00126 cout << '\r' << leaf << ": ";
00127 cout << setw(width) << c << '/' << dbsize << flush;
00128 }
00129
00130 ++it;
00131 }
00132
00133 cout << endl;
00134 }
00135
00136 cout << "Copying spelling data..." << flush;
00137 Xapian::TermIterator spellword = db_in.spellings_begin();
00138 while (spellword != db_in.spellings_end()) {
00139 db_out.add_spelling(*spellword, spellword.get_termfreq());
00140 ++spellword;
00141 }
00142 cout << " done." << endl;
00143
00144 cout << "Copying synonym data..." << flush;
00145 Xapian::TermIterator synkey = db_in.synonym_keys_begin();
00146 while (synkey != db_in.synonym_keys_end()) {
00147 string key = *synkey;
00148 Xapian::TermIterator syn = db_in.synonyms_begin(key);
00149 while (syn != db_in.synonyms_end(key)) {
00150 db_out.add_synonym(key, *syn);
00151 ++syn;
00152 }
00153 ++synkey;
00154 }
00155 cout << " done." << endl;
00156
00157 cout << "Copying user metadata..." << flush;
00158 Xapian::TermIterator metakey = db_in.metadata_keys_begin();
00159 while (metakey != db_in.metadata_keys_end()) {
00160 string key = *metakey;
00161 db_out.set_metadata(key, db_in.get_metadata(key));
00162 ++metakey;
00163 }
00164 cout << " done." << endl;
00165 }
00166
00167 cout << "Committing..." << flush;
00168
00169 db_out.commit();
00170 cout << " done." << endl;
00171 } catch (const Xapian::Error & e) {
00172 cerr << '\n' << argv[0] << ": " << e.get_description() << endl;
00173 exit(1);
00174 }