xapian-core  2.0.0
api_none.cc
Go to the documentation of this file.
1 
4 /* Copyright (C) 2009 Richard Boulton
5  * Copyright (C) 2009-2026 Olly Betts
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_none.h"
25 
26 #define XAPIAN_DEPRECATED(D) D
27 #include <xapian.h>
28 
29 #include "apitest.h"
30 #include "str.h"
31 #include "testsuite.h"
32 #include "testutils.h"
33 
34 #include <string_view>
35 #include <vector>
36 
37 using namespace std;
38 
39 // Check the version functions give consistent results.
40 DEFINE_TESTCASE(version1, !backend) {
41  string version = str(Xapian::major_version());
42  version += '.';
43  version += str(Xapian::minor_version());
44  version += '.';
45  version += str(Xapian::revision());
47 }
48 
49 // Regression test: various methods on Database() used to segfault or cause
50 // division by 0. Fixed in 1.1.4 and 1.0.18. Ticket#415.
51 DEFINE_TESTCASE(nosubdatabases1, !backend) {
53  TEST(db.get_metadata("foo").empty());
57  TEST_EQUAL(db.allterms_begin("foo"), db.allterms_end("foo"));
59  TEST_EQUAL(db.get_lastdocid(), 0);
64 
69 }
70 
72 DEFINE_TESTCASE(document1, !backend) {
73  Xapian::Document doc;
74  doc.add_boolean_term("Hxapian.org");
75  TEST_EQUAL(doc.termlist_count(), 1);
77  TEST(t != doc.termlist_end());
78  TEST_EQUAL(*t, "Hxapian.org");
79  TEST_EQUAL(t.get_wdf(), 0);
80  TEST(++t == doc.termlist_end());
81  doc.remove_term("Hxapian.org");
82  TEST_EQUAL(doc.termlist_count(), 0);
83  TEST(doc.termlist_begin() == doc.termlist_end());
84 }
85 
87 DEFINE_TESTCASE(document2, !backend) {
88  Xapian::Document doc;
89  // The return value is uninitialised, so running under valgrind this
90  // will fail reliably prior to the fix.
91  TEST_EQUAL(doc.get_docid(), 0);
92 }
93 
95 DEFINE_TESTCASE(documentclearterms1, !backend) {
96  {
97  Xapian::Document doc;
98  doc.add_boolean_term("Hlocalhost");
99  doc.add_term("hello");
100  doc.add_term("there", 2);
101  doc.add_posting("positional", 1);
102  doc.add_posting("information", 2, 3);
103  TEST_EQUAL(doc.termlist_count(), 5);
104  TEST(doc.termlist_begin() != doc.termlist_end());
105  doc.clear_terms();
106  TEST_EQUAL(doc.termlist_count(), 0);
107  TEST(doc.termlist_begin() == doc.termlist_end());
108  // Test clear_terms() when there are no terms.
109  doc.clear_terms();
110  TEST_EQUAL(doc.termlist_count(), 0);
111  TEST(doc.termlist_begin() == doc.termlist_end());
112  }
113 
114  {
115  // Test clear_terms() when there have never been any terms.
116  Xapian::Document doc;
117  doc.clear_terms();
118  TEST_EQUAL(doc.termlist_count(), 0);
119  TEST(doc.termlist_begin() == doc.termlist_end());
120  }
121 }
122 
124 DEFINE_TESTCASE(documentclearvalues1, !backend) {
125  {
126  Xapian::Document doc;
127  doc.add_value(37, "hello");
128  doc.add_value(42, "world");
129  TEST_EQUAL(doc.values_count(), 2);
130  TEST(doc.values_begin() != doc.values_end());
131  doc.clear_values();
132  TEST_EQUAL(doc.values_count(), 0);
133  TEST(doc.values_begin() == doc.values_end());
134  // Test clear_values() when there are no values.
135  doc.clear_values();
136  TEST_EQUAL(doc.values_count(), 0);
137  TEST(doc.values_begin() == doc.values_end());
138  }
139 
140  {
141  // Test clear_values() when there have never been any values.
142  Xapian::Document doc;
143  doc.clear_values();
144  TEST_EQUAL(doc.values_count(), 0);
145  TEST(doc.termlist_begin() == doc.termlist_end());
146  }
147 }
148 
150 DEFINE_TESTCASE(documentemptyterm1, !backend) {
151  Xapian::Document doc;
153  doc.add_boolean_term(string()));
155  doc.add_term(string()));
157  doc.add_posting(string(), 1));
159  doc.add_posting(string(), 2, 3));
161  doc.remove_term(string()));
163  doc.remove_posting(string(), 1));
165  doc.remove_posting(string(), 2, 3));
167  doc.remove_postings(string(), 2, 3));
169  doc.remove_postings(string(), 2, 3, 4));
170 }
171 
172 DEFINE_TESTCASE(emptyquery4, !backend) {
173  // Test we get an empty query from applying any of the following ops to
174  // an empty list of subqueries.
175  Xapian::Query q;
176  TEST(Xapian::Query(q.OP_AND, &q, &q).empty());
177  TEST(Xapian::Query(q.OP_OR, &q, &q).empty());
178  TEST(Xapian::Query(q.OP_AND_NOT, &q, &q).empty());
179  TEST(Xapian::Query(q.OP_XOR, &q, &q).empty());
180  TEST(Xapian::Query(q.OP_AND_MAYBE, &q, &q).empty());
181  TEST(Xapian::Query(q.OP_FILTER, &q, &q).empty());
182  TEST(Xapian::Query(q.OP_NEAR, &q, &q).empty());
183  TEST(Xapian::Query(q.OP_PHRASE, &q, &q).empty());
184  TEST(Xapian::Query(q.OP_ELITE_SET, &q, &q).empty());
185  TEST(Xapian::Query(q.OP_SYNONYM, &q, &q).empty());
186  TEST(Xapian::Query(q.OP_MAX, &q, &q).empty());
187 }
188 
189 DEFINE_TESTCASE(singlesubquery1, !backend) {
190  // Test that we get just the subquery if we apply any of the following
191  // ops to just that subquery.
192 #define singlesubquery1_(OP) \
193  TEST_STRINGS_EQUAL(Xapian::Query(q->OP, q, q + 1).get_description(),\
194  "Query(test)")
195  Xapian::Query q[1] = { Xapian::Query("test") };
196  singlesubquery1_(OP_AND);
197  singlesubquery1_(OP_OR);
198  singlesubquery1_(OP_AND_NOT);
199  singlesubquery1_(OP_XOR);
200  singlesubquery1_(OP_AND_MAYBE);
201  singlesubquery1_(OP_FILTER);
202  singlesubquery1_(OP_NEAR);
203  singlesubquery1_(OP_PHRASE);
204  singlesubquery1_(OP_ELITE_SET);
205  singlesubquery1_(OP_SYNONYM);
206  singlesubquery1_(OP_MAX);
207 }
208 
209 DEFINE_TESTCASE(singlesubquery2, !backend) {
210  // Like the previous test, but using MatchNothing as the subquery.
211 #define singlesubquery2_(OP) \
212  TEST_STRINGS_EQUAL(Xapian::Query(q->OP, q, q + 1).get_description(),\
213  "Query()")
215  singlesubquery2_(OP_AND);
216  singlesubquery2_(OP_OR);
217  singlesubquery2_(OP_AND_NOT);
218  singlesubquery2_(OP_XOR);
219  singlesubquery2_(OP_AND_MAYBE);
220  singlesubquery2_(OP_FILTER);
221  singlesubquery2_(OP_NEAR);
222  singlesubquery2_(OP_PHRASE);
223  singlesubquery2_(OP_ELITE_SET);
224  singlesubquery2_(OP_SYNONYM);
225  singlesubquery2_(OP_MAX);
226 }
227 
228 DEFINE_TESTCASE(singlesubquery3, !backend) {
229  // Like the previous test, but using MatchAll as the subquery.
230 #define singlesubquery3_(OP) \
231  TEST_STRINGS_EQUAL(Xapian::Query(q->OP, q, q + 1).get_description(),\
232  "Query(<alldocuments>)")
234  singlesubquery3_(OP_AND);
235  singlesubquery3_(OP_OR);
236  singlesubquery3_(OP_AND_NOT);
237  singlesubquery3_(OP_XOR);
238  singlesubquery3_(OP_AND_MAYBE);
239  singlesubquery3_(OP_FILTER);
240  // OP_NEAR and OP_PHRASE over MatchAll doesn't really make sense.
241  singlesubquery3_(OP_ELITE_SET);
242  singlesubquery3_(OP_SYNONYM);
243  singlesubquery3_(OP_MAX);
244 }
245 
246 DEFINE_TESTCASE(pairwisequery1, !backend) {
247  // Test that constructing from char* and const char* gives the same result
248  // as explicitly constructing Query objects for the subqueries. This
249  // serves as a regression test for using char*/const char* not compiling
250  // with Xapian <= 1.4.30.
251 #define lit_a "a"
252 #define lit_b "b"
253  char aa[] = lit_a;
254  char ab[] = lit_b;
255  const char* ca = aa;
256  const char* cb = ab;
257  Xapian::Query qa(aa);
258  Xapian::Query qb(ab);
259 
260 #define pairwisequery1_(OP) do {\
261  auto expect = Xapian::Query(qa.OP, lit_a, lit_b).get_description(); \
262  TEST_STRINGS_EQUAL(expect, \
263  Xapian::Query(qa.OP, aa, ab).get_description()); \
264  TEST_STRINGS_EQUAL(expect, \
265  Xapian::Query(qa.OP, ca, cb).get_description()); \
266  TEST_STRINGS_EQUAL(expect, \
267  Xapian::Query(qa.OP, qa, qb).get_description()); \
268  } while (false)
269 
270  pairwisequery1_(OP_AND);
271  pairwisequery1_(OP_OR);
272  pairwisequery1_(OP_AND_NOT);
273  pairwisequery1_(OP_XOR);
274  pairwisequery1_(OP_AND_MAYBE);
275  pairwisequery1_(OP_FILTER);
276  pairwisequery1_(OP_NEAR);
277  pairwisequery1_(OP_PHRASE);
278  pairwisequery1_(OP_ELITE_SET);
279  pairwisequery1_(OP_SYNONYM);
280  pairwisequery1_(OP_MAX);
281 }
282 
284 DEFINE_TESTCASE(combinewqfnomore1, !backend) {
286  Xapian::Query("beer", 1, 1),
287  Xapian::Query("beer", 1, 1));
288  // Prior to 1.3.0, we would have given beer@2, but we decided that wasn't
289  // really useful or helpful.
290  TEST_EQUAL(q.get_description(), "Query((beer@1 OR beer@1))");
291 }
292 
294  bool & destroyed;
295 
296  public:
297  DestroyedFlag(bool & destroyed_) : destroyed(destroyed_) {
298  destroyed = false;
299  }
300 
302  destroyed = true;
303  }
304 };
305 
308 
309  public:
310  TestRangeProcessor(bool & destroyed_)
311  : Xapian::RangeProcessor(0), destroyed(destroyed_) { }
312 
313  Xapian::Query operator()(const std::string&, const std::string&) override {
315  }
316 };
317 
319 DEFINE_TESTCASE(subclassablerefcount1, !backend) {
320  bool gone_auto, gone;
321 #ifdef _MSC_VER
322  // MSVC incorrectly warns these are potentially uninitialised. It's
323  // unhelpful to always initialise these as that could mask if a genuine bug
324  // were introduced (which currently would likely be caught by a warning
325  // from a smarter compiler).
326  gone_auto = gone = false;
327 #endif
328 
329  // Simple test of release().
330  {
332  TEST(!gone);
334  qp.add_rangeprocessor(rp->release());
335  TEST(!gone);
336  }
337  TEST(gone);
338 
339  // Check a second call to release() has no effect.
340  {
342  TEST(!gone);
344  qp.add_rangeprocessor(rp->release());
345  rp->release();
346  TEST(!gone);
347  }
348  TEST(gone);
349 
350  // Test reference counting works, and that a RangeProcessor with automatic
351  // storage works OK.
352  {
353  TestRangeProcessor rp_auto(gone_auto);
354  TEST(!gone_auto);
355  {
357  {
360  rp = new TestRangeProcessor(gone);
361  TEST(!gone);
362  qp1.add_rangeprocessor(rp->release());
363  TEST(!gone);
364  qp2.add_rangeprocessor(rp);
365  TEST(!gone);
366  qp2.add_rangeprocessor(&rp_auto);
367  TEST(!gone);
368  TEST(!gone_auto);
369  }
370  TEST(!gone);
371  }
372  TEST(gone);
373  TEST(!gone_auto);
374  }
375  TEST(gone_auto);
376 
377  // Regression test for initial implementation, where ~opt_intrusive_ptr()
378  // checked the reference of the object, which may have already been deleted
379  // if it wasn't been reference counted.
380  {
382  {
384  TEST(!gone);
385  qp.add_rangeprocessor(rp);
386  delete rp;
387  TEST(gone);
388  }
389  // At the end of this block, qp is destroyed, but mustn't dereference
390  // the pointer it has to rp. If it does, that should get caught
391  // when tests are run under valgrind.
392  }
393 }
394 
397 
398  public:
399  TestFieldProcessor(bool & destroyed_) : destroyed(destroyed_) { }
400 
401  Xapian::Query operator()(const string& str) override {
402  return Xapian::Query(str);
403  }
404 };
405 
407 DEFINE_TESTCASE(subclassablerefcount2, !backend) {
408  bool gone_auto, gone;
409 #ifdef _MSC_VER
410  // MSVC incorrectly warns these are potentially uninitialised. It's
411  // unhelpful to always initialise these as that could mask if a genuine bug
412  // were introduced (which currently would likely be caught by a warning
413  // from a smarter compiler).
414  gone_auto = gone = false;
415 #endif
416 
417  // Simple test of release().
418  {
419  Xapian::FieldProcessor * proc = new TestFieldProcessor(gone);
420  TEST(!gone);
422  qp.add_prefix("foo", proc->release());
423  TEST(!gone);
424  }
425  TEST(gone);
426 
427  // Check a second call to release() has no effect.
428  {
429  Xapian::FieldProcessor * proc = new TestFieldProcessor(gone);
430  TEST(!gone);
432  qp.add_prefix("foo", proc->release());
433  proc->release();
434  TEST(!gone);
435  }
436  TEST(gone);
437 
438  // Test reference counting works, and that a FieldProcessor with automatic
439  // storage works OK.
440  {
441  TestFieldProcessor proc_auto(gone_auto);
442  TEST(!gone_auto);
443  {
445  {
447  Xapian::FieldProcessor * proc;
448  proc = new TestFieldProcessor(gone);
449  TEST(!gone);
450  qp1.add_prefix("foo", proc->release());
451  TEST(!gone);
452  qp2.add_prefix("foo", proc);
453  TEST(!gone);
454  qp2.add_prefix("bar", &proc_auto);
455  TEST(!gone);
456  TEST(!gone_auto);
457  }
458  TEST(!gone);
459  }
460  TEST(gone);
461  TEST(!gone_auto);
462  }
463  TEST(gone_auto);
464 }
465 
468 
469  public:
470  TestMatchSpy(bool & destroyed_) : destroyed(destroyed_) { }
471 
472  void operator()(const Xapian::Document&, double) override { }
473 };
474 
476 DEFINE_TESTCASE(subclassablerefcount3, backend) {
477  Xapian::Database db = get_database("apitest_simpledata");
478 
479  bool gone_auto, gone;
480 #ifdef _MSC_VER
481  // MSVC incorrectly warns these are potentially uninitialised. It's
482  // unhelpful to always initialise these as that could mask if a genuine bug
483  // were introduced (which currently would likely be caught by a warning
484  // from a smarter compiler).
485  gone_auto = gone = false;
486 #endif
487 
488  // Simple test of release().
489  {
490  Xapian::MatchSpy * spy = new TestMatchSpy(gone);
491  TEST(!gone);
492  Xapian::Enquire enquire(db);
493  enquire.add_matchspy(spy->release());
494  TEST(!gone);
495  }
496  TEST(gone);
497 
498  // Check a second call to release() has no effect.
499  {
500  Xapian::MatchSpy * spy = new TestMatchSpy(gone);
501  TEST(!gone);
502  Xapian::Enquire enquire(db);
503  enquire.add_matchspy(spy->release());
504  spy->release();
505  TEST(!gone);
506  }
507  TEST(gone);
508 
509  // Test reference counting works, and that a MatchSpy with automatic
510  // storage works OK.
511  {
512  TestMatchSpy spy_auto(gone_auto);
513  TEST(!gone_auto);
514  {
515  Xapian::Enquire enq1(db);
516  {
517  Xapian::Enquire enq2(db);
518  Xapian::MatchSpy * spy;
519  spy = new TestMatchSpy(gone);
520  TEST(!gone);
521  enq1.add_matchspy(spy->release());
522  TEST(!gone);
523  enq2.add_matchspy(spy);
524  TEST(!gone);
525  enq2.add_matchspy(&spy_auto);
526  TEST(!gone);
527  TEST(!gone_auto);
528  }
529  TEST(!gone);
530  }
531  TEST(gone);
532  TEST(!gone_auto);
533  }
534  TEST(gone_auto);
535 }
536 
537 class TestStopper : public Xapian::Stopper {
539 
540  public:
541  TestStopper(bool & destroyed_) : destroyed(destroyed_) { }
542 
543  bool operator()(const std::string&) const override { return true; }
544 };
545 
547 DEFINE_TESTCASE(subclassablerefcount4, !backend) {
548  bool gone_auto, gone;
549 #ifdef _MSC_VER
550  // MSVC incorrectly warns these are potentially uninitialised. It's
551  // unhelpful to always initialise these as that could mask if a genuine bug
552  // were introduced (which currently would likely be caught by a warning
553  // from a smarter compiler).
554  gone_auto = gone = false;
555 #endif
556 
557  // Simple test of release().
558  {
559  Xapian::Stopper * stopper = new TestStopper(gone);
560  TEST(!gone);
562  qp.set_stopper(stopper->release());
563  TEST(!gone);
564  }
565  TEST(gone);
566 
567  // Test that setting a new stopper causes the previous one to be released.
568  {
569  bool gone0;
570  Xapian::Stopper * stopper0 = new TestStopper(gone0);
571  TEST(!gone0);
573  qp.set_stopper(stopper0->release());
574  TEST(!gone0);
575 
576  Xapian::Stopper * stopper = new TestStopper(gone);
577  TEST(!gone);
578  qp.set_stopper(stopper->release());
579  TEST(gone0);
580  TEST(!gone);
581  }
582  TEST(gone);
583 
584  // Check a second call to release() has no effect.
585  {
586  Xapian::Stopper * stopper = new TestStopper(gone);
587  TEST(!gone);
589  qp.set_stopper(stopper->release());
590  stopper->release();
591  TEST(!gone);
592  }
593  TEST(gone);
594 
595  // Test reference counting works, and that a Stopper with automatic
596  // storage works OK.
597  {
598  TestStopper stopper_auto(gone_auto);
599  TEST(!gone_auto);
600  {
602  {
604  Xapian::Stopper * stopper;
605  stopper = new TestStopper(gone);
606  TEST(!gone);
607  qp1.set_stopper(stopper->release());
608  TEST(!gone);
609  qp2.set_stopper(stopper);
610  TEST(!gone);
611  qp2.set_stopper(&stopper_auto);
612  TEST(!gone);
613  TEST(!gone_auto);
614  }
615  TEST(!gone);
616  }
617  TEST(gone);
618  TEST(!gone_auto);
619  }
620  TEST(gone_auto);
621 }
622 
624 DEFINE_TESTCASE(subclassablerefcount5, !backend) {
625  bool gone_auto, gone;
626 #ifdef _MSC_VER
627  // MSVC incorrectly warns these are potentially uninitialised. It's
628  // unhelpful to always initialise these as that could mask if a genuine bug
629  // were introduced (which currently would likely be caught by a warning
630  // from a smarter compiler).
631  gone_auto = gone = false;
632 #endif
633 
634  // Simple test of release().
635  {
636  Xapian::Stopper * stopper = new TestStopper(gone);
637  TEST(!gone);
638  Xapian::TermGenerator indexer;
639  indexer.set_stopper(stopper->release());
640  TEST(!gone);
641  }
642  TEST(gone);
643 
644  // Test that setting a new stopper causes the previous one to be released.
645  {
646  bool gone0;
647  Xapian::Stopper * stopper0 = new TestStopper(gone0);
648  TEST(!gone0);
649  Xapian::TermGenerator indexer;
650  indexer.set_stopper(stopper0->release());
651  TEST(!gone0);
652 
653  Xapian::Stopper * stopper = new TestStopper(gone);
654  TEST(!gone);
655  indexer.set_stopper(stopper->release());
656  TEST(gone0);
657  TEST(!gone);
658  }
659  TEST(gone);
660 
661  // Check a second call to release() has no effect.
662  {
663  Xapian::Stopper * stopper = new TestStopper(gone);
664  TEST(!gone);
665  Xapian::TermGenerator indexer;
666  indexer.set_stopper(stopper->release());
667  stopper->release();
668  TEST(!gone);
669  }
670  TEST(gone);
671 
672  // Test reference counting works, and that a Stopper with automatic
673  // storage works OK.
674  {
675  TestStopper stopper_auto(gone_auto);
676  TEST(!gone_auto);
677  {
678  Xapian::TermGenerator indexer1;
679  {
680  Xapian::TermGenerator indexer2;
681  Xapian::Stopper * stopper;
682  stopper = new TestStopper(gone);
683  TEST(!gone);
684  indexer1.set_stopper(stopper->release());
685  TEST(!gone);
686  indexer2.set_stopper(stopper);
687  TEST(!gone);
688  indexer2.set_stopper(&stopper_auto);
689  TEST(!gone);
690  TEST(!gone_auto);
691  }
692  TEST(!gone);
693  }
694  TEST(gone);
695  TEST(!gone_auto);
696  }
697  TEST(gone_auto);
698 }
699 
702 
703  public:
704  TestKeyMaker(bool & destroyed_) : destroyed(destroyed_) { }
705 
706  string operator()(const Xapian::Document&) const override {
707  return string();
708  }
709 };
710 
712 DEFINE_TESTCASE(subclassablerefcount6, backend) {
713  Xapian::Database db = get_database("apitest_simpledata");
714 
715  bool gone_auto, gone;
716 #ifdef _MSC_VER
717  // MSVC incorrectly warns these are potentially uninitialised. It's
718  // unhelpful to always initialise these as that could mask if a genuine bug
719  // were introduced (which currently would likely be caught by a warning
720  // from a smarter compiler).
721  gone_auto = gone = false;
722 #endif
723 
724  // Simple test of release().
725  {
726  Xapian::KeyMaker * keymaker = new TestKeyMaker(gone);
727  TEST(!gone);
728  Xapian::Enquire enq(db);
729  enq.set_sort_by_key(keymaker->release(), false);
730  TEST(!gone);
731  }
732  TEST(gone);
733 
734  // Test that setting a new keymaker causes the previous one to be released.
735  {
736  bool gone0;
737  Xapian::KeyMaker * keymaker0 = new TestKeyMaker(gone0);
738  TEST(!gone0);
739  Xapian::Enquire enq(db);
740  enq.set_sort_by_key(keymaker0->release(), false);
741  TEST(!gone0);
742 
743  Xapian::KeyMaker * keymaker = new TestKeyMaker(gone);
744  TEST(!gone);
745  enq.set_sort_by_key_then_relevance(keymaker->release(), false);
746  TEST(gone0);
747  TEST(!gone);
748  }
749  TEST(gone);
750 
751  // Check a second call to release() has no effect.
752  {
753  Xapian::KeyMaker * keymaker = new TestKeyMaker(gone);
754  TEST(!gone);
755  Xapian::Enquire enq(db);
756  enq.set_sort_by_key(keymaker->release(), false);
757  keymaker->release();
758  TEST(!gone);
759  }
760  TEST(gone);
761 
762  // Test reference counting works, and that a KeyMaker with automatic
763  // storage works OK.
764  {
765  TestKeyMaker keymaker_auto(gone_auto);
766  TEST(!gone_auto);
767  {
768  Xapian::Enquire enq1(db);
769  {
770  Xapian::Enquire enq2(db);
771  Xapian::KeyMaker * keymaker;
772  keymaker = new TestKeyMaker(gone);
773  TEST(!gone);
774  enq1.set_sort_by_key(keymaker->release(), false);
775  TEST(!gone);
776  enq2.set_sort_by_relevance_then_key(keymaker, false);
777  TEST(!gone);
778  enq2.set_sort_by_key_then_relevance(&keymaker_auto, false);
779  TEST(!gone);
780  TEST(!gone_auto);
781  }
782  TEST(!gone);
783  }
784  TEST(gone);
785  TEST(!gone_auto);
786  }
787  TEST(gone_auto);
788 }
789 
792 
793  public:
794  TestExpandDecider(bool & destroyed_) : destroyed(destroyed_) { }
795 
796  bool operator()(const string&) const override { return true; }
797 };
798 
800 DEFINE_TESTCASE(subclassablerefcount7, backend) {
801  Xapian::Database db = get_database("apitest_simpledata");
802  Xapian::Enquire enq(db);
803  Xapian::RSet rset;
804  rset.add_document(1);
805 
806  bool gone_auto, gone;
807 #ifdef _MSC_VER
808  // MSVC incorrectly warns these are potentially uninitialised. It's
809  // unhelpful to always initialise these as that could mask if a genuine bug
810  // were introduced (which currently would likely be caught by a warning
811  // from a smarter compiler).
812  gone_auto = gone = false;
813 #endif
814 
815  for (int flags = 0;
818  // Test of auto lifetime ExpandDecider.
819  {
820  TestExpandDecider edecider_auto(gone_auto);
821  TEST(!gone_auto);
822  (void)enq.get_eset(5, rset, 0, &edecider_auto);
823  TEST(!gone_auto);
824  }
825  TEST(gone_auto);
826 
827  // Simple test of release().
828  {
829  Xapian::ExpandDecider * edecider = new TestExpandDecider(gone);
830  TEST(!gone);
831  (void)enq.get_eset(5, rset, 0, edecider);
832  TEST(!gone);
833  delete edecider;
834  TEST(gone);
835  }
836 
837  // Test that a released ExpandDecider gets cleaned up by get_eset().
838  {
839  Xapian::ExpandDecider * edecider = new TestExpandDecider(gone);
840  TEST(!gone);
841  (void)enq.get_eset(5, rset, 0, edecider->release());
842  TEST(gone);
843  }
844 
845  // Check a second call to release() has no effect.
846  {
847  Xapian::ExpandDecider * edecider = new TestExpandDecider(gone);
848  TEST(!gone);
849  edecider->release();
850  TEST(!gone);
851  (void)enq.get_eset(5, rset, 0, edecider->release());
852  TEST(gone);
853  }
854  }
855 
856  // Test combinations of released/non-released with ExpandDeciderAnd.
857  {
858  TestExpandDecider edecider_auto(gone_auto);
859  TEST(!gone_auto);
860  Xapian::ExpandDecider * edecider = new TestExpandDecider(gone);
861  TEST(!gone);
862  (void)enq.get_eset(5, rset, 0,
864  &edecider_auto,
865  edecider->release()))->release());
866  TEST(!gone_auto);
867  TEST(gone);
868  }
869  TEST(gone_auto);
870  {
871  TestExpandDecider edecider_auto(gone_auto);
872  TEST(!gone_auto);
873  Xapian::ExpandDecider * edecider = new TestExpandDecider(gone);
874  TEST(!gone);
875  (void)enq.get_eset(5, rset, 0,
877  edecider->release(),
878  &edecider_auto))->release());
879  TEST(!gone_auto);
880  TEST(gone);
881  }
882  TEST(gone_auto);
883 }
884 
886 DEFINE_TESTCASE(nonutf8docdesc1, !backend) {
887  Xapian::Document doc;
888  doc.set_data("\xc0\x80\xf5\x80\x80\x80\xfe\xff");
890  "Document(docid=0, data=\\xc0\\x80\\xf5\\x80\\x80\\x80\\xfe\\xff)");
891  doc.set_data(string("\x00\x1f", 2));
893  "Document(docid=0, data=\\x00\\x1f)");
894  // Check that backslashes are encoded so output isn't ambiguous.
895  doc.set_data("back\\slash");
897  "Document(docid=0, data=back\\x5cslash)");
898 }
899 
900 DEFINE_TESTCASE(orphaneddoctermitor1, !backend) {
902  {
903  Xapian::Document doc;
904  doc.add_term("foo");
905  t = doc.termlist_begin();
906  }
907  TEST_EQUAL(*t, "foo");
908 }
909 
916 DEFINE_TESTCASE(deletewhileiterating1, !backend) {
917  for (bool preinc : { false, true }) {
918  Xapian::Document doc;
919  Xapian::TermGenerator indexer;
920  indexer.set_document(doc);
921  indexer.index_text("Pull the rug out from under ourselves", 1, "S");
922  Xapian::TermIterator term_iterator = doc.termlist_begin();
923  term_iterator.skip_to("S");
924  while (term_iterator != doc.termlist_end()) {
925  const string& term = *term_iterator;
926  if (!startswith(term, "S")) {
927  break;
928  }
929  if (preinc) ++term_iterator;
930  doc.remove_term(term);
931  if (!preinc) ++term_iterator;
932  }
933  TEST_EQUAL(doc.termlist_count(), 0);
934  TEST(doc.termlist_begin() == doc.termlist_end());
935  }
936 }
937 
939 DEFINE_TESTCASE(removepostings, !backend) {
940  Xapian::Document doc;
941  // Add Fibonacci sequence as positions.
942  Xapian::termpos prev_pos = 1;
943  Xapian::termpos pos = 1;
944  while (pos < 1000) {
945  doc.add_posting("foo", pos);
946  auto new_pos = prev_pos + pos;
947  prev_pos = pos;
948  pos = new_pos;
949  }
950 
951  // Check we added exactly one term.
952  TEST_EQUAL(doc.termlist_count(), 1);
953 
955  auto num_pos = t.positionlist_count();
956  TEST_EQUAL(t.get_wdf(), num_pos);
957 
959 
960  // Out of order is a no-op.
961  TEST_EQUAL(doc.remove_postings("foo", 2, 1), 0);
962  t = doc.termlist_begin();
963  TEST_EQUAL(t.positionlist_count(), num_pos);
964  TEST_EQUAL(t.get_wdf(), num_pos);
965 
966  // 6 and 7 aren't in the sequence.
967  TEST_EQUAL(doc.remove_postings("foo", 6, 7), 0);
968  t = doc.termlist_begin();
969  TEST_EQUAL(t.positionlist_count(), num_pos);
970  TEST_EQUAL(t.get_wdf(), num_pos);
971 
972  // Beyond the end of the positions.
973  TEST_EQUAL(doc.remove_postings("foo", 1000, 2000), 0);
974  t = doc.termlist_begin();
975  TEST_EQUAL(t.positionlist_count(), num_pos);
976  TEST_EQUAL(t.get_wdf(), num_pos);
977 
978  // 1, 2, 3 are in the sequence, 4 isn't.
979  TEST_EQUAL(doc.remove_postings("foo", 1, 4), 3);
980  t = doc.termlist_begin();
981  TEST_EQUAL(t.positionlist_count(), num_pos - 3);
982  TEST_EQUAL(t.get_wdf(), num_pos - 3);
983 
984  // Test an existing PositionIterator isn't affected.
985  TEST_EQUAL(*pi, 1);
986  TEST_EQUAL(*++pi, 2);
987  TEST_EQUAL(*++pi, 3);
988  TEST_EQUAL(*++pi, 5);
989 
990  // Remove the end position.
991  TEST_EQUAL(doc.remove_postings("foo", 876, 987), 1);
992  t = doc.termlist_begin();
993  TEST_EQUAL(t.positionlist_count(), num_pos - 4);
994  TEST_EQUAL(t.get_wdf(), num_pos - 4);
995 
996  // Remove a range in the middle.
997  TEST_EQUAL(doc.remove_postings("foo", 33, 233), 5);
998  t = doc.termlist_begin();
999  TEST_EQUAL(t.positionlist_count(), num_pos - 9);
1000  TEST_EQUAL(t.get_wdf(), num_pos - 9);
1001 
1002  // Check the expected positions are left.
1003  t = doc.termlist_begin();
1004  static const Xapian::termpos expected[] = { 5, 8, 13, 21, 377, 610, 9999 };
1005  const Xapian::termpos* expect = expected;
1006  for (auto p = t.positionlist_begin(); p != t.positionlist_end(); ++p) {
1007  TEST_EQUAL(*p, *expect);
1008  ++expect;
1009  }
1010  TEST_EQUAL(*expect, 9999);
1011  TEST_EQUAL(t.get_wdf(), 6);
1012 
1013  pi = t.positionlist_begin();
1014 
1015  // Test remove_position().
1016  doc.remove_posting("foo", 8);
1017 
1018  // Test an existing PositionIterator isn't affected.
1019  TEST_EQUAL(*pi, 5);
1020  TEST_EQUAL(*++pi, 8);
1021 
1022  // Check removing all positions removes the term too if the wdf reaches 0
1023  // (since 2.0.0).
1024  TEST_EQUAL(doc.remove_postings("foo", 5, 1000), 5);
1025  t = doc.termlist_begin();
1026  TEST(t == doc.termlist_end());
1027 
1028  // Test the removing all positions doesn't remove the term if the wdf is
1029  // still non-zero.
1030  doc.add_posting("foo", 123, 2);
1031  TEST_EQUAL(doc.remove_postings("foo", 1, 200), 1);
1032  t = doc.termlist_begin();
1033  TEST(t != doc.termlist_end());
1035  TEST_EQUAL(t.get_wdf(), 1);
1036 
1037  // Test removing the last posting is handled correctly (this case is
1038  // special-cased internally to be O(1)).
1039  t = doc.termlist_begin();
1040  doc.add_posting("foo", 12);
1041  doc.add_posting("foo", 23);
1042  pi = t.positionlist_begin();
1043  doc.remove_posting("foo", 23);
1044  TEST_EQUAL(*pi, 12);
1045  ++pi;
1046  TEST_EQUAL(*pi, 23);
1047  ++pi;
1048  TEST(pi == t.positionlist_end());
1049 }
1050 
1051 [[noreturn]]
1052 static void
1054 {
1055  // GCC 9 was giving a warning on the next line with -Wdeprecated-copy
1056  // (which is enabled by -Wextra).
1057  throw error;
1058 }
1059 
1061 DEFINE_TESTCASE(errorcopyctor, !backend) {
1062  Xapian::RangeError e("test");
1063  try {
1065  } catch (Xapian::Error&) {
1066  return;
1067  }
1068  FAIL_TEST("Expected exception to be thrown");
1069 }
1070 
1071 DEFINE_TESTCASE(emptydbbounds, !backend) {
1072  Xapian::Database db;
1075  // We always returned 1 here in the initial implementation.
1078 }
1079 
1080 // Test ESetIterator iterator_traits.
1081 DEFINE_TESTCASE(stlesetiterator, !backend) {
1082  Xapian::ESet eset;
1083  vector<string> v;
1084  // This gave a compile error with stdc++ and -DGLIBCXX_DEBUG in 1.4.30:
1085  v.insert(v.begin(), eset.begin(), eset.end());
1086 }
1087 
1088 // Test MSetIterator iterator_traits.
1089 DEFINE_TESTCASE(stlmsetiterator, !backend) {
1090  Xapian::MSet mset;
1091  vector<Xapian::docid> v;
1092  // In Xapian <= 1.4.30 this gave a compile error with libc++, or
1093  // with stdc++ and -DGLIBCXX_DEBUG:
1094  v.insert(v.begin(), mset.begin(), mset.end());
1095 }
1096 
1097 // Test PositionIterator iterator_traits.
1098 DEFINE_TESTCASE(stlpositioniterator, !backend) {
1099  Xapian::Database db;
1100  vector<Xapian::termpos> v;
1101  if (db.get_doccount() > 0) {
1102  // In Xapian <= 1.4.30 this gave a compile error with stdc++ and
1103  // -DGLIBCXX_DEBUG:
1104  v.insert(v.begin(),
1105  db.positionlist_begin(1, ""),
1106  db.positionlist_end(1, ""));
1107  }
1108 }
1109 
1110 // Test PostingIterator iterator_traits.
1111 DEFINE_TESTCASE(stlpostingiterator, !backend) {
1112  Xapian::Database db;
1113  vector<Xapian::docid> v;
1114  // In Xapian <= 1.4.30 this gave a compile error with stdc++ and
1115  // -DGLIBCXX_DEBUG:
1116  v.insert(v.begin(), db.postlist_begin(""), db.postlist_end(""));
1117 }
1118 
1119 // Test TermIterator iterator_traits.
1120 DEFINE_TESTCASE(stltermiterator, !backend) {
1121  Xapian::Document doc;
1122  vector<string> v;
1123  // In Xapian <= 1.4.30 this gave a compile error with stdc++ and
1124  // -DGLIBCXX_DEBUG:
1125  v.insert(v.begin(), doc.termlist_begin(), doc.termlist_end());
1126 }
1127 
1128 // Test Utf8Iterator iterator_traits.
1129 DEFINE_TESTCASE(stlutf8iterator, !backend) {
1130  vector<unsigned> v;
1131  // In Xapian <= 1.4.30 this gave a compile error with stdc++ and
1132  // -DGLIBCXX_DEBUG:
1133  v.insert(v.begin(), Xapian::Utf8Iterator(""), Xapian::Utf8Iterator());
1134 }
1135 
1136 // Test ValueIterator iterator_traits.
1137 DEFINE_TESTCASE(stlvalueiterator, !backend) {
1138  Xapian::Document doc;
1139  vector<string> v;
1140  // In Xapian <= 1.4.30 this gave a compile error with stdc++ and
1141  // -DGLIBCXX_DEBUG:
1142  v.insert(v.begin(), doc.values_begin(), doc.values_end());
1143 }
DEFINE_TESTCASE(version1, !backend)
Definition: api_none.cc:40
#define singlesubquery1_(OP)
#define singlesubquery3_(OP)
#define singlesubquery2_(OP)
#define lit_a
static void errorcopyctor_helper(Xapian::Error &error)
Definition: api_none.cc:1053
#define pairwisequery1_(OP)
#define lit_b
Xapian::Database get_database(const string &dbname)
Definition: apitest.cc:47
test functionality of the Xapian API
DestroyedFlag(bool &destroyed_)
Definition: api_none.cc:297
bool & destroyed
Definition: api_none.cc:294
TestExpandDecider(bool &destroyed_)
Definition: api_none.cc:794
DestroyedFlag destroyed
Definition: api_none.cc:791
bool operator()(const string &) const override
Do we want this term in the ESet?
Definition: api_none.cc:796
TestFieldProcessor(bool &destroyed_)
Definition: api_none.cc:399
DestroyedFlag destroyed
Definition: api_none.cc:396
Xapian::Query operator()(const string &str) override
Convert a field-prefixed string to a Query object.
Definition: api_none.cc:401
string operator()(const Xapian::Document &) const override
Build a key string for a Document.
Definition: api_none.cc:706
TestKeyMaker(bool &destroyed_)
Definition: api_none.cc:704
DestroyedFlag destroyed
Definition: api_none.cc:701
DestroyedFlag destroyed
Definition: api_none.cc:467
void operator()(const Xapian::Document &, double) override
Register a document with the match spy.
Definition: api_none.cc:472
TestMatchSpy(bool &destroyed_)
Definition: api_none.cc:470
Xapian::Query operator()(const std::string &, const std::string &) override
Check for a valid range of this type.
Definition: api_none.cc:313
DestroyedFlag destroyed
Definition: api_none.cc:307
TestRangeProcessor(bool &destroyed_)
Definition: api_none.cc:310
DestroyedFlag destroyed
Definition: api_none.cc:538
bool operator()(const std::string &) const override
Is term a stop-word?
Definition: api_none.cc:543
TestStopper(bool &destroyed_)
Definition: api_none.cc:541
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::termcount get_unique_terms_lower_bound() const
Get a lower bound on the unique terms size of a document in this DB.
Definition: database.cc:323
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
PositionIterator positionlist_begin(Xapian::docid did, std::string_view term) const
Start iterating positions for a term in a document.
Definition: database.cc:221
Xapian::termcount get_doclength(Xapian::docid did) const
Get the length of a specified document.
Definition: database.cc:341
Xapian::TermIterator metadata_keys_end(std::string_view={}) const noexcept
End iterator corresponding to metadata_keys_begin().
Definition: database.h:576
Xapian::termcount get_unique_terms_upper_bound() const
Get an upper bound on the unique terms size of a document in this DB.
Definition: database.cc:329
TermIterator allterms_end(std::string_view={}) const noexcept
End iterator corresponding to allterms_begin(prefix).
Definition: database.h:307
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
Xapian::docid get_lastdocid() const
Get the highest document id which has been used in the database.
Definition: database.cc:239
TermIterator allterms_begin(std::string_view prefix={}) const
Start iterating all terms in the database with a given prefix.
Definition: database.cc:209
ValueIterator valuestream_end(Xapian::valueno) const noexcept
Return end iterator corresponding to valuestream_begin().
Definition: database.h:421
Xapian::termcount get_doclength_upper_bound() const
Get an upper bound on the length of a document in this DB.
Definition: database.cc:308
Xapian::Document get_document(Xapian::docid did, unsigned flags=0) const
Get a document from the database.
Definition: database.cc:368
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
void add_boolean_term(std::string_view term)
Add a boolean filter term to the document.
Definition: document.h:145
Xapian::docid get_docid() const
Get the document ID this document came from.
Definition: document.cc:69
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
Xapian::valueno values_count() const
Count the value slots used in this document.
Definition: document.cc:203
ValueIterator values_begin() const
Start iterating the values in this document.
Definition: document.cc:208
void remove_term(std::string_view term)
Remove a term from this document.
Definition: document.cc:96
void remove_posting(std::string_view term, Xapian::termpos term_pos, Xapian::termcount wdf_dec=1)
Remove posting for a term.
Definition: document.cc:122
TermIterator termlist_end() const noexcept
End iterator corresponding to termlist_begin().
Definition: document.h:219
Xapian::termcount termlist_count() const
Return the number of distinct terms in this document.
Definition: document.cc:174
TermIterator termlist_begin() const
Start iterating the terms in this document.
Definition: document.cc:179
void clear_values()
Clear all value slots in this document.
Definition: document.cc:197
std::string get_description() const
Return a string describing this object.
Definition: document.cc:226
void clear_terms()
Clear all terms from the document.
Definition: document.cc:168
Xapian::termpos remove_postings(std::string_view term, Xapian::termpos term_pos_first, Xapian::termpos term_pos_last, Xapian::termcount wdf_dec=1)
Remove a range of postings for a term.
Definition: document.cc:144
ValueIterator values_end() const noexcept
End iterator corresponding to values_begin().
Definition: document.h:259
void add_value(Xapian::valueno slot, std::string_view value)
Add a value to a slot in this document.
Definition: document.cc:191
void add_posting(std::string_view term, Xapian::termpos term_pos, Xapian::termcount wdf_inc=1)
Add a posting for a term.
Definition: document.cc:111
Class representing a list of search results.
Definition: eset.h:42
ESetIterator end() const
Return iterator pointing to just after the last item in this ESet.
Definition: eset.h:329
ESetIterator begin() const
Return iterator pointing to the first item in this ESet.
Definition: eset.h:324
Querying session.
Definition: enquire.h:57
void add_matchspy(MatchSpy *spy) XAPIAN_NONNULL()
Add a matchspy.
Definition: enquire.cc:179
void set_sort_by_key(KeyMaker *sorter, bool reverse) XAPIAN_NONNULL()
Set the sorting to be by key generated from values only.
Definition: enquire.cc:112
ESet get_eset(termcount maxitems, const RSet &rset, int flags=0, const ExpandDecider *edecider=NULL, double min_weight=0.0) const
Perform query expansion.
Definition: enquire.cc:231
void set_sort_by_relevance_then_key(KeyMaker *sorter, bool reverse) XAPIAN_NONNULL()
Set the sorting to be by relevance, then by keys generated from values.
Definition: enquire.cc:153
void set_sort_by_key_then_relevance(KeyMaker *sorter, bool reverse) XAPIAN_NONNULL()
Set the sorting to be by keys generated from values, then by relevance for documents with identical k...
Definition: enquire.cc:132
static const int INCLUDE_QUERY_TERMS
Flag telling get_eset() to allow query terms in Xapian::ESet.
Definition: enquire.h:469
All exceptions thrown by Xapian are subclasses of Xapian::Error.
Definition: error.h:41
ExpandDecider subclass which rejects terms using two ExpandDeciders.
Definition: expanddecider.h:88
Virtual base class for expand decider functor.
Definition: expanddecider.h:38
ExpandDecider * release()
Start reference counting this object.
Definition: expanddecider.h:65
Base class for field processors.
Definition: queryparser.h:468
FieldProcessor * release()
Start reference counting this object.
Definition: queryparser.h:497
InvalidArgumentError indicates an invalid parameter value was passed to the API.
Definition: error.h:229
InvalidOperationError indicates the API was used in an invalid way.
Definition: error.h:271
Virtual base class for key making functors.
Definition: keymaker.h:44
KeyMaker * release()
Start reference counting this object.
Definition: keymaker.h:123
Class representing a list of search results.
Definition: mset.h:46
MSetIterator begin() const
Return iterator pointing to the first item in this MSet.
Definition: mset.h:786
MSetIterator end() const
Return iterator pointing to just after the last item in this MSet.
Definition: mset.h:791
Abstract base class for match spies.
Definition: matchspy.h:50
MatchSpy * release()
Start reference counting this object.
Definition: matchspy.h:184
Class for iterating over term positions.
Build a Xapian::Query object from a user query string.
Definition: queryparser.h:516
void add_rangeprocessor(Xapian::RangeProcessor *range_proc, const std::string *grouping=NULL)
Register a RangeProcessor.
Definition: queryparser.cc:247
void add_prefix(std::string_view field, std::string_view prefix)
Add a free-text field term prefix.
Definition: queryparser.cc:200
void set_stopper(const Stopper *stop=NULL)
Set the stopper.
Definition: queryparser.cc:87
Class representing a query.
Definition: query.h:45
std::string get_description() const
Return a string describing this object.
Definition: query.cc:307
@ OP_MAX
Pick the maximum weight of any subquery.
Definition: query.h:249
@ OP_XOR
Match documents which an odd number of subqueries match.
Definition: query.h:107
@ OP_AND_MAYBE
Match the first subquery taking extra weight from other subqueries.
Definition: query.h:118
@ OP_NEAR
Match only documents where all subqueries match near each other.
Definition: query.h:140
@ OP_ELITE_SET
Pick the best N subqueries and combine with OP_OR.
Definition: query.h:215
@ OP_AND
Match only documents which all subqueries match.
Definition: query.h:84
@ OP_OR
Match documents which at least one subquery matches.
Definition: query.h:92
@ OP_FILTER
Match like OP_AND but only taking weight from the first subquery.
Definition: query.h:128
@ OP_PHRASE
Match only documents where all subqueries match near and in order.
Definition: query.h:152
@ OP_SYNONYM
Match like OP_OR but weighting as if a single term.
Definition: query.h:239
@ OP_AND_NOT
Match documents which the first subquery matches but no others do.
Definition: query.h:99
static const Xapian::Query MatchNothing
A query matching no documents.
Definition: query.h:64
bool empty() const noexcept
Check if this query is Xapian::Query::MatchNothing.
Definition: query.h:661
static const Xapian::Query MatchAll
A query matching all documents.
Definition: query.h:75
Class representing a set of documents judged as relevant.
Definition: rset.h:39
void add_document(Xapian::docid did)
Mark a document as relevant.
Definition: rset.cc:55
RangeError indicates an attempt to access outside the bounds of a container.
Definition: error.h:959
Base class for range processors.
Definition: queryparser.h:140
RangeProcessor * release()
Start reference counting this object.
Definition: queryparser.h:232
Abstract base class for stop-word decision functor.
Definition: queryparser.h:50
Stopper * release()
Start reference counting this object.
Definition: queryparser.h:80
Parses a piece of text and generate terms.
Definition: termgenerator.h:49
void index_text(const Xapian::Utf8Iterator &itor, Xapian::termcount wdf_inc=1, std::string_view prefix={})
Index some text.
void set_document(const Xapian::Document &doc)
Set the current document.
void set_stopper(const Xapian::Stopper *stop=NULL)
Set the Xapian::Stopper object to be used for identifying stopwords.
Class for iterating over a list of terms.
Definition: termiterator.h:41
void skip_to(std::string_view term)
Advance the iterator to term term.
PositionIterator positionlist_end() const noexcept
Return an end PositionIterator for the current term.
Definition: termiterator.h:109
Xapian::termcount positionlist_count() const
Return the length of the position list for the current position.
Xapian::termcount get_wdf() const
Return the wdf for the term at the current position.
PositionIterator positionlist_begin() const
Return a PositionIterator for the current term.
An iterator which returns Unicode character values from a UTF-8 encoded string.
Definition: unicode.h:39
This class provides read/write access to a database.
Definition: database.h:964
void begin_transaction(bool flushed=true)
Begin a transaction.
Definition: database.cc:549
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
string term
PositionList * p
Xapian::termpos pos
string str(int value)
Convert int to std::string.
Definition: str.cc:91
The Xapian namespace contains public interfaces for the Xapian library.
Definition: compactor.cc:82
int major_version()
Report the major version of the library which the program is linked with.
Definition: xapian.h:128
int revision()
Report the revision of the library which the program is linked with.
Definition: xapian.h:146
const char * version_string()
Report the version string of the library which the program is linked with.
Definition: xapian.h:119
int minor_version()
Report the minor version of the library which the program is linked with.
Definition: xapian.h:137
unsigned XAPIAN_TERMPOS_BASE_TYPE termpos
A term position within a document or query.
Definition: types.h:75
Convert types to std::string.
bool startswith(std::string_view s, char pfx)
Definition: stringutils.h:56
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
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.