xapian-core  1.4.25
api_posdb.cc
Go to the documentation of this file.
1 
4 /* Copyright 1999,2000,2001 BrightStation PLC
5  * Copyright 2002 Ananova Ltd
6  * Copyright 2002,2003,2004,2005,2006,2007,2009,2016 Olly Betts
7  *
8  * This program is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU General Public License as
10  * published by the Free Software Foundation; either version 2 of the
11  * License, or (at your option) any later version.
12  *
13  * This program is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU General Public License for more details.
17  *
18  * You should have received a copy of the GNU General Public License
19  * along with this program; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301
21  * USA
22  */
23 
24 #include <config.h>
25 
26 #include "api_posdb.h"
27 
28 #include <string>
29 #include <vector>
30 
31 using namespace std;
32 
33 #include <xapian.h>
34 #include "testsuite.h"
35 #include "testutils.h"
36 
37 #include "apitest.h"
38 
40 DEFINE_TESTCASE(near1, positional) {
41  Xapian::Database mydb(get_database("apitest_phrase"));
42  Xapian::Enquire enquire(mydb);
43  Xapian::Stem stemmer("english");
45 
46  // make a query
47  vector<Xapian::Query> subqs;
48  Xapian::Query q;
49  subqs.push_back(Xapian::Query(stemmer("phrase")));
50  subqs.push_back(Xapian::Query(stemmer("fridge")));
51  q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 2);
52  enquire.set_query(q);
53 
54  // retrieve the top ten results
55  Xapian::MSet mymset = enquire.get_mset(0, 10);
56  mset_expect_order(mymset);
57 
58  subqs.clear();
59  subqs.push_back(Xapian::Query(stemmer("phrase")));
60  subqs.push_back(Xapian::Query(stemmer("near")));
61  q = Xapian::Query(Xapian::Query::OP_NEAR, subqs.begin(), subqs.end(), 2);
62  enquire.set_query(q);
63 
64  // retrieve the top ten results
65  mymset = enquire.get_mset(0, 10);
66  mset_expect_order(mymset, 3);
67 
68  subqs.clear();
69  subqs.push_back(Xapian::Query(stemmer("phrase")));
70  subqs.push_back(Xapian::Query(stemmer("near")));
71  q = Xapian::Query(Xapian::Query::OP_NEAR, subqs.begin(), subqs.end(), 3);
72  enquire.set_query(q);
73 
74  // retrieve the top ten results
75  mymset = enquire.get_mset(0, 10);
76  mset_expect_order(mymset, 1, 3);
77 
78  subqs.clear();
79  subqs.push_back(Xapian::Query(stemmer("phrase")));
80  subqs.push_back(Xapian::Query(stemmer("near")));
81  q = Xapian::Query(Xapian::Query::OP_NEAR, subqs.begin(), subqs.end(), 5);
82  enquire.set_query(q);
83 
84  // retrieve the top ten results
85  mymset = enquire.get_mset(0, 10);
86  mset_expect_order(mymset, 1, 3);
87 
88  subqs.clear();
89  subqs.push_back(Xapian::Query(stemmer("phrase")));
90  subqs.push_back(Xapian::Query(stemmer("near")));
91  q = Xapian::Query(Xapian::Query::OP_NEAR, subqs.begin(), subqs.end(), 6);
92  enquire.set_query(q);
93 
94  // retrieve the top ten results
95  mymset = enquire.get_mset(0, 10);
96  mset_expect_order(mymset, 1, 2, 3);
97 
98  subqs.clear();
99  subqs.push_back(Xapian::Query(stemmer("leave")));
100  subqs.push_back(Xapian::Query(stemmer("fridge")));
101  subqs.push_back(Xapian::Query(stemmer("on")));
102  q = Xapian::Query(Xapian::Query::OP_NEAR, subqs.begin(), subqs.end(), 3);
103  enquire.set_query(q);
104 
105  // retrieve the top ten results
106  mymset = enquire.get_mset(0, 10);
107  mset_expect_order(mymset, 4, 5, 6, 7, 8, 9);
108 
109  subqs.clear();
110  subqs.push_back(Xapian::Query(stemmer("leave")));
111  subqs.push_back(Xapian::Query(stemmer("fridge")));
112  subqs.push_back(Xapian::Query(stemmer("on")));
113  q = Xapian::Query(Xapian::Query::OP_NEAR, subqs.begin(), subqs.end(), 4);
114  enquire.set_query(q);
115 
116  // retrieve the top ten results
117  mymset = enquire.get_mset(0, 10);
118  mset_expect_order(mymset, 4, 5, 6, 7, 8, 9, 10);
119 
120  subqs.clear();
121  subqs.push_back(Xapian::Query(stemmer("leave")));
122  subqs.push_back(Xapian::Query(stemmer("fridge")));
123  subqs.push_back(Xapian::Query(stemmer("on")));
124  q = Xapian::Query(Xapian::Query::OP_NEAR, subqs.begin(), subqs.end(), 5);
125  enquire.set_query(q);
126 
127  // retrieve the top ten results
128  mymset = enquire.get_mset(0, 10);
129  mset_expect_order(mymset, 4, 5, 6, 7, 8, 9, 10, 11);
130 
131  subqs.clear();
132  subqs.push_back(Xapian::Query(stemmer("leave")));
133  subqs.push_back(Xapian::Query(stemmer("fridge")));
134  subqs.push_back(Xapian::Query(stemmer("on")));
135  q = Xapian::Query(Xapian::Query::OP_NEAR, subqs.begin(), subqs.end(), 6);
136  enquire.set_query(q);
137 
138  // retrieve the top ten results
139  mymset = enquire.get_mset(0, 10);
140  mset_expect_order(mymset, 4, 5, 6, 7, 8, 9, 10, 11, 12);
141 
142  subqs.clear();
143  subqs.push_back(Xapian::Query(stemmer("leave")));
144  subqs.push_back(Xapian::Query(stemmer("fridge")));
145  subqs.push_back(Xapian::Query(stemmer("on")));
146  q = Xapian::Query(Xapian::Query::OP_NEAR, subqs.begin(), subqs.end(), 7);
147  enquire.set_query(q);
148 
149  // retrieve the top twenty results
150  mymset = enquire.get_mset(0, 20);
151  mset_expect_order(mymset, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13);
152 
153  subqs.clear();
154  subqs.push_back(Xapian::Query(stemmer("leave")));
155  subqs.push_back(Xapian::Query(stemmer("fridge")));
156  subqs.push_back(Xapian::Query(stemmer("on")));
157  q = Xapian::Query(Xapian::Query::OP_NEAR, subqs.begin(), subqs.end(), 8);
158  enquire.set_query(q);
159 
160  // retrieve the top twenty results
161  mymset = enquire.get_mset(0, 20);
162  mset_expect_order(mymset, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);
163 
164  subqs.clear();
165  subqs.push_back(Xapian::Query(stemmer("leave")));
166  subqs.push_back(Xapian::Query(stemmer("fridge")));
167  subqs.push_back(Xapian::Query(stemmer("on")));
168  // test really large window size
169  q = Xapian::Query(Xapian::Query::OP_NEAR, subqs.begin(), subqs.end(), 999999999);
170  enquire.set_query(q);
171 
172  // retrieve the top twenty results
173  mymset = enquire.get_mset(0, 20);
174  mset_expect_order(mymset, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14);
175 }
176 
178 DEFINE_TESTCASE(near2, positional) {
179  Xapian::Database mydb(get_database("apitest_phrase"));
180  Xapian::Enquire enquire(mydb);
181  Xapian::Stem stemmer("english");
183  Xapian::MSet mymset;
184 
185  // make a query
186  vector<Xapian::Query> subqs;
187  Xapian::Query q;
188  subqs.push_back(Xapian::Query(Xapian::Query::OP_AND,
189  Xapian::Query(stemmer("phrase")),
190  Xapian::Query(stemmer("near"))));
191  subqs.push_back(Xapian::Query(stemmer("and")));
193  q = Xapian::Query(q.OP_NEAR, subqs.begin(), subqs.end(), 2);
194  enquire.set_query(q);
195 
196  // retrieve the top ten results
197  mymset = enquire.get_mset(0, 10)
198  );
199 #if 0 // Disable until we reimplement this.
200  mset_expect_order(mymset, 1);
201 
202  subqs.clear();
203  subqs.push_back(Xapian::Query(Xapian::Query::OP_AND,
204  Xapian::Query(stemmer("phrase")),
205  Xapian::Query(stemmer("near"))));
206  subqs.push_back(Xapian::Query(stemmer("operator")));
207  q = Xapian::Query(Xapian::Query::OP_NEAR, subqs.begin(), subqs.end(), 2);
208  enquire.set_query(q);
209 
210  // retrieve the top ten results
211  mymset = enquire.get_mset(0, 10);
212  mset_expect_order(mymset, 2);
213 
214  subqs.clear();
215  subqs.push_back(Xapian::Query(stemmer("operator")));
216  subqs.push_back(Xapian::Query(Xapian::Query::OP_AND,
217  Xapian::Query(stemmer("phrase")),
218  Xapian::Query(stemmer("near"))));
219  q = Xapian::Query(Xapian::Query::OP_NEAR, subqs.begin(), subqs.end(), 2);
220  enquire.set_query(q);
221 
222  // retrieve the top ten results
223  mymset = enquire.get_mset(0, 10);
224  mset_expect_order(mymset, 2);
225 #endif
226 }
227 
229 DEFINE_TESTCASE(phrase1, positional) {
230  Xapian::Database mydb(get_database("apitest_phrase"));
231  Xapian::Enquire enquire(mydb);
232  Xapian::Stem stemmer("english");
234 
235  // make a query
236  vector<Xapian::Query> subqs;
237  Xapian::Query q;
238  subqs.push_back(Xapian::Query(stemmer("phrase")));
239  subqs.push_back(Xapian::Query(stemmer("fridge")));
240  q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 2);
241  enquire.set_query(q);
242 
243  // retrieve the top ten results
244  Xapian::MSet mymset = enquire.get_mset(0, 10);
245  mset_expect_order(mymset);
246 
247  subqs.clear();
248  subqs.push_back(Xapian::Query(stemmer("phrase")));
249  subqs.push_back(Xapian::Query(stemmer("near")));
250  q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 2);
251  enquire.set_query(q);
252 
253  // retrieve the top ten results
254  mymset = enquire.get_mset(0, 10);
255  mset_expect_order(mymset);
256 
257  subqs.clear();
258  subqs.push_back(Xapian::Query(stemmer("phrase")));
259  subqs.push_back(Xapian::Query(stemmer("near")));
260  q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 3);
261  enquire.set_query(q);
262 
263  // retrieve the top ten results
264  mymset = enquire.get_mset(0, 10);
265  mset_expect_order(mymset, 1);
266 
267  subqs.clear();
268  subqs.push_back(Xapian::Query(stemmer("phrase")));
269  subqs.push_back(Xapian::Query(stemmer("near")));
270  q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 5);
271  enquire.set_query(q);
272 
273  // retrieve the top ten results
274  mymset = enquire.get_mset(0, 10);
275  mset_expect_order(mymset, 1);
276 
277  subqs.clear();
278  subqs.push_back(Xapian::Query(stemmer("phrase")));
279  subqs.push_back(Xapian::Query(stemmer("near")));
280  q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 6);
281  enquire.set_query(q);
282 
283  // retrieve the top ten results
284  mymset = enquire.get_mset(0, 10);
285  mset_expect_order(mymset, 1, 2);
286 
287  subqs.clear();
288  subqs.push_back(Xapian::Query(stemmer("leave")));
289  subqs.push_back(Xapian::Query(stemmer("fridge")));
290  subqs.push_back(Xapian::Query(stemmer("on")));
291  q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 3);
292  enquire.set_query(q);
293 
294  // retrieve the top ten results
295  mymset = enquire.get_mset(0, 10);
296  mset_expect_order(mymset, 4);
297 
298  subqs.clear();
299  subqs.push_back(Xapian::Query(stemmer("leave")));
300  subqs.push_back(Xapian::Query(stemmer("fridge")));
301  subqs.push_back(Xapian::Query(stemmer("on")));
302  q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 4);
303  enquire.set_query(q);
304 
305  // retrieve the top ten results
306  mymset = enquire.get_mset(0, 10);
307  mset_expect_order(mymset, 4);
308 
309  subqs.clear();
310  subqs.push_back(Xapian::Query(stemmer("leave")));
311  subqs.push_back(Xapian::Query(stemmer("fridge")));
312  subqs.push_back(Xapian::Query(stemmer("on")));
313  q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 5);
314  enquire.set_query(q);
315 
316  // retrieve the top ten results
317  mymset = enquire.get_mset(0, 10);
318  mset_expect_order(mymset, 4);
319 
320  subqs.clear();
321  subqs.push_back(Xapian::Query(stemmer("leave")));
322  subqs.push_back(Xapian::Query(stemmer("fridge")));
323  subqs.push_back(Xapian::Query(stemmer("on")));
324  q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 6);
325  enquire.set_query(q);
326 
327  // retrieve the top ten results
328  mymset = enquire.get_mset(0, 10);
329  mset_expect_order(mymset, 4);
330 
331  subqs.clear();
332  subqs.push_back(Xapian::Query(stemmer("leave")));
333  subqs.push_back(Xapian::Query(stemmer("fridge")));
334  subqs.push_back(Xapian::Query(stemmer("on")));
335  q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 7);
336  enquire.set_query(q);
337 
338  // retrieve the top twenty results
339  mymset = enquire.get_mset(0, 20);
340  mset_expect_order(mymset, 4);
341 
342  subqs.clear();
343  subqs.push_back(Xapian::Query(stemmer("leave")));
344  subqs.push_back(Xapian::Query(stemmer("fridge")));
345  subqs.push_back(Xapian::Query(stemmer("on")));
346  q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 8);
347  enquire.set_query(q);
348 
349  // retrieve the top 20 results
350  mymset = enquire.get_mset(0, 20);
351  mset_expect_order(mymset, 4);
352 
353  // test really large window size
354  subqs.clear();
355  subqs.push_back(Xapian::Query(stemmer("leave")));
356  subqs.push_back(Xapian::Query(stemmer("fridge")));
357  subqs.push_back(Xapian::Query(stemmer("on")));
358  q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 999999999);
359  enquire.set_query(q);
360 
361  // retrieve the top 20 results
362  mymset = enquire.get_mset(0, 20);
363  mset_expect_order(mymset, 4);
364 
365  // regression test (was matching doc 15, should fail)
366  subqs.clear();
367  subqs.push_back(Xapian::Query(stemmer("first")));
368  subqs.push_back(Xapian::Query(stemmer("second")));
369  subqs.push_back(Xapian::Query(stemmer("third")));
370  q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 9);
371  enquire.set_query(q);
372 
373  // retrieve the top ten results
374  mymset = enquire.get_mset(0, 10);
375  mset_expect_order(mymset);
376 
377  // regression test (should match doc 15, make sure still does with fix)
378  subqs.clear();
379  subqs.push_back(Xapian::Query(stemmer("first")));
380  subqs.push_back(Xapian::Query(stemmer("second")));
381  subqs.push_back(Xapian::Query(stemmer("third")));
382  q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 10);
383  enquire.set_query(q);
384 
385  // retrieve the top ten results
386  mymset = enquire.get_mset(0, 10);
387  mset_expect_order(mymset, 15);
388 
389  // regression test (phrase matching was getting order wrong when
390  // build_and_tree reordered vector of PostLists)
391  subqs.clear();
392  subqs.push_back(Xapian::Query(stemmer("milk")));
393  subqs.push_back(Xapian::Query(stemmer("rare")));
394  q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 2);
395  enquire.set_query(q);
396 
397  // retrieve the top ten results
398  mymset = enquire.get_mset(0, 10);
399  mset_expect_order(mymset, 16);
400 
401  // regression test (phrase matching was getting order wrong when
402  // build_and_tree reordered vector of PostLists)
403  subqs.clear();
404  subqs.push_back(Xapian::Query(stemmer("rare")));
405  subqs.push_back(Xapian::Query(stemmer("milk")));
406  q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 2);
407  enquire.set_query(q);
408 
409  // retrieve the top ten results
410  mymset = enquire.get_mset(0, 10);
411  mset_expect_order(mymset, 17);
412 }
413 
415 DEFINE_TESTCASE(phrase2, positional) {
416  Xapian::Database mydb(get_database("apitest_phrase"));
417  Xapian::Enquire enquire(mydb);
418  Xapian::Stem stemmer("english");
420  Xapian::MSet mymset;
421 
422  // make a query
423  vector<Xapian::Query> subqs;
424  Xapian::Query q;
425  subqs.push_back(Xapian::Query(Xapian::Query::OP_AND,
426  Xapian::Query(stemmer("phrase")),
427  Xapian::Query(stemmer("near"))));
428  subqs.push_back(Xapian::Query(stemmer("and")));
430  q = Xapian::Query(q.OP_PHRASE, subqs.begin(), subqs.end(), 2);
431  enquire.set_query(q);
432 
433  // retrieve the top ten results
434  mymset = enquire.get_mset(0, 10)
435  );
436 #if 0 // Disable until we reimplement this.
437  mset_expect_order(mymset);
438 
439  subqs.clear();
440  subqs.push_back(Xapian::Query(Xapian::Query::OP_AND,
441  Xapian::Query(stemmer("phrase")),
442  Xapian::Query(stemmer("near"))));
443  subqs.push_back(Xapian::Query(stemmer("operator")));
444  q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 2);
445  enquire.set_query(q);
446 
447  // retrieve the top ten results
448  mymset = enquire.get_mset(0, 10);
449  mset_expect_order(mymset, 2);
450 
451  subqs.clear();
452  subqs.push_back(Xapian::Query(stemmer("operator")));
453  subqs.push_back(Xapian::Query(Xapian::Query::OP_AND,
454  Xapian::Query(stemmer("phrase")),
455  Xapian::Query(stemmer("near"))));
456  q = Xapian::Query(Xapian::Query::OP_PHRASE, subqs.begin(), subqs.end(), 2);
457  enquire.set_query(q);
458 
459  // retrieve the top ten results
460  mymset = enquire.get_mset(0, 10);
461  mset_expect_order(mymset);
462 #endif
463 }
464 
466 DEFINE_TESTCASE(poslist1, positional) {
467  Xapian::Database mydb(get_database("apitest_poslist"));
468 
469  Xapian::Stem stemmer("english");
470  string term = stemmer("sponge");
471 
472  Xapian::PositionIterator pli = mydb.positionlist_begin(2, term);
473 
474  TEST(pli != mydb.positionlist_end(2, term));
475  TEST_EQUAL(*pli, 1);
476  pli++;
477  TEST(pli != mydb.positionlist_end(2, term));
478  TEST_EQUAL(*pli, 2);
479  pli++;
480  TEST(pli != mydb.positionlist_end(2, term));
481  TEST_EQUAL(*pli, 3);
482  pli++;
483  TEST(pli != mydb.positionlist_end(2, term));
484  TEST_EQUAL(*pli, 5);
485  pli++;
486  TEST(pli != mydb.positionlist_end(2, term));
487  TEST_EQUAL(*pli, 8);
488  pli++;
489  TEST(pli != mydb.positionlist_end(2, term));
490  TEST_EQUAL(*pli, 13);
491  pli++;
492  TEST(pli != mydb.positionlist_end(2, term));
493  TEST_EQUAL(*pli, 21);
494  pli++;
495  TEST(pli != mydb.positionlist_end(2, term));
496  TEST_EQUAL(*pli, 34);
497  pli++;
498  TEST(pli == mydb.positionlist_end(2, term));
499 }
500 
501 DEFINE_TESTCASE(poslist2, positional && writable) {
503 
504  Xapian::Document doc;
505  doc.add_term("nopos");
506  Xapian::docid did = db.add_document(doc);
507 
508  // Check what happens when term doesn't exist - should give an empty list.
509  // Threw RangeError in Xapian < 1.1.0.
510  TEST_EQUAL(db.positionlist_begin(did, "nosuchterm"),
511  db.positionlist_end(did, "nosuchterm"));
512 
513  // Check what happens when the document doesn't even exist - should give
514  // an empty list. Threw DocNotFoundError in Xapian < 1.1.0.
515  TEST_EQUAL(db.positionlist_begin(123, "nosuchterm"),
516  db.positionlist_end(123, "nosuchterm"));
517 
518  TEST_EQUAL(db.positionlist_begin(did, "nopos"),
519  db.positionlist_end(did, "nopos"));
520 
521  Xapian::Document doc2 = db.get_document(did);
522 
523  Xapian::TermIterator term = doc2.termlist_begin();
524 
525  {
527  TEST_EQUAL(i, term.positionlist_end());
528  }
529 
530  Xapian::Document doc3;
531  doc3.add_posting("hadpos", 1);
532  Xapian::docid did2 = db.add_document(doc3);
533 
534  Xapian::Document doc4 = db.get_document(did2);
535  doc4.remove_posting("hadpos", 1);
536  db.replace_document(did2, doc4);
537 
538  {
539  Xapian::PositionIterator i = db.positionlist_begin(did2, "hadpos");
540  TEST_EQUAL(i, db.positionlist_end(did2, "hadpos"));
541  }
542 
543  db.delete_document(did);
544  // Check what happens when the document doesn't exist (but once did).
545  TEST_EQUAL(db.positionlist_begin(did, "nosuchterm"),
546  db.positionlist_end(did, "nosuchterm"));
547 }
548 
551 DEFINE_TESTCASE(poslist3, positional && writable) {
553 
554  Xapian::Document document;
555  document.add_posting("foo", 5);
556  document.add_posting("foo", 8);
557  document.add_posting("foo", 10);
558  document.add_posting("foo", 12);
559  db.add_document(document);
560 
562  Xapian::PositionIterator pl_end = db.positionlist_end(1, "foo");
563 
564  TEST(pl != pl_end);
565  TEST_EQUAL(*pl, 5);
566  ++pl;
567  TEST(pl != pl_end);
568  TEST_EQUAL(*pl, 8);
569  ++pl;
570  TEST(pl != pl_end);
571  TEST_EQUAL(*pl, 10);
572  ++pl;
573  TEST(pl != pl_end);
574  TEST_EQUAL(*pl, 12);
575  ++pl;
576  TEST(pl == pl_end);
577 
578  pl = db.positionlist_begin(1, "foo");
579  pl.skip_to(5);
580  TEST(pl != pl_end);
581  TEST_EQUAL(*pl, 5);
582 
583  pl.skip_to(9);
584  TEST(pl != pl_end);
585  TEST_EQUAL(*pl, 10);
586 
587  ++pl;
588  TEST(pl != pl_end);
589  TEST_EQUAL(*pl, 12);
590 
591  pl.skip_to(12);
592  TEST(pl != pl_end);
593  TEST_EQUAL(*pl, 12);
594 
595  pl.skip_to(13);
596  TEST(pl == pl_end);
597 }
598 
599 // Regression test - in 0.9.4 (and many previous versions) you couldn't get a
600 // PositionIterator from a TermIterator from Database::termlist_begin().
601 //
602 // Also test that positionlist_count() is implemented for this case, which it
603 // wasn't in 1.0.2 and earlier.
604 DEFINE_TESTCASE(positfromtermit1, positional) {
605  Xapian::Database db(get_database("apitest_phrase"));
607  TEST_NOT_EQUAL(t, db.termlist_end(7));
608  Xapian::PositionIterator p = t.positionlist_begin();
609  TEST_NOT_EQUAL(p, t.positionlist_end());
610 
611  try {
612  TEST_EQUAL(t.positionlist_count(), 1);
613  t.skip_to("on");
614  TEST_NOT_EQUAL(t, db.termlist_end(7));
615  TEST_EQUAL(t.positionlist_count(), 2);
616  } catch (const Xapian::UnimplementedError &) {
617  SKIP_TEST("TermList::positionlist_count() not yet implemented for this backend");
618  }
619 }
Xapian::Document get_document(Xapian::docid did) const
Get a document from the database, given its document id.
Definition: omdatabase.cc:490
Xapian::docid add_document(const Xapian::Document &document)
Add a new document to the database.
Definition: omdatabase.cc:902
PositionIterator positionlist_end(Xapian::docid, const std::string &) const
Corresponding end iterator to positionlist_begin().
Definition: database.h:254
TermIterator termlist_begin(Xapian::docid did) const
An iterator pointing to the start of the termlist for a given document.
Definition: omdatabase.cc:198
#define TEST(a)
Test a condition, without an additional explanation for failure.
Definition: testsuite.h:275
void skip_to(Xapian::termpos termpos)
Advance the iterator to term position termpos.
This class is used to access a database, or a group of databases.
Definition: database.h:68
Class representing a stemming algorithm.
Definition: stem.h:62
PositionIterator positionlist_begin(Xapian::docid did, const std::string &tname) const
An iterator pointing to the start of the position list for a given term in a given document...
Definition: omdatabase.cc:250
Xapian::WritableDatabase get_writable_database(const string &dbname)
Definition: apitest.cc:87
a generic test suite engine
Class representing a list of search results.
Definition: mset.h:44
STL namespace.
MSet get_mset(Xapian::doccount first, Xapian::doccount maxitems, Xapian::doccount checkatleast=0, const RSet *omrset=0, const MatchDecider *mdecider=0) const
Get (a portion of) the match set for the current query.
Definition: omenquire.cc:932
void replace_document(Xapian::docid did, const Xapian::Document &document)
Replace a given document in the database.
Definition: omdatabase.cc:952
static Xapian::Stem stemmer
Definition: stemtest.cc:41
test functionality of the Xapian API
Class for iterating over a list of terms.
Definition: termiterator.h:41
PositionIterator positionlist_end() const
Return an end PositionIterator for the current term.
Definition: termiterator.h:110
#define TEST_NOT_EQUAL(a, b)
Test for non-equality of two things.
Definition: testsuite.h:305
Class implementing a "boolean" weighting scheme.
Definition: weight.h:422
This class provides read/write access to a database.
Definition: database.h:789
Match only documents where all subqueries match near and in order.
Definition: query.h:152
Public interfaces for the Xapian library.
void delete_document(Xapian::docid did)
Delete a document from the database.
Definition: omdatabase.cc:925
#define TEST_EXCEPTION(TYPE, CODE)
Check that CODE throws exactly Xapian exception TYPE.
Definition: testutils.h:109
Class for iterating over term positions.
TermIterator termlist_end(Xapian::docid) const
Corresponding end iterator to termlist_begin().
Definition: database.h:240
void set_query(const Xapian::Query &query, Xapian::termcount qlen=0)
Set the query to run.
Definition: omenquire.cc:793
void add_posting(const std::string &tname, Xapian::termpos tpos, Xapian::termcount wdfinc=1)
Add an occurrence of a term at a particular position.
Definition: omdocument.cc:128
Match only documents which all subqueries match.
Definition: query.h:84
Xapian::Database get_database(const string &dbname)
Definition: apitest.cc:48
#define SKIP_TEST(MSG)
Skip the current testcase with message MSG.
Definition: testsuite.h:74
This class provides an interface to the information retrieval system for the purpose of searching...
Definition: enquire.h:152
Match only documents where all subqueries match near each other.
Definition: query.h:140
Xapian-specific test helper functions and macros.
void mset_expect_order(const Xapian::MSet &A, Xapian::docid d1, Xapian::docid d2, Xapian::docid d3, Xapian::docid d4, Xapian::docid d5, Xapian::docid d6, Xapian::docid d7, Xapian::docid d8, Xapian::docid d9, Xapian::docid d10, Xapian::docid d11, Xapian::docid d12)
Definition: testutils.cc:225
void set_weighting_scheme(const Weight &weight_)
Set the weighting scheme to use for queries.
Definition: omenquire.cc:819
unsigned XAPIAN_DOCID_BASE_TYPE docid
A unique identifier for a document.
Definition: types.h:52
Class representing a query.
Definition: query.h:46
DEFINE_TESTCASE(near1, positional)
Simple test of NEAR.
Definition: api_posdb.cc:40
#define TEST_EQUAL(a, b)
Test for equality of two things.
Definition: testsuite.h:278
PositionIterator positionlist_begin() const
Return a PositionIterator for the current term.
A handle representing a document in a Xapian database.
Definition: document.h:61
void remove_posting(const std::string &tname, Xapian::termpos tpos, Xapian::termcount wdfdec=1)
Remove a posting of a term from the document.
Definition: omdocument.cc:150
UnimplementedError indicates an attempt to use an unimplemented feature.
Definition: error.h:325
void add_term(const std::string &tname, Xapian::termcount wdfinc=1)
Add a term to the document, without positional information.
Definition: omdocument.cc:140