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