xapian-core  2.0.0
api_replacedoc.cc
Go to the documentation of this file.
1 
4 /* Copyright 2009 Richard Boulton
5  * Copyright 2015,2016 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_replacedoc.h"
25 
26 #include <string>
27 
28 using namespace std;
29 
30 #include <xapian.h>
31 #include "testsuite.h"
32 #include "testutils.h"
33 
34 #include "apitest.h"
35 #include "dbcheck.h"
36 
37 // Test that positionlists are updated correctly.
38 DEFINE_TESTCASE(poslistupdate1, positional && writable) {
40 
41  Xapian::Document doc;
42  doc.add_posting("pos", 2);
43  doc.add_posting("pos", 3);
44  db.add_document(doc);
45  db.commit();
46 
47  TEST_EQUAL(docterms_to_string(db, 1), "Term(pos, wdf=2, pos=[2, 3])");
48 
49  doc = db.get_document(1);
50  doc.add_term("pos2");
51  db.replace_document(1, doc);
52  db.commit();
54  "Term(pos, wdf=2, pos=[2, 3]), "
55  "Term(pos2, wdf=1)");
56 
57  doc = db.get_document(1);
58  doc.add_posting("pos3", 1);
59  doc.add_posting("pos3", 5);
60  db.replace_document(1, doc);
61  db.commit();
63  "Term(pos, wdf=2, pos=[2, 3]), "
64  "Term(pos2, wdf=1), "
65  "Term(pos3, wdf=2, pos=[1, 5])");
66 
67  doc = db.get_document(1);
68  doc.remove_term("pos");
69  db.replace_document(1, doc);
70  db.commit();
72  "Term(pos2, wdf=1), "
73  "Term(pos3, wdf=2, pos=[1, 5])");
74 
75  // Regression test: the old positionlist fragment used to be left lying
76  // around here.
77  Xapian::PositionIterator posit(db.positionlist_begin(1, "pos"));
78  TEST(posit == db.positionlist_end(1, "pos"));
79 
80  doc = db.get_document(1);
81  doc.remove_term("pos3");
82  db.replace_document(1, doc);
83  db.commit();
85  "Term(pos2, wdf=1)");
86 
87  // Regression test: the old positionlist fragment used to be left lying
88  // around here.
89  Xapian::PositionIterator posit2(db.positionlist_begin(1, "pos3"));
90  TEST(posit2 == db.positionlist_end(1, "pos3"));
91 
92  doc = db.get_document(1);
93  doc.add_term("pos");
94  db.replace_document(1, doc);
95  db.commit();
97  "Term(pos, wdf=1), "
98  "Term(pos2, wdf=1)");
99 }
100 
101 static Xapian::Document
103  Xapian::Document doc;
104  doc.add_term("z0", 0);
105  doc.add_term("z1", 1);
106  return doc;
107 }
108 
109 static string
111  return ", Term(z0, wdf=0), Term(z1, wdf=1)";
112 }
113 
116 DEFINE_TESTCASE(modtermwdf1, writable) {
118 
119  string bdt(basic_docterms());
120 
121  // Add a simple document.
122  Xapian::Document doc1(basic_doc());
123  doc1.add_term("takeaway", 1);
124  db.add_document(doc1);
125 
126  dbcheck(db, 1, 1);
127  TEST_EQUAL(docterms_to_string(db, 1), "Term(takeaway, wdf=1)" + bdt);
128 
129  // Modify the wdf of an existing document, checking stats before commit.
130  Xapian::Document doc2(basic_doc());
131  doc2.add_term("takeaway", 2);
132  db.replace_document(1, doc2);
133  dbcheck(db, 1, 1);
134  TEST_EQUAL(docterms_to_string(db, 1), "Term(takeaway, wdf=2)" + bdt);
135 
136  // Remove a term, and then put it back again.
137  Xapian::Document doc0(basic_doc());
138  db.replace_document(1, doc0);
139  dbcheck(db, 1, 1);
140  TEST_EQUAL(docterms_to_string(db, 1), bdt.substr(2));
141  db.replace_document(1, doc1);
142  dbcheck(db, 1, 1);
143  TEST_EQUAL(docterms_to_string(db, 1), "Term(takeaway, wdf=1)" + bdt);
144 
145  // Remove a term, commit, then put it back, remove it, and put it back.
146  // This is to test the handling of items in the change cache.
147  db.replace_document(1, doc0);
148  db.commit();
149  db.replace_document(1, doc2);
150  db.replace_document(1, doc0);
151  db.replace_document(1, doc2);
152  db.commit();
153  dbcheck(db, 1, 1);
154  TEST_EQUAL(docterms_to_string(db, 1), "Term(takeaway, wdf=2)" + bdt);
155 
156  // Remove a term, and then put it back again without checking stats.
157  db.replace_document(1, doc0);
158  db.replace_document(1, doc2);
159  dbcheck(db, 1, 1);
160  TEST_EQUAL(docterms_to_string(db, 1), "Term(takeaway, wdf=2)" + bdt);
161 
162  // Modify a term, and then put it back again without checking stats.
163  db.replace_document(1, doc1);
164  db.replace_document(1, doc2);
165  dbcheck(db, 1, 1);
166  TEST_EQUAL(docterms_to_string(db, 1), "Term(takeaway, wdf=2)" + bdt);
167 
168  // Modify the wdf of an existing document, checking stats after commit.
169  Xapian::Document doc3(basic_doc());
170  doc3.add_term("takeaway", 3);
171  db.replace_document(1, doc3);
172  db.commit();
173  dbcheck(db, 1, 1);
174  TEST_EQUAL(docterms_to_string(db, 1), "Term(takeaway, wdf=3)" + bdt);
175 
176  // Change a document, without changing its length.
177  Xapian::Document doc3_diff(basic_doc());
178  doc3_diff.add_term("takeaways", 3);
179  db.replace_document(1, doc3_diff);
180  db.commit();
181  dbcheck(db, 1, 1);
182  TEST_EQUAL(docterms_to_string(db, 1), "Term(takeaways, wdf=3)" + bdt);
183 
184  // Put it back.
185  db.replace_document(1, doc3);
186  dbcheck(db, 1, 1);
187  TEST_EQUAL(docterms_to_string(db, 1), "Term(takeaway, wdf=3)" + bdt);
188 
189  // Modify a document taken from the database.
190  Xapian::Document doc4(db.get_document(1));
191  Xapian::Document doc3a(db.get_document(1)); // need this one later
192  doc3a.add_boolean_term("takeaway"); // Pull the document termlist into memory.
193  doc4.add_term("takeaway", 1);
194  db.replace_document(1, doc4);
195  dbcheck(db, 1, 1);
196  TEST_EQUAL(docterms_to_string(db, 1), "Term(takeaway, wdf=4)" + bdt);
197 
198  // Add a document which was previously added and then modified.
199  doc1.add_term("takeaway", 1);
200  db.replace_document(1, doc1);
201  dbcheck(db, 1, 1);
202  TEST_EQUAL(docterms_to_string(db, 1), "Term(takeaway, wdf=2)" + bdt);
203 
204  // Add back a document which was taken from the database, but never modified.
205  db.replace_document(1, doc3a);
206  dbcheck(db, 1, 1);
207  TEST_EQUAL(docterms_to_string(db, 1), "Term(takeaway, wdf=3)" + bdt);
208 
209  // Add a position to the document.
210  Xapian::Document doc5(db.get_document(1));
211  doc5.add_posting("takeaway", 1, 2);
212  db.replace_document(1, doc5);
213  dbcheck(db, 1, 1);
214  TEST_EQUAL(docterms_to_string(db, 1), "Term(takeaway, wdf=5, pos=[1])" + bdt);
215 
216  // Add a position without changing the wdf.
217  Xapian::Document doc5b(db.get_document(1));
218  doc5b.add_posting("takeaway", 2, 0);
219  db.replace_document(1, doc5b);
220  dbcheck(db, 1, 1);
221  TEST_EQUAL(docterms_to_string(db, 1), "Term(takeaway, wdf=5, pos=[1, 2])" + bdt);
222 
223  // Delete a position without changing the wdf.
224  Xapian::Document doc5c(basic_doc());
225  doc5c.add_posting("takeaway", 2, 5);
226  db.replace_document(1, doc5c);
227  dbcheck(db, 1, 1);
228  TEST_EQUAL(docterms_to_string(db, 1), "Term(takeaway, wdf=5, pos=[2])" + bdt);
229 
230  // Delete the other position without changing the wdf.
231  Xapian::Document doc5d(basic_doc());
232  doc5d.add_term("takeaway", 5);
233  db.replace_document(1, doc5d);
234  dbcheck(db, 1, 1);
235  TEST_EQUAL(docterms_to_string(db, 1), "Term(takeaway, wdf=5)" + bdt);
236 
237  // Reduce the wdf to 0, but don't delete the term.
238  Xapian::Document doc0freq(basic_doc());
239  doc0freq.add_term("takeaway", 0);
240  db.replace_document(1, doc0freq);
241  dbcheck(db, 1, 1);
242  TEST_EQUAL(docterms_to_string(db, 1), "Term(takeaway, wdf=0)" + bdt);
243 
244  // Reduce the wdf to 0, and delete the term.
245  db.replace_document(1, doc0);
246  dbcheck(db, 1, 1);
247  TEST_EQUAL(docterms_to_string(db, 1), bdt.substr(2));
248 
249  // Delete the document.
250  db.delete_document(1);
251  dbcheck(db, 0, 1);
253  TEST_EQUAL(postlist_to_string(db, "takeaway"), "");
255  TEST_EQUAL(termstats_to_string(db, "takeaway"), "tf=0,cf=0");
256  TEST_EQUAL(db.get_doccount(), 0);
257  TEST_EQUAL(db.get_avlength(), 0);
258  TEST_EQUAL(db.get_lastdocid(), 1);
259 }
static Xapian::Document basic_doc()
static string basic_docterms()
DEFINE_TESTCASE(poslistupdate1, positional &&writable)
Xapian::WritableDatabase get_writable_database(const string &dbname)
Definition: apitest.cc:86
test functionality of the Xapian API
PositionIterator positionlist_end(Xapian::docid, std::string_view) const noexcept
End iterator corresponding to positionlist_begin().
Definition: database.h:292
double get_avlength() const
Old name for get_average_length() for backward compatibility.
Definition: database.h:322
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::doccount get_doccount() const
Get the number of documents in the database.
Definition: database.cc:233
Xapian::docid get_lastdocid() const
Get the highest document id which has been used in the database.
Definition: database.cc:239
Xapian::Document get_document(Xapian::docid did, unsigned flags=0) const
Get a document from the database.
Definition: database.cc:368
Indicates an attempt to access a document not present in the database.
Definition: error.h:662
Class representing a document.
Definition: document.h:64
void add_boolean_term(std::string_view term)
Add a boolean filter term to the document.
Definition: document.h:145
void add_term(std::string_view term, Xapian::termcount wdf_inc=1)
Add a term to this document.
Definition: document.cc:87
void remove_term(std::string_view term)
Remove a term from this document.
Definition: document.cc:96
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 for iterating over term positions.
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 replace_document(Xapian::docid did, const Xapian::Document &document)
Replace a document in the database.
Definition: database.cc:582
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
test database contents and consistency.
string docterms_to_string(const Xapian::Database &db, Xapian::docid did)
Convert the list of terms in a document to a string.
Definition: dbcheck.cc:81
void dbcheck(const Xapian::Database &db, Xapian::doccount expected_doccount, Xapian::docid expected_lastdocid)
Check consistency of database and statistics.
Definition: dbcheck.cc:125
string postlist_to_string(const Xapian::Database &db, const string &tname)
Convert the list of postings in a postlist to a string.
Definition: dbcheck.cc:54
string termstats_to_string(const Xapian::Database &db, const string &term)
Convert statistics about a term to a string.
Definition: dbcheck.cc:114
string docstats_to_string(const Xapian::Database &db, Xapian::docid did)
Convert statistics about a document to a string.
Definition: dbcheck.cc:104
a generic test suite engine
#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.