xapian-core  1.4.27
api_compact.cc
Go to the documentation of this file.
1 
4 /* Copyright (C) 2009,2010,2011,2012,2013,2015,2016,2017,2018,2019 Olly Betts
5  * Copyright (C) 2010 Richard Boulton
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 "api_compact.h"
26 
27 #include <xapian.h>
28 
29 #include "apitest.h"
30 #include "dbcheck.h"
31 #include "filetests.h"
32 #include "msvcignoreinvalidparam.h"
33 #include "str.h"
34 #include "testsuite.h"
35 #include "testutils.h"
36 
37 #include <cerrno>
38 #include <cstdlib>
39 #include <fstream>
40 
41 #include <sys/types.h>
42 #include "safesysstat.h"
43 #include "safefcntl.h"
44 #include "safeunistd.h"
45 
46 #include "unixcmds.h"
47 
48 using namespace std;
49 
50 static void
52 {
53  // Need non-const pointer for strtoul(), but data isn't modified.
54  char * p = const_cast<char *>(s.c_str());
55 
56  while (*p) {
57  bool del = (*p == '!');
58  if (del) ++p;
59  Xapian::docid first = strtoul(p, &p, 10);
60  Xapian::docid last = first;
61  if (*p == '-') {
62  last = strtoul(p + 1, &p, 10);
63  }
64  if (*p && *p != ' ') {
65  tout << p - s.c_str() << '\n';
66  FAIL_TEST("Bad sparse db spec (expected space): " << s);
67  }
68  if (first > last) {
69  FAIL_TEST("Bad sparse db spec (first > last): " << s);
70  }
71 
72  do {
73  if (del) {
74  db.delete_document(first);
75  } else {
76  Xapian::Document doc;
77  string id = str(first);
78  doc.set_data(id);
79  doc.add_term("Q" + str(first));
80  doc.add_term(string(first % 7 + 1, char((first % 26) + 'a')));
81  db.replace_document(first, doc);
82  }
83  } while (first++ < last);
84 
85  if (*p == '\0') break;
86  ++p;
87  }
88 
89  db.commit();
90 }
91 
92 static void
93 check_sparse_uid_terms(const string & path)
94 {
95  Xapian::Database db(path);
97  for (t = db.allterms_begin("Q"); t != db.allterms_end("Q"); ++t) {
98  Xapian::docid did = atoi((*t).c_str() + 1);
100  TEST_EQUAL(*p, did);
101  }
102 }
103 
104 // With multi the docids in the shards change the behaviour.
105 DEFINE_TESTCASE(compactnorenumber1, compact && !multi) {
106  string a = get_database_path("compactnorenumber1a", make_sparse_db,
107  "5-7 24 76 987 1023-1027 9999 !9999");
108  string a_uuid;
109  {
110  Xapian::Database db(a);
111  a_uuid = db.get_uuid();
112  }
113  string b = get_database_path("compactnorenumber1b", make_sparse_db,
114  "1027-1030");
115  string c = get_database_path("compactnorenumber1c", make_sparse_db,
116  "1028-1040");
117  string d = get_database_path("compactnorenumber1d", make_sparse_db,
118  "3000 999999 !999999");
119 
120  string out = get_compaction_output_path("compactnorenumber1out");
121 
122  rm_rf(out);
123  {
124  Xapian::Database db(a);
126  }
127 
129 
130  {
131  TEST(!dir_exists(out + "/donor"));
132  Xapian::Database db(out);
133  // xapian-compact should change the UUID of the database, but didn't
134  // prior to 1.0.18/1.1.4.
135  string out_uuid = db.get_uuid();
136  TEST_NOT_EQUAL(a_uuid, out_uuid);
137  TEST_EQUAL(out_uuid.size(), 36);
138  TEST_NOT_EQUAL(out_uuid, "00000000-0000-0000-0000-000000000000");
139 
140  // White box test - ensure that the donor database is removed.
141  TEST(!dir_exists(out + "/donor"));
142  }
143 
144  rm_rf(out);
145  {
146  Xapian::Database db;
150  }
152  {
153  // Check that xapian-compact is producing a consistent database. Also,
154  // regression test - xapian 1.1.4 set lastdocid to 0 in the output
155  // database.
156  Xapian::Database outdb(out);
157  dbcheck(outdb, 24, 9999);
158  }
159 
160  rm_rf(out);
161  {
162  Xapian::Database db;
167  }
169 
170  rm_rf(out);
171  {
172  Xapian::Database db;
177  }
179 
180  // Should fail.
181  rm_rf(out);
182  {
183  Xapian::Database db;
188  );
189  }
190 
191  // Should fail.
192  rm_rf(out);
193  {
194  Xapian::Database db;
199  );
200  }
201 
202  // Should fail.
203  rm_rf(out);
204  {
205  Xapian::Database db;
211  );
212  }
213 
214  // Should fail.
215  rm_rf(out);
216  {
217  Xapian::Database db;
223  );
224  }
225 
226  // Should fail.
227  rm_rf(out);
228  {
229  Xapian::Database db;
235  );
236  }
237 }
238 
239 // Test use of compact to merge two databases.
240 DEFINE_TESTCASE(compactmerge1, compact) {
241  string indbpath = get_database_path("apitest_simpledata");
242  string outdbpath = get_compaction_output_path("compactmerge1out");
243  rm_rf(outdbpath);
244 
245  bool singlefile = startswith(get_dbtype(), "singlefile_");
246  {
247  Xapian::Database db;
248  db.add_database(Xapian::Database(indbpath));
249  db.add_database(Xapian::Database(indbpath));
250  if (singlefile) {
251  db.compact(outdbpath, Xapian::DBCOMPACT_SINGLE_FILE);
252  } else {
253  db.compact(outdbpath);
254  }
255  }
256 
257  Xapian::Database indb(get_database("apitest_simpledata"));
258  Xapian::Database outdb(outdbpath);
259 
260  TEST_EQUAL(indb.get_doccount() * 2, outdb.get_doccount());
261  dbcheck(outdb, outdb.get_doccount(), outdb.get_doccount());
262 
263  if (singlefile) {
264  // Check we actually got a single file out.
265  TEST(file_exists(outdbpath));
266  TEST_EQUAL(Xapian::Database::check(outdbpath, 0, &tout), 0);
267  } else if (indb.size() > 1) {
268  // Can't check tables for a sharded DB.
269  TEST_EQUAL(Xapian::Database::check(outdbpath, 0, &tout), 0);
270  } else {
271  // Check we got a directory out, not a file.
272  TEST(dir_exists(outdbpath));
273  static const char* const suffixes[] = {
274  "", "/postlist", "/termlist.", nullptr
275  };
276  for (auto s : suffixes) {
277  string suffix;
278  if (s) {
279  suffix = s;
280  } else {
281  if (get_dbtype() == "chert") {
282  suffix = "/record.DB";
283  } else {
284  suffix = "/docdata." + get_dbtype();
285  }
286  }
287  tout.str(string());
288  tout << "Trying suffix '" << suffix << "'\n";
289  string arg = outdbpath;
290  arg += suffix;
292  }
293  }
294 }
295 
296 static void
298 {
299  int count = 10000;
300 
301  Xapian::Document doc;
302  doc.add_term("a");
303  while (count) {
304  db.add_document(doc);
305  --count;
306  }
307 
308  db.commit();
309 }
310 
311 // Test use of compact on a database which has multiple chunks for a term.
312 // This is a regression test for ticket #427
313 DEFINE_TESTCASE(compactmultichunks1, compact) {
314  string indbpath = get_database_path("compactmultichunks1in",
315  make_multichunk_db, "");
316  string outdbpath = get_compaction_output_path("compactmultichunks1out");
317  rm_rf(outdbpath);
318 
319  {
320  Xapian::Database db(indbpath);
321  db.compact(outdbpath);
322  }
323 
324  Xapian::Database indb(indbpath);
325  Xapian::Database outdb(outdbpath);
326 
327  TEST_EQUAL(indb.get_doccount(), outdb.get_doccount());
328  dbcheck(outdb, outdb.get_doccount(), outdb.get_doccount());
329 }
330 
331 // Test compacting from a stub database directory.
332 DEFINE_TESTCASE(compactstub1, compact) {
333  const char * stubpath = ".stub/compactstub1";
334  const char * stubpathfile = ".stub/compactstub1/XAPIANDB";
335  mkdir(".stub", 0755);
336  mkdir(stubpath, 0755);
337  ofstream stub(stubpathfile);
338  TEST(stub.is_open());
339  stub << "auto ../../" << get_database_path("apitest_simpledata") << '\n';
340  stub << "auto ../../" << get_database_path("apitest_simpledata2") << '\n';
341  stub.close();
342 
343  string outdbpath = get_compaction_output_path("compactstub1out");
344  rm_rf(outdbpath);
345 
346  {
347  Xapian::Database db(stubpath);
348  db.compact(outdbpath);
349  }
350 
351  Xapian::Database indb(stubpath);
352  Xapian::Database outdb(outdbpath);
353 
354  TEST_EQUAL(indb.get_doccount(), outdb.get_doccount());
355  dbcheck(outdb, outdb.get_doccount(), outdb.get_doccount());
356 }
357 
358 // Test compacting from a stub database file.
359 DEFINE_TESTCASE(compactstub2, compact) {
360  const char * stubpath = ".stub/compactstub2";
361  mkdir(".stub", 0755);
362  ofstream stub(stubpath);
363  TEST(stub.is_open());
364  stub << "auto ../" << get_database_path("apitest_simpledata") << '\n';
365  stub << "auto ../" << get_database_path("apitest_simpledata2") << '\n';
366  stub.close();
367 
368  string outdbpath = get_compaction_output_path("compactstub2out");
369  rm_rf(outdbpath);
370 
371  {
372  Xapian::Database db(stubpath);
373  db.compact(outdbpath);
374  }
375 
376  Xapian::Database indb(stubpath);
377  Xapian::Database outdb(outdbpath);
378 
379  TEST_EQUAL(indb.get_doccount(), outdb.get_doccount());
380  dbcheck(outdb, outdb.get_doccount(), outdb.get_doccount());
381 }
382 
383 // Test compacting a stub database file to itself.
384 DEFINE_TESTCASE(compactstub3, compact) {
385  const char * stubpath = ".stub/compactstub3";
386  mkdir(".stub", 0755);
387  ofstream stub(stubpath);
388  TEST(stub.is_open());
389  stub << "auto ../" << get_database_path("apitest_simpledata") << '\n';
390  stub << "auto ../" << get_database_path("apitest_simpledata2") << '\n';
391  stub.close();
392 
393  Xapian::doccount in_docs;
394  {
395  Xapian::Database indb(stubpath);
396  in_docs = indb.get_doccount();
397  indb.compact(stubpath);
398  }
399 
400  Xapian::Database outdb(stubpath);
401 
402  TEST_EQUAL(in_docs, outdb.get_doccount());
403  dbcheck(outdb, outdb.get_doccount(), outdb.get_doccount());
404 }
405 
406 // Test compacting a stub database directory to itself.
407 DEFINE_TESTCASE(compactstub4, compact) {
408  const char * stubpath = ".stub/compactstub4";
409  const char * stubpathfile = ".stub/compactstub4/XAPIANDB";
410  mkdir(".stub", 0755);
411  mkdir(stubpath, 0755);
412  ofstream stub(stubpathfile);
413  TEST(stub.is_open());
414  stub << "auto ../../" << get_database_path("apitest_simpledata") << '\n';
415  stub << "auto ../../" << get_database_path("apitest_simpledata2") << '\n';
416  stub.close();
417 
418  Xapian::doccount in_docs;
419  {
420  Xapian::Database indb(stubpath);
421  in_docs = indb.get_doccount();
422  indb.compact(stubpath);
423  }
424 
425  Xapian::Database outdb(stubpath);
426 
427  TEST_EQUAL(in_docs, outdb.get_doccount());
428  dbcheck(outdb, outdb.get_doccount(), outdb.get_doccount());
429 }
430 
431 static void
433 {
434  Xapian::Document doc;
435  doc.add_term("foo");
436  db.add_document(doc);
437  db.add_spelling("foo");
438  db.add_synonym("bar", "pub");
439  db.add_synonym("foobar", "foo");
440 
441  db.commit();
442 }
443 
444 static void
446 {
447  Xapian::Document doc;
448  doc.add_term("foo");
449  db.add_document(doc);
450 
451  db.commit();
452 }
453 
454 DEFINE_TESTCASE(compactmissingtables1, compact) {
455  string a = get_database_path("compactmissingtables1a",
457  string b = get_database_path("compactmissingtables1b",
459 
460  string out = get_compaction_output_path("compactmissingtables1out");
461  rm_rf(out);
462 
463  {
464  Xapian::Database db;
467  db.compact(out);
468  }
469 
470  {
471  Xapian::Database db(out);
474  // FIXME: arrange for input b to not have a termlist table.
475 // TEST_EXCEPTION(Xapian::FeatureUnavailableError, db.termlist_begin(1));
476  }
477 }
478 
479 static void
481 {
482  Xapian::Document doc;
483  doc.add_term("bar");
484  db.add_document(doc);
485  db.add_spelling("bar");
486  db.add_synonym("bar", "baa");
487  db.add_synonym("barfoo", "barbar");
488  db.add_synonym("foofoo", "barfoo");
489 
490  db.commit();
491 }
492 
494 DEFINE_TESTCASE(compactmergesynonym1, compact) {
495  string a = get_database_path("compactmergesynonym1a",
497  string b = get_database_path("compactmergesynonym1b",
499 
500  string out = get_compaction_output_path("compactmergesynonym1out");
501  rm_rf(out);
502 
503  {
504  Xapian::Database db;
507  db.compact(out);
508  }
509 
510  {
511  Xapian::Database db(out);
512 
514  TEST_NOT_EQUAL(i, db.spellings_end());
515  TEST_EQUAL(*i, "bar");
516  ++i;
517  TEST_NOT_EQUAL(i, db.spellings_end());
518  TEST_EQUAL(*i, "foo");
519  ++i;
520  TEST_EQUAL(i, db.spellings_end());
521 
522  i = db.synonym_keys_begin();
524  TEST_EQUAL(*i, "bar");
525  ++i;
527  TEST_EQUAL(*i, "barfoo");
528  ++i;
530  TEST_EQUAL(*i, "foobar");
531  ++i;
533  TEST_EQUAL(*i, "foofoo");
534  ++i;
535  TEST_EQUAL(i, db.synonym_keys_end());
536  }
537 }
538 
539 DEFINE_TESTCASE(compactempty1, compact) {
540  string empty_dbpath = get_database_path(string());
541  string outdbpath = get_compaction_output_path("compactempty1out");
542  rm_rf(outdbpath);
543 
544  {
545  // Compacting an empty database tried to divide by zero in 1.3.0.
546  Xapian::Database db;
547  db.add_database(Xapian::Database(empty_dbpath));
548  db.compact(outdbpath);
549 
550  Xapian::Database outdb(outdbpath);
551  TEST_EQUAL(outdb.get_doccount(), 0);
552  dbcheck(outdb, 0, 0);
553  }
554 
555  {
556  // Check compacting two empty databases together.
557  Xapian::Database db;
558  db.add_database(Xapian::Database(empty_dbpath));
559  db.add_database(Xapian::Database(empty_dbpath));
560  db.compact(outdbpath);
561 
562  Xapian::Database outdb(outdbpath);
563  TEST_EQUAL(outdb.get_doccount(), 0);
564  dbcheck(outdb, 0, 0);
565  }
566 }
567 
568 DEFINE_TESTCASE(compactmultipass1, compact) {
569  string outdbpath = get_compaction_output_path("compactmultipass1");
570  rm_rf(outdbpath);
571 
572  string a = get_database_path("compactnorenumber1a", make_sparse_db,
573  "5-7 24 76 987 1023-1027 9999 !9999");
574  string b = get_database_path("compactnorenumber1b", make_sparse_db,
575  "1027-1030");
576  string c = get_database_path("compactnorenumber1c", make_sparse_db,
577  "1028-1040");
578  string d = get_database_path("compactnorenumber1d", make_sparse_db,
579  "3000 999999 !999999");
580 
581  {
582  Xapian::Database db;
587  db.compact(outdbpath, Xapian::DBCOMPACT_MULTIPASS);
588  }
589 
590  Xapian::Database outdb(outdbpath);
591  dbcheck(outdb, 29, 1041);
592 }
593 
594 // Test compacting to an fd.
595 // Chert doesn't support single file databases.
596 DEFINE_TESTCASE(compacttofd1, compact && !chert) {
597  Xapian::Database indb(get_database("apitest_simpledata"));
598  string outdbpath = get_compaction_output_path("compacttofd1out");
599  rm_rf(outdbpath);
600 
601  int fd = open(outdbpath.c_str(), O_CREAT|O_RDWR|O_BINARY, 0666);
602  TEST(fd != -1);
603  indb.compact(fd);
604 
605  // Confirm that the fd was closed by Xapian. Set errno first to workaround
606  // a bug in Wine's msvcrt.dll which fails to set errno in this case:
607  // https://bugs.winehq.org/show_bug.cgi?id=43902
608  errno = EBADF;
609  {
610  MSVCIgnoreInvalidParameter invalid_fd_in_close_is_expected;
611  TEST(close(fd) == -1);
612  TEST_EQUAL(errno, EBADF);
613  }
614 
615  Xapian::Database outdb(outdbpath);
616 
617  TEST_EQUAL(indb.get_doccount(), outdb.get_doccount());
618  dbcheck(outdb, outdb.get_doccount(), outdb.get_doccount());
619 }
620 
621 // Test compacting to an fd at at offset.
622 // Chert doesn't support single file databases.
623 DEFINE_TESTCASE(compacttofd2, compact && !chert) {
624  Xapian::Database indb(get_database("apitest_simpledata"));
625  string outdbpath = get_compaction_output_path("compacttofd2out");
626  rm_rf(outdbpath);
627 
628  int fd = open(outdbpath.c_str(), O_CREAT|O_RDWR|O_BINARY, 0666);
629  TEST(fd != -1);
630  TEST(lseek(fd, 8192, SEEK_SET) == 8192);
631  indb.compact(fd);
632 
633  // Confirm that the fd was closed by Xapian. Set errno first to workaround
634  // a bug in Wine's msvcrt.dll which fails to set errno in this case:
635  // https://bugs.winehq.org/show_bug.cgi?id=43902
636  errno = EBADF;
637  {
638  MSVCIgnoreInvalidParameter invalid_fd_in_close_is_expected;
639  TEST(close(fd) == -1);
640  TEST_EQUAL(errno, EBADF);
641  }
642 
643  fd = open(outdbpath.c_str(), O_RDONLY|O_BINARY);
644  TEST(fd != -1);
645 
646  // Test that the database wasn't just written to the start of the file.
647  char buf[8192];
648  size_t n = sizeof(buf);
649  while (n) {
650  ssize_t c = read(fd, buf, n);
651  TEST(c > 0);
652  for (const char * p = buf; p != buf + c; ++p) {
653  TEST(*p == 0);
654  }
655  n -= c;
656  }
657 
658  TEST(lseek(fd, 8192, SEEK_SET) == 8192);
659  Xapian::Database outdb(fd);
660 
661  TEST_EQUAL(indb.get_doccount(), outdb.get_doccount());
662  dbcheck(outdb, outdb.get_doccount(), outdb.get_doccount());
663 }
664 
665 // Regression test for bug fixed in 1.3.5. If you compact a WritableDatabase
666 // with uncommitted changes, you get an inconsistent output.
667 //
668 // Chert doesn't support single file databases.
669 DEFINE_TESTCASE(compactsingle1, compact && writable && !chert) {
671  Xapian::Document doc;
672  doc.add_term("foo");
673  doc.add_term("bar");
674  doc.add_term("baz");
675  db.add_document(doc);
676  // Include a zero-length document as a regression test for a
677  // Database::check() bug fixed in 1.4.7 (and introduced in 1.4.6). Test it
678  // here so we also have test coverage for compaction for such a document.
679  Xapian::Document doc2;
680  doc2.add_boolean_term("Kfoo");
681  db.add_document(doc2);
682  // Also test a completely empty document.
684 
685  string output = get_compaction_output_path("compactsingle1-out");
686  // In 1.3.4, we would hang if the output file already existed, so check
687  // that works.
688  touch(output);
689 
692 
693  // Check the file wasn't removed by the failed attempt.
694  TEST(file_exists(output));
695 
696  db.commit();
698  db.close();
699 
700  TEST_EQUAL(Xapian::Database::check(output, 0, &tout), 0);
701 
702  TEST_EQUAL(Xapian::Database(output).get_doccount(), 3);
703 }
704 
705 // Regression test for bug fixed in 1.4.6. Same as above, except not with
706 // a single file database!
707 DEFINE_TESTCASE(compact1, compact && writable) {
709  Xapian::Document doc;
710  doc.add_term("foo");
711  doc.add_term("bar");
712  doc.add_term("baz");
713  db.add_document(doc);
714  // Include a zero-length document as a regression test for a
715  // Database::check() bug fixed in 1.4.7 (and introduced in 1.4.6). Test it
716  // here so we also have test coverage for compaction for such a document.
717  Xapian::Document doc2;
718  doc2.add_boolean_term("Kfoo");
719  db.add_document(doc2);
720  // Also test a completely empty document.
722 
723  string output = get_compaction_output_path("compact1-out");
724  rm_rf(output);
725 
727  db.compact(output));
728 
729  db.commit();
730  db.compact(output);
731  db.close();
732 
733  TEST_EQUAL(Xapian::Database::check(output, 0, &tout), 0);
734 
735  TEST_EQUAL(Xapian::Database(output).get_doccount(), 3);
736 }
int close(FD &fd)
Definition: fd.h:63
Xapian::docid add_document(const Xapian::Document &document)
Add a new document to the database.
Definition: omdatabase.cc:902
static size_t check(const std::string &path, int opts=0, std::ostream *out=NULL)
Check the integrity of a database or database table.
Definition: database.h:564
void dbcheck(const Xapian::Database &db, Xapian::doccount expected_doccount, Xapian::docid expected_lastdocid)
Check consistency of database and statistics.
Definition: dbcheck.cc:126
#define TEST(a)
Test a condition, without an additional explanation for failure.
Definition: testsuite.h:275
This class is used to access a database, or a group of databases.
Definition: database.h:68
Work around MSVC&#39;s unhelpful non-standard invalid parameter handling.
test database contents and consistency.
static void make_missing_tables(Xapian::WritableDatabase &db, const string &)
Definition: api_compact.cc:445
InvalidOperationError indicates the API was used in an invalid way.
Definition: error.h:283
TermIterator allterms_end(const std::string &=std::string()) const
Corresponding end iterator to allterms_begin(prefix).
Definition: database.h:269
Xapian::WritableDatabase get_writable_database(const string &dbname)
Definition: apitest.cc:87
#define O_BINARY
Definition: safefcntl.h:81
a generic test suite engine
C++ function versions of useful Unix commands.
WritableDatabase open()
Construct a WritableDatabase object for a new, empty InMemory database.
Definition: dbfactory.h:104
STL namespace.
Convert types to std::string.
Utility functions for testing files.
void replace_document(Xapian::docid did, const Xapian::Document &document)
Replace a given document in the database.
Definition: omdatabase.cc:952
const int DBCOMPACT_NO_RENUMBER
Use the same document ids in the output as in the input(s).
Definition: constants.h:256
Xapian::doccount get_doccount() const
Get the number of documents in the database.
Definition: omdatabase.cc:267
include <sys/stat.h> with portability enhancements
test functionality of the Xapian API
void rm_rf(const string &filename)
Remove a directory and contents, just like the Unix "rm -rf" command.
Definition: unixcmds.cc:111
static void make_all_tables2(Xapian::WritableDatabase &db, const string &)
Definition: api_compact.cc:480
Class for iterating over a list of terms.
Definition: termiterator.h:41
Class for iterating over a list of terms.
#define TEST_NOT_EQUAL(a, b)
Test for non-equality of two things.
Definition: testsuite.h:305
string get_database_path(const string &dbname)
Definition: apitest.cc:72
This class provides read/write access to a database.
Definition: database.h:789
Xapian::TermIterator spellings_begin() const
An iterator which returns all the spelling correction targets.
Definition: omdatabase.cc:704
static void make_all_tables(Xapian::WritableDatabase &db, const string &)
Definition: api_compact.cc:432
std::ostringstream tout
The debug printing stream.
Definition: testsuite.cc:104
Public interfaces for the Xapian library.
Xapian::TermIterator synonym_keys_begin(const std::string &prefix=std::string()) const
An iterator which returns all terms which have synonyms.
Definition: omdatabase.cc:740
static void make_multichunk_db(Xapian::WritableDatabase &db, const string &)
Definition: api_compact.cc:297
void delete_document(Xapian::docid did)
Delete a document from the database.
Definition: omdatabase.cc:925
#define TEST_EXCEPTION(TYPE, CODE)
Check that CODE throws exactly Xapian exception TYPE.
Definition: testutils.h:109
Xapian::TermIterator synonym_keys_end(const std::string &=std::string()) const
Corresponding end iterator to synonym_keys_begin(prefix).
Definition: database.h:459
std::string get_dbtype()
Definition: apitest.cc:42
string str(int value)
Convert int to std::string.
Definition: str.cc:90
void commit()
Commit any pending modifications made to the database.
Definition: omdatabase.cc:857
bool startswith(const std::string &s, char pfx)
Definition: stringutils.h:51
TermIterator allterms_begin(const std::string &prefix=std::string()) const
An iterator which runs across all terms with a given prefix.
Definition: omdatabase.cc:223
void compact(const std::string &output, unsigned flags=0, int block_size=0)
Produce a compact version of this database.
Definition: database.h:627
bool dir_exists(const char *path)
Test if a directory exists.
Definition: filetests.h:136
void add_database(const Database &database)
Add an existing database (or group of databases) to those accessed by this object.
Definition: omdatabase.cc:148
DEFINE_TESTCASE(compactnorenumber1, compact &&!multi)
Definition: api_compact.cc:105
size_t size() const
Return number of shards in this Database object.
Definition: database.h:93
std::string get_compaction_output_path(const std::string &name)
Definition: apitest.cc:105
#define FAIL_TEST(MSG)
Fail the current testcase with message MSG.
Definition: testsuite.h:68
Xapian::Database get_database(const string &dbname)
Definition: apitest.cc:48
unsigned XAPIAN_DOCID_BASE_TYPE doccount
A count of documents.
Definition: types.h:38
Xapian-specific test helper functions and macros.
const int DBCOMPACT_MULTIPASS
If merging more than 3 databases, merge the postlists in multiple passes.
Definition: constants.h:262
<unistd.h>, but with compat.
void add_boolean_term(const std::string &term)
Add a boolean filter term to the document.
Definition: document.h:192
Xapian::TermIterator spellings_end() const
Corresponding end iterator to spellings_begin().
Definition: database.h:436
void add_synonym(const std::string &term, const std::string &synonym) const
Add a synonym for a term.
Definition: omdatabase.cc:1028
unsigned XAPIAN_DOCID_BASE_TYPE docid
A unique identifier for a document.
Definition: types.h:52
static void check_sparse_uid_terms(const string &path)
Definition: api_compact.cc:93
#define TEST_EQUAL(a, b)
Test for equality of two things.
Definition: testsuite.h:278
const int DBCOMPACT_SINGLE_FILE
Produce a single-file database.
Definition: constants.h:268
void set_data(const std::string &data)
Set data stored in the document.
Definition: omdocument.cc:78
bool file_exists(const char *path)
Test if a file exists.
Definition: filetests.h:39
virtual void close()
Close the database.
Definition: omdatabase.cc:138
include <fcntl.h>, but working around broken platforms.
A handle representing a document in a Xapian database.
Definition: document.h:61
std::string get_uuid() const
Get a UUID for the database.
Definition: omdatabase.cc:776
void add_spelling(const std::string &word, Xapian::termcount freqinc=1) const
Add a word to the spelling dictionary.
Definition: omdatabase.cc:1004
PostingIterator postlist_begin(const std::string &tname) const
An iterator pointing to the start of the postlist for a given term.
Definition: omdatabase.cc:162
void touch(const string &filename)
Touch a file, just like the Unix "touch" command.
Definition: unixcmds.cc:155
void add_term(const std::string &tname, Xapian::termcount wdfinc=1)
Add a term to the document, without positional information.
Definition: omdocument.cc:140
static void make_sparse_db(Xapian::WritableDatabase &db, const string &s)
Definition: api_compact.cc:51