xapian-core  2.0.0
api_closedb.cc
Go to the documentation of this file.
1 
4 /* Copyright 2008,2009 Lemur Consulting Ltd
5  * Copyright 2009,2012,2015,2023 Olly Betts
6  *
7  * This program is free software; you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation; either version 2 of the License, or
10  * (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_closedb.h"
25 
26 #include <xapian.h>
27 
28 #include "safeunistd.h"
29 
30 #include "apitest.h"
31 #include "testutils.h"
32 
33 using namespace std;
34 
35 #define COUNT_EXCEPTION(CODE, EXCEPTION) \
36  try { \
37  CODE; \
38  } catch (const Xapian::EXCEPTION&) { \
39  ++exception_count; \
40  }
41 
42 #define COUNT_CLOSED(CODE) COUNT_EXCEPTION(CODE, DatabaseClosedError)
43 
44 // Iterators used by closedb1.
58 
59  void setup(Xapian::Database db_) {
60  db = db_;
61 
62  // Set up the iterators for the test.
63  pl1 = db.postlist_begin("paragraph");
64  pl2 = db.postlist_begin("this");
65  ++pl2;
66  pl1end = db.postlist_end("paragraph");
67  pl2end = db.postlist_end("this");
68  tl1 = db.termlist_begin(1);
69  tlend = db.termlist_end(1);
70  atl1 = db.allterms_begin("t");
71  atlend = db.allterms_end("t");
72  pil1 = db.positionlist_begin(1, "paragraph");
73  pilend = db.positionlist_end(1, "paragraph");
74  }
75 
76  int perform() {
77  int exception_count = 0;
78 
79  // Getting a document may throw.
81  doc1 = db.get_document(1);
82  // Only do these if get_document() succeeded.
83  COUNT_CLOSED(TEST_EQUAL(doc1.get_data().substr(0, 33),
84  "This is a test document used with"));
86  );
87 
88  // Causing the database to access its files raises the "database
89  // closed" error.
90  COUNT_CLOSED(db.postlist_begin("paragraph"));
93  COUNT_CLOSED(db.positionlist_begin(1, "paragraph"));
96  COUNT_CLOSED(db.get_termfreq("paragraph"));
97  COUNT_CLOSED(db.get_collection_freq("paragraph"));
98  COUNT_CLOSED(db.term_exists("paragraph"));
105 
106  // Reopen raises the "database closed" error.
107  COUNT_CLOSED(db.reopen());
108 
109  TEST_NOT_EQUAL(pl1, pl1end);
110  TEST_NOT_EQUAL(pl2, pl2end);
111  TEST_NOT_EQUAL(tl1, tlend);
112  TEST_NOT_EQUAL(atl1, atlend);
113  TEST_NOT_EQUAL(pil1, pilend);
114 
115  COUNT_CLOSED(db.postlist_begin("paragraph"));
116 
117  COUNT_CLOSED(TEST_EQUAL(*pl1, 1));
120 
121  COUNT_CLOSED(TEST_EQUAL(*pl2, 2));
124 
125  COUNT_CLOSED(TEST_EQUAL(*tl1, "a"));
126  COUNT_CLOSED(TEST_EQUAL(tl1.get_wdf(), 2));
128 
129  COUNT_CLOSED(TEST_EQUAL(*atl1, "test"));
131 
132  COUNT_CLOSED(TEST_EQUAL(*pil1, 12));
133 
134  // Advancing the iterator may or may not raise an error, but if it
135  // doesn't it must return the correct answers.
136  COUNT_CLOSED(
137  ++pl1;
138  COUNT_CLOSED(TEST_EQUAL(*pl1, 2));
141  );
142 
143  COUNT_CLOSED(
144  ++pl2;
145  COUNT_CLOSED(TEST_EQUAL(*pl2, 3));
148  );
149 
150  COUNT_CLOSED(
151  ++tl1;
152  COUNT_CLOSED(TEST_EQUAL(*tl1, "api"));
153  COUNT_CLOSED(TEST_EQUAL(tl1.get_wdf(), 1));
155  );
156 
157  COUNT_CLOSED(
158  ++atl1;
159  COUNT_CLOSED(TEST_EQUAL(*atl1, "that"));
161  );
162 
163  COUNT_CLOSED(
164  ++pil1;
165  COUNT_CLOSED(TEST_EQUAL(*pil1, 28));
166  );
167 
168  return exception_count;
169  }
170 };
171 
172 // Test for closing a database
173 DEFINE_TESTCASE(closedb1, backend) {
174  Xapian::Database db(get_database("apitest_simpledata"));
175  closedb1_iterators iters;
176 
177  // Run the test, checking that we get no "closed" exceptions.
178  iters.setup(db);
179  int exception_count = iters.perform();
180  TEST_EQUAL(exception_count, 0);
181 
182  // Setup for the next test.
183  iters.setup(db);
184 
185  // Close the database.
186  db.close();
187 
188  // Dup stdout to the fds which the database was using, to try to catch
189  // issues with lingering references to closed fds (regression test for
190  // early development versions of honey).
191  vector<int> fds;
192  for (int i = 0; i != 6; ++i) {
193  fds.push_back(dup(1));
194  }
195 
196  // Reopening a closed database should always raise DatabaseClosedError.
198 
199  // Run the test again, checking that we get some "closed" exceptions.
200  exception_count = iters.perform();
201  TEST_NOT_EQUAL(exception_count, 0);
202 
203  // get_description() shouldn't throw an exception. Actually do something
204  // with the description, in case this method is marked as "pure" in the
205  // future.
206  TEST(!db.get_description().empty());
207 
208  // Calling close repeatedly is okay.
209  db.close();
210 
211  for (int fd : fds) {
212  close(fd);
213  }
214 }
215 
216 // Test closing a writable database, and that it drops the lock.
217 DEFINE_TESTCASE(closedb2, writable && path) {
218  Xapian::WritableDatabase dbw1(get_named_writable_database("apitest_closedb2"));
221  Xapian::DB_OPEN));
222  dbw1.close();
223  Xapian::WritableDatabase dbw2 = get_named_writable_database("apitest_closedb2");
225  dbw1.postlist_begin("paragraph"));
226  TEST_EQUAL(dbw2.postlist_begin("paragraph"), dbw2.postlist_end("paragraph"));
227 }
228 
230 DEFINE_TESTCASE(closedb3, backend) {
231  Xapian::Database db(get_database("etext"));
232  const string & uuid = db.get_uuid();
233  db.close();
234  try {
235  TEST_EQUAL(db.get_uuid(), uuid);
236  } catch (const Xapian::DatabaseClosedError &) {
237  }
238  try {
239  TEST(db.has_positions());
240  } catch (const Xapian::DatabaseClosedError &) {
241  }
242  try {
243  TEST_EQUAL(db.get_doccount(), 566);
244  } catch (const Xapian::DatabaseClosedError &) {
245  }
246  try {
247  TEST_EQUAL(db.get_lastdocid(), 566);
248  } catch (const Xapian::DatabaseClosedError &) {
249  }
250  try {
252  } catch (const Xapian::DatabaseClosedError &) {
253  }
254  try {
256  } catch (const Xapian::DatabaseClosedError &) {
257  }
258  try {
259  TEST(db.get_wdf_upper_bound("king"));
260  } catch (const Xapian::DatabaseClosedError &) {
261  }
262  try {
263  // For non-remote databases, keep_alive() is a no-op anyway.
264  db.keep_alive();
265  } catch (const Xapian::DatabaseClosedError &) {
266  }
267 }
268 
270 DEFINE_TESTCASE(closedb4, writable && !inmemory) {
273  TEST_EQUAL(wdb.get_doccount(), 1);
274  wdb.close();
276  TEST_EQUAL(db.get_doccount(), 1);
277 }
278 
280 DEFINE_TESTCASE(closedb5, transactions) {
281  {
282  // If a transaction is active, close() shouldn't implicitly commit().
284  wdb.begin_transaction();
286  TEST_EQUAL(wdb.get_doccount(), 1);
287  wdb.close();
289  TEST_EQUAL(db.get_doccount(), 0);
290  }
291 
292  {
293  // Same test but for an unflushed transaction.
295  wdb.begin_transaction(false);
297  TEST_EQUAL(wdb.get_doccount(), 1);
298  wdb.close();
300  TEST_EQUAL(db.get_doccount(), 0);
301  }
302 
303  {
304  // commit_transaction() throws InvalidOperationError when
305  // not in a transaction.
307  wdb.close();
309  wdb.commit_transaction());
310 
311  // begin_transaction() is no-op or throws DatabaseClosedError. We may be
312  // able to call db.begin_transaction(), but we can't make any changes
313  // inside that transaction. If begin_transaction() succeeds, then
314  // commit_transaction() either end the transaction or throw
315  // DatabaseClosedError.
316  try {
317  wdb.begin_transaction();
318  try {
319  wdb.commit_transaction();
320  } catch (const Xapian::DatabaseClosedError &) {
321  }
322  } catch (const Xapian::DatabaseClosedError &) {
323  }
324  }
325 
326  {
327  // Same test but for cancel_transaction().
329  wdb.close();
331  wdb.cancel_transaction());
332 
333  try {
334  wdb.begin_transaction();
335  try {
336  wdb.cancel_transaction();
337  } catch (const Xapian::DatabaseClosedError &) {
338  }
339  } catch (const Xapian::DatabaseClosedError &) {
340  }
341  }
342 }
343 
345 DEFINE_TESTCASE(closedb6, remote) {
346  Xapian::Database db(get_database("etext"));
347  db.close();
348 
349  try {
350  db.keep_alive();
351  FAIL_TEST("Expected DatabaseClosedError wasn't thrown");
352  } catch (const Xapian::DatabaseClosedError &) {
353  }
354 }
355 
356 // Test WritableDatabase methods.
357 DEFINE_TESTCASE(closedb7, writable) {
360  db.close();
361 
362  // Since we can't make any changes which need to be committed,
363  // db.commit() is a no-op, and so doesn't have to fail.
364  try {
365  db.commit();
366  } catch (const Xapian::DatabaseClosedError &) {
367  }
368 
372  db.delete_document(1));
378  db.replace_document("Qi", Xapian::Document()));
379 }
380 
381 // Test spelling related methods.
382 DEFINE_TESTCASE(closedb8, writable && spelling) {
384  db.add_spelling("pneumatic");
385  db.add_spelling("pneumonia");
386  db.close();
387 
389  db.add_spelling("penmanship"));
391  db.remove_spelling("pneumatic"));
393  db.get_spelling_suggestion("newmonia"));
395  db.spellings_begin());
396 }
397 
398 // Test synonym related methods.
399 DEFINE_TESTCASE(closedb9, writable && synonyms) {
401  db.add_synonym("color", "colour");
402  db.add_synonym("honor", "honour");
403  db.close();
404 
406  db.add_synonym("behavior", "behaviour"));
408  db.remove_synonym("honor", "honour"));
410  db.clear_synonyms("honor"));
412  db.synonyms_begin("color"));
414  db.synonym_keys_begin());
415 }
416 
417 // Test metadata related methods.
418 DEFINE_TESTCASE(closedb10, writable && metadata) {
420  db.set_metadata("foo", "FOO");
421  db.set_metadata("bar", "BAR");
422  db.close();
423 
425  db.set_metadata("test", "TEST"));
427  db.get_metadata("foo"));
429  db.get_metadata("bar"));
431  db.metadata_keys_begin());
432 }
433 
434 #define COUNT_NETWORK(CODE) COUNT_EXCEPTION(CODE, NetworkError)
435 
436 // Iterators used by remotefailure1.
450 
452  db = db_;
453 
454  // Set up the iterators for the test.
455  pl1 = db.postlist_begin("paragraph");
456  pl2 = db.postlist_begin("this");
457  ++pl2;
458  pl1end = db.postlist_end("paragraph");
459  pl2end = db.postlist_end("this");
460  tl1 = db.termlist_begin(1);
461  tlend = db.termlist_end(1);
462  atl1 = db.allterms_begin("t");
463  atlend = db.allterms_end("t");
464  pil1 = db.positionlist_begin(1, "paragraph");
465  pilend = db.positionlist_end(1, "paragraph");
466  }
467 
468  int perform() {
469  int exception_count = 0;
470 
471  // Getting a document may throw.
473  doc1 = db.get_document(1);
474  // Only do these if get_document() succeeded.
475  COUNT_NETWORK(TEST_EQUAL(doc1.get_data().substr(0, 33),
476  "This is a test document used with"));
478  );
479 
480  // These should always fail.
481  COUNT_NETWORK(db.postlist_begin("paragraph"));
484  COUNT_NETWORK(db.positionlist_begin(1, "paragraph"));
486  COUNT_NETWORK(db.allterms_begin("p"));
487  COUNT_NETWORK(db.get_termfreq("paragraph"));
488  COUNT_NETWORK(db.get_collection_freq("paragraph"));
489  COUNT_NETWORK(db.term_exists("paragraph"));
496 
497  // Should always fail.
498  COUNT_NETWORK(db.reopen());
499 
500  TEST_NOT_EQUAL(pl1, pl1end);
501  TEST_NOT_EQUAL(pl2, pl2end);
502  TEST_NOT_EQUAL(tl1, tlend);
503  TEST_NOT_EQUAL(atl1, atlend);
504  TEST_NOT_EQUAL(pil1, pilend);
505 
506  COUNT_NETWORK(db.postlist_begin("paragraph"));
507 
508  COUNT_NETWORK(TEST_EQUAL(*pl1, 1));
511 
512  COUNT_NETWORK(TEST_EQUAL(*pl2, 2));
515 
516  COUNT_NETWORK(TEST_EQUAL(*tl1, "a"));
517  COUNT_NETWORK(TEST_EQUAL(tl1.get_wdf(), 2));
519 
520  COUNT_NETWORK(TEST_EQUAL(*atl1, "test"));
522 
523  COUNT_NETWORK(TEST_EQUAL(*pil1, 12));
524 
525  // Advancing the iterator may or may not raise an error, but if it
526  // doesn't it must return the correct answers.
528  ++pl1;
529  COUNT_NETWORK(TEST_EQUAL(*pl1, 2));
532  );
533 
535  ++pl2;
536  COUNT_NETWORK(TEST_EQUAL(*pl2, 3));
539  );
540 
542  ++tl1;
543  COUNT_NETWORK(TEST_EQUAL(*tl1, "api"));
544  COUNT_NETWORK(TEST_EQUAL(tl1.get_wdf(), 1));
546  );
547 
549  ++atl1;
550  COUNT_NETWORK(TEST_EQUAL(*atl1, "that"));
552  );
553 
555  ++pil1;
556  COUNT_NETWORK(TEST_EQUAL(*pil1, 28));
557  );
558 
559  return exception_count;
560  }
561 };
562 
563 // Test for a remote server failing.
564 DEFINE_TESTCASE(remotefailure1, remotetcp) {
565 #ifdef __WIN32__
566  // Calling GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, pid) to kill
567  // a whole process group fails under Wine with ERROR_INVALID_HANDLE.
568  // We haven't managed to reduce a testcase for this.
569  if (getenv("XAPIAN_TESTSUITE_RUNNING_UNDER_WINE"))
570  SKIP_TEST("This testcase doesn't work under Wine");
571 #endif
572  Xapian::Database db(get_database("apitest_simpledata"));
574 
575  // Run the test, checking that we get no exceptions.
576  iters.setup(db);
577  int exception_count = iters.perform();
578  TEST_EQUAL(exception_count, 0);
579 
580  // Setup for the next test.
581  iters.setup(db);
582 
583  // Simulate remote server failure.
584  kill_remote(db);
585 
586  // Dup stdout to the fds which the database was using, to try to catch
587  // issues with lingering references to closed fds.
588  vector<int> fds;
589  for (int i = 0; i != 6; ++i) {
590  fds.push_back(dup(1));
591  }
592 
593  // Run the test again, checking that we get some "NetworkError" exceptions.
594  exception_count = iters.perform();
595  TEST_NOT_EQUAL(exception_count, 0);
596 
597  // get_description() shouldn't throw an exception. Actually do something
598  // with the description, in case this method is marked as "pure" in the
599  // future.
600  TEST(!db.get_description().empty());
601 
602  for (int fd : fds) {
603  close(fd);
604  }
605 }
606 
607 // There's no remotefailure2 plus other gaps in the numbering - these testcases
608 // are adapted versions of the closedb testcases, but some closedb testcases
609 // don't make sense to convert.
610 
612 DEFINE_TESTCASE(remotefailure3, remotetcp) {
613 #ifdef __WIN32__
614  if (getenv("XAPIAN_TESTSUITE_RUNNING_UNDER_WINE"))
615  SKIP_TEST("This testcase doesn't work under Wine");
616 #endif
617  Xapian::Database db(get_database("etext"));
618  const string & uuid = db.get_uuid();
619  kill_remote(db);
620  try {
621  TEST_EQUAL(db.get_uuid(), uuid);
622  } catch (const Xapian::NetworkError&) {
623  }
624  try {
625  TEST(db.has_positions());
626  } catch (const Xapian::NetworkError&) {
627  }
628  try {
629  TEST_EQUAL(db.get_doccount(), 566);
630  } catch (const Xapian::NetworkError&) {
631  }
632  try {
633  TEST_EQUAL(db.get_lastdocid(), 566);
634  } catch (const Xapian::NetworkError&) {
635  }
636  try {
638  } catch (const Xapian::NetworkError&) {
639  }
640  try {
642  } catch (const Xapian::NetworkError&) {
643  }
644  try {
645  TEST(db.get_wdf_upper_bound("king"));
646  } catch (const Xapian::NetworkError&) {
647  }
649 }
650 
652 DEFINE_TESTCASE(remotefailure5, remotetcp) {
653 #ifdef __WIN32__
654  if (getenv("XAPIAN_TESTSUITE_RUNNING_UNDER_WINE"))
655  SKIP_TEST("This testcase doesn't work under Wine");
656 #endif
657  {
659  kill_remote(wdb);
660 
661  // commit_transaction() and cancel_transaction() should throw
662  // InvalidOperationError because we aren't in a transaction.
664  wdb.commit_transaction());
665 
667  wdb.cancel_transaction());
668 
669  // begin_transaction() only sets state locally so works.
670  wdb.begin_transaction();
671  // commit_transaction() should only communicate with the server if
672  // there are changes in the transaction.
673  wdb.commit_transaction();
674 
675  wdb.begin_transaction();
676  // cancel_transaction() should only communicate with the server if
677  // there are changes in the transaction.
678  wdb.cancel_transaction();
679  }
680 
681  {
683  wdb.begin_transaction();
685  kill_remote(wdb);
686  // With a transaction active, commit_transaction() should fail with
687  // NetworkError.
689  wdb.commit_transaction());
690  }
691 
692  {
694  wdb.begin_transaction();
696  kill_remote(wdb);
697  // With a transaction active, cancel_transaction() should fail with
698  // NetworkError.
700  wdb.cancel_transaction());
701  }
702 }
703 
704 // Test WritableDatabase methods.
705 DEFINE_TESTCASE(remotefailure7, remotetcp) {
706 #ifdef __WIN32__
707  if (getenv("XAPIAN_TESTSUITE_RUNNING_UNDER_WINE"))
708  SKIP_TEST("This testcase doesn't work under Wine");
709 #endif
712  kill_remote(db);
713 
714  // We have a pending change from before the kill so this should fail.
716  db.commit());
720  db.delete_document(1));
726  db.replace_document("Qi", Xapian::Document()));
727 }
728 
729 // Test spelling related methods.
730 DEFINE_TESTCASE(remotefailure8, remotetcp) {
731 #ifdef __WIN32__
732  if (getenv("XAPIAN_TESTSUITE_RUNNING_UNDER_WINE"))
733  SKIP_TEST("This testcase doesn't work under Wine");
734 #endif
736  db.add_spelling("pneumatic");
737  db.add_spelling("pneumonia");
738  kill_remote(db);
739 
741  db.add_spelling("penmanship"));
743  db.remove_spelling("pneumatic"));
744  // These methods aren't implemented for remote databases - they're no-ops
745  // which don't fail even when we kill the remote server. Once remote
746  // spelling suggestions are working we can uncomment them.
747  // TEST_EXCEPTION(Xapian::NetworkError,
748  // db.get_spelling_suggestion("newmonia"));
749  // TEST_EXCEPTION(Xapian::NetworkError,
750  // db.spellings_begin());
751 }
752 
753 // Test synonym related methods.
754 DEFINE_TESTCASE(remotefailure9, remotetcp) {
755 #ifdef __WIN32__
756  if (getenv("XAPIAN_TESTSUITE_RUNNING_UNDER_WINE"))
757  SKIP_TEST("This testcase doesn't work under Wine");
758 #endif
760  db.add_synonym("color", "colour");
761  db.add_synonym("honor", "honour");
762  kill_remote(db);
763 
765  db.add_synonym("behavior", "behaviour"));
767  db.remove_synonym("honor", "honour"));
769  db.clear_synonyms("honor"));
771  db.synonyms_begin("color"));
773  db.synonym_keys_begin());
774 }
775 
776 // Test metadata related methods.
777 DEFINE_TESTCASE(remotefailure10, remotetcp) {
778 #ifdef __WIN32__
779  if (getenv("XAPIAN_TESTSUITE_RUNNING_UNDER_WINE"))
780  SKIP_TEST("This testcase doesn't work under Wine");
781 #endif
783  db.set_metadata("foo", "FOO");
784  db.set_metadata("bar", "BAR");
785  kill_remote(db);
786 
788  db.set_metadata("test", "TEST"));
790  db.get_metadata("foo"));
792  db.get_metadata("bar"));
794  db.metadata_keys_begin());
795 }
#define COUNT_NETWORK(CODE)
Definition: api_closedb.cc:434
DEFINE_TESTCASE(closedb1, backend)
Definition: api_closedb.cc:173
#define COUNT_CLOSED(CODE)
Definition: api_closedb.cc:42
Xapian::Database get_writable_database_as_database()
Definition: apitest.cc:126
Xapian::WritableDatabase get_writable_database(const string &dbname)
Definition: apitest.cc:86
std::string get_named_writable_database_path(const std::string &name)
Definition: apitest.cc:98
Xapian::Database get_database(const string &dbname)
Definition: apitest.cc:47
Xapian::WritableDatabase get_named_writable_database(const std::string &name, const std::string &source)
Definition: apitest.cc:92
void kill_remote(const Xapian::Database &db)
Kill the server associated with remote database db.
Definition: apitest.cc:120
test functionality of the Xapian API
Indicates an attempt to access a closed database.
Definition: error.h:1085
DatabaseLockError indicates failure to lock a database.
Definition: error.h:481
An indexed database of documents.
Definition: database.h:75
Xapian::TermIterator metadata_keys_begin(std::string_view prefix={}) const
An iterator which returns all user-specified metadata keys.
Definition: database.cc:499
ValueIterator valuestream_begin(Xapian::valueno slot) const
Return an iterator over the value in slot slot for each document.
Definition: database.cc:335
Xapian::doccount get_termfreq(std::string_view term) const
Get the number of documents indexed by a specified term.
Definition: database.cc:262
Xapian::TermIterator synonym_keys_begin(std::string_view prefix={}) const
An iterator which returns all terms which have synonyms.
Definition: database.cc:484
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
PositionIterator positionlist_end(Xapian::docid, std::string_view) const noexcept
End iterator corresponding to positionlist_begin().
Definition: database.h:292
Xapian::termcount get_doclength_lower_bound() const
Get a lower bound on the length of a document in this DB.
Definition: database.cc:302
PostingIterator postlist_begin(std::string_view term) const
Start iterating the postings of a term.
Definition: database.cc:192
TermIterator termlist_begin(Xapian::docid did) const
Start iterating the terms in a document.
Definition: database.cc:200
void keep_alive()
Send a keep-alive message.
Definition: database.cc:385
double get_avlength() const
Old name for get_average_length() for backward compatibility.
Definition: database.h:322
Xapian::termcount get_wdf_upper_bound(std::string_view term) const
Get an upper bound on the wdf of term term.
Definition: database.cc:314
PositionIterator positionlist_begin(Xapian::docid did, std::string_view term) const
Start iterating positions for a term in a document.
Definition: database.cc:221
std::string get_value_upper_bound(Xapian::valueno slot) const
Get an upper bound on the values stored in the given value slot.
Definition: database.cc:296
virtual std::string get_description() const
Return a string describing this object.
Definition: database.cc:391
Xapian::termcount get_doclength(Xapian::docid did) const
Get the length of a specified document.
Definition: database.cc:341
bool term_exists(std::string_view term) const
Test is a particular term is present in any document.
Definition: database.cc:378
std::string get_value_lower_bound(Xapian::valueno slot) const
Get a lower bound on the values stored in the given value slot.
Definition: database.cc:290
TermIterator allterms_end(std::string_view={}) const noexcept
End iterator corresponding to allterms_begin(prefix).
Definition: database.h:307
bool has_positions() const
Does this database have any positional information?
Definition: database.cc:215
Xapian::termcount get_collection_freq(std::string_view term) const
Get the total number of occurrences of a specified term.
Definition: database.cc:273
Xapian::doccount get_doccount() const
Get the number of documents in the database.
Definition: database.cc:233
PostingIterator postlist_end(std::string_view) const noexcept
End iterator corresponding to postlist_begin().
Definition: database.h:258
TermIterator termlist_end(Xapian::docid) const noexcept
End iterator corresponding to termlist_begin().
Definition: database.h:271
Xapian::docid get_lastdocid() const
Get the highest document id which has been used in the database.
Definition: database.cc:239
Xapian::doccount get_value_freq(Xapian::valueno slot) const
Return the frequency of a given value slot.
Definition: database.cc:284
TermIterator allterms_begin(std::string_view prefix={}) const
Start iterating all terms in the database with a given prefix.
Definition: database.cc:209
Xapian::TermIterator synonyms_begin(std::string_view term) const
An iterator which returns all the synonyms for a given term.
Definition: database.cc:478
bool reopen()
Reopen the database at the latest available revision.
Definition: database.cc:93
Xapian::termcount get_doclength_upper_bound() const
Get an upper bound on the length of a document in this DB.
Definition: database.cc:308
std::string get_spelling_suggestion(std::string_view word, unsigned max_edit_distance=2) const
Suggest a spelling correction.
Definition: database.cc:400
Xapian::Document get_document(Xapian::docid did, unsigned flags=0) const
Get a document from the database.
Definition: database.cc:368
std::string get_uuid() const
Get the UUID for the database.
Definition: database.cc:505
std::string get_metadata(std::string_view key) const
Get the user-specified metadata associated with a given key.
Definition: database.cc:490
Xapian::termcount get_unique_terms(Xapian::docid did) const
Get the number of unique terms in a specified document.
Definition: database.cc:350
Class representing a document.
Definition: document.h:64
std::string get_data() const
Get the document data.
Definition: document.cc:75
std::string get_value(Xapian::valueno slot) const
Read a value slot in this document.
Definition: document.cc:185
TermIterator termlist_begin() const
Start iterating the terms in this document.
Definition: document.cc:179
InvalidOperationError indicates the API was used in an invalid way.
Definition: error.h:271
Indicates a problem communicating with a remote database.
Definition: error.h:791
Class for iterating over term positions.
Class for iterating over a list of terms.
Xapian::termcount get_doclength() const
Return the length of the document at the current position.
Xapian::termcount get_unique_terms() const
Return the number of unique terms in the current document.
Class for iterating over a list of terms.
Definition: termiterator.h:41
Xapian::doccount get_termfreq() const
Return the term frequency for the term at the current position.
Xapian::termcount get_wdf() const
Return the wdf for the term at the current position.
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 clear_synonyms(std::string_view term) const
Remove all synonyms for a term.
Definition: database.cc:628
void begin_transaction(bool flushed=true)
Begin a transaction.
Definition: database.cc:549
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 set_metadata(std::string_view key, std::string_view metadata)
Set the user-specified metadata associated with a given key.
Definition: database.cc:634
void commit_transaction()
Complete the transaction currently in progress.
Definition: database.h:1193
void cancel_transaction()
Abort the transaction currently in progress.
Definition: database.h:1206
void add_spelling(std::string_view word, Xapian::termcount freqinc=1) const
Add a word to the spelling dictionary.
Definition: database.cc:600
termcount remove_spelling(std::string_view word, termcount freqdec=1) const
Remove a word from the spelling dictionary.
Definition: database.cc:607
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
void remove_synonym(std::string_view term, std::string_view synonym) const
Remove a synonym for a term.
Definition: database.cc:621
int close(FD &fd)
Definition: fd.h:63
const int DB_OPEN
Open an existing database.
Definition: constants.h:49
<unistd.h>, but with compat.
Xapian::PostingIterator pl1end
Definition: api_closedb.cc:50
Xapian::TermIterator atl1
Definition: api_closedb.cc:54
Xapian::PostingIterator pl1
Definition: api_closedb.cc:48
Xapian::Document doc1
Definition: api_closedb.cc:47
Xapian::TermIterator tl1
Definition: api_closedb.cc:52
Xapian::PositionIterator pil1
Definition: api_closedb.cc:56
Xapian::TermIterator atlend
Definition: api_closedb.cc:55
void setup(Xapian::Database db_)
Definition: api_closedb.cc:59
Xapian::TermIterator tlend
Definition: api_closedb.cc:53
Xapian::PostingIterator pl2end
Definition: api_closedb.cc:51
Xapian::PostingIterator pl2
Definition: api_closedb.cc:49
Xapian::PositionIterator pilend
Definition: api_closedb.cc:57
Xapian::Database db
Definition: api_closedb.cc:46
Xapian::TermIterator atlend
Definition: api_closedb.cc:447
Xapian::Document doc1
Definition: api_closedb.cc:439
Xapian::Database db
Definition: api_closedb.cc:438
Xapian::PositionIterator pilend
Definition: api_closedb.cc:449
Xapian::TermIterator atl1
Definition: api_closedb.cc:446
Xapian::TermIterator tlend
Definition: api_closedb.cc:445
Xapian::TermIterator tl1
Definition: api_closedb.cc:444
void setup(Xapian::Database db_)
Definition: api_closedb.cc:451
Xapian::PostingIterator pl1
Definition: api_closedb.cc:440
Xapian::PostingIterator pl2end
Definition: api_closedb.cc:443
Xapian::PostingIterator pl2
Definition: api_closedb.cc:441
Xapian::PositionIterator pil1
Definition: api_closedb.cc:448
Xapian::PostingIterator pl1end
Definition: api_closedb.cc:442
#define TEST_REL(A, REL, B)
Test a relation holds,e.g. TEST_REL(a,>,b);.
Definition: testmacros.h:35
#define FAIL_TEST(MSG)
Fail the current testcase with message MSG.
Definition: testsuite.h:65
#define SKIP_TEST(MSG)
Skip the current testcase with message MSG.
Definition: testsuite.h:71
#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
Public interfaces for the Xapian library.