xapian-core  2.1.0
documentinternal.h
Go to the documentation of this file.
1 
4 /* Copyright 2017,2018,2019,2023,2024,2026 Olly Betts
5  *
6  * This program is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License as
8  * published by the Free Software Foundation; either version 2 of the
9  * License, or (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see
18  * <https://www.gnu.org/licenses/>.
19  */
20 
21 #ifndef XAPIAN_INCLUDED_DOCUMENTINTERNAL_H
22 #define XAPIAN_INCLUDED_DOCUMENTINTERNAL_H
23 
24 #include <xapian/document.h>
25 #include <xapian/intrusive_ptr.h>
26 #include <xapian/types.h>
27 
28 #include "api/terminfo.h"
29 #include "api/termlist.h"
31 #include "clamp_cast.h"
32 #include "overflow.h"
33 
34 #include <functional>
35 #include <limits>
36 #include <map>
37 #include <memory>
38 #include <string>
39 #include <string_view>
40 
41 class DocumentTermList;
42 class DocumentValueList;
43 class GlassValueManager;
44 class HoneyValueManager;
46 
47 namespace Xapian {
48 
51  friend class ::DocumentTermList;
52  friend class ::DocumentValueList;
53  // For ensure_values_fetched():
54  friend class ::GlassValueManager;
55  friend class ::HoneyValueManager;
56  friend class ::ValueStreamDocument;
57 
59  void operator=(const Internal &) = delete;
60 
62  Internal(const Internal &) = delete;
63 
68  std::unique_ptr<std::string> data;
69 
78  mutable
79  std::unique_ptr<std::map<std::string, TermInfo, std::less<>>> terms;
80 
88 
105 
116  mutable bool positions_modified_ : 1;
117 
123  void ensure_terms_fetched() const;
124 
130  void ensure_values_fetched() const;
131 
132  protected:
141  mutable std::unique_ptr<std::map<Xapian::valueno, std::string>> values;
142 
148 
157 
160  Xapian::docid did_)
161  : index(), positions_modified_(false), database(database_), did(did_) {}
162 
165  Xapian::docid did_,
166  std::string&& data_,
167  std::map<Xapian::valueno, std::string>&& values_)
168  : data(new std::string(std::move(data_))),
169  index(), positions_modified_(false),
170  values(new std::map<Xapian::valueno, std::string>(std::move(values_))),
171  database(database_),
172  did(did_) {}
173 
179  virtual std::string fetch_data() const;
180 
186  virtual void fetch_all_values(std::map<Xapian::valueno,
187  std::string>& values_) const;
188 
194  virtual std::string fetch_value(Xapian::valueno slot) const;
195 
196  public:
198  Internal() : index(), positions_modified_(false), did(0) {}
199 
203  virtual ~Internal();
204 
211  bool data_modified() const { return data != NULL; }
212 
219  bool terms_modified() const { return terms != NULL; }
220 
227  bool values_modified() const { return values != NULL; }
228 
235  bool modified() const {
236  return data_modified() || terms_modified() || values_modified();
237  }
238 
245  bool positions_modified() const { return positions_modified_; }
246 
254  Xapian::docid get_docid() const { return did; }
255 
257  Xapian::doccount get_index() const { return index; }
258 
260  void set_index(Xapian::doccount new_index) { index = new_index; }
261 
263  std::string get_data() const {
264  if (data)
265  return *data;
266  return fetch_data();
267  }
268 
270  void set_data(std::string_view data_) {
271  data.reset(new std::string(data_));
272  }
273 
275  void add_term(std::string_view term, Xapian::termcount wdf_inc) {
277 
278  auto i = terms->find(term);
279  if (i == terms->end()) {
280  ++termlist_size;
281  terms->emplace(term, TermInfo(wdf_inc));
282  } else {
283  if (i->second.increase_wdf(wdf_inc))
284  ++termlist_size;
285  }
286  }
287 
289  bool remove_term(std::string_view term) {
291 
292  auto i = terms->find(term);
293  if (i == terms->end()) {
294  return false;
295  }
296  if (i->second.has_positions()) {
297  positions_modified_ = true;
298  }
299  if (!i->second.remove()) {
300  return false;
301  }
302  --termlist_size;
303  return true;
304  }
305 
307  void add_posting(std::string_view term,
308  Xapian::termpos term_pos,
309  Xapian::termcount wdf_inc) {
311  positions_modified_ = true;
312 
313  auto i = terms->find(term);
314  if (i == terms->end()) {
315  ++termlist_size;
316  terms->emplace(term, TermInfo(wdf_inc, term_pos));
317  return;
318  }
319  if (i->second.add_position(wdf_inc, term_pos))
320  ++termlist_size;
321  }
322 
324 
327  remove_posting(std::string_view term,
328  Xapian::termpos term_pos,
329  Xapian::termcount wdf_dec) {
331 
332  auto i = terms->find(term);
333  if (i == terms->end() || i->second.is_deleted()) {
334  return remove_posting_result::NO_TERM;
335  }
336  if (!i->second.remove_position(term_pos)) {
337  return remove_posting_result::NO_POS;
338  }
339  if (i->second.decrease_wdf(wdf_dec))
340  --termlist_size;
341  positions_modified_ = true;
342  return remove_posting_result::OK;
343  }
344 
350  remove_postings(std::string_view term,
351  Xapian::termpos term_pos_first,
352  Xapian::termpos term_pos_last,
353  Xapian::termcount wdf_dec,
354  Xapian::termpos& n_removed) {
356 
357  auto i = terms->find(term);
358  if (i == terms->end() || i->second.is_deleted()) {
359  return remove_posting_result::NO_TERM;
360  }
361  n_removed = i->second.remove_positions(term_pos_first,
362  term_pos_last);
363  if (n_removed) {
364  positions_modified_ = true;
365  Xapian::termcount wdf_delta;
366  if (mul_overflows(n_removed, wdf_dec, wdf_delta)) {
367  // Decreasing by the maximum value will zero the wdf.
368  wdf_delta = std::numeric_limits<Xapian::termcount>::max();
369  }
370  if (i->second.decrease_wdf(wdf_delta))
371  --termlist_size;
372  }
373  return remove_posting_result::OK;
374  }
375 
377  void clear_terms() {
378  if (!terms) {
379  if (!database) {
380  // We didn't come from a database, so there are no unfetched
381  // terms to clear.
382  return;
383  }
384  terms.reset(new std::map<std::string, TermInfo, std::less<>>());
385  } else {
386  terms->clear();
387  }
388  termlist_size = 0;
389  // Assume there was positional data if there's any in the database.
391  }
392 
395  if (terms)
396  return termlist_size;
397 
398  if (!database)
399  return 0;
400 
401  std::unique_ptr<TermList> tl(database->open_term_list(did));
402  // get_approx_size() is exact for TermList from a database.
403  return tl->get_approx_size();
404  }
405 
411  TermList* open_term_list() const;
412 
417  std::string get_value(Xapian::valueno slot) const {
418  if (values) {
419  auto i = values->find(slot);
420  if (i != values->end())
421  return i->second;
422  return std::string();
423  }
424 
425  return fetch_value(slot);
426  }
427 
429  void add_value(Xapian::valueno slot, std::string_view value) {
431 
432  if (!value.empty()) {
433  (*values)[slot] = value;
434  } else {
435  // Empty values aren't stored, but replace any existing value by
436  // removing it.
437  values->erase(slot);
438  }
439  }
440 
442  void clear_values() {
443  if (!values) {
444  if (database) {
445  values.reset(new std::map<Xapian::valueno, std::string>());
446  } else {
447  // We didn't come from a database, so there are no unfetched
448  // values to clear.
449  }
450  } else {
451  values->clear();
452  }
453  }
454 
458  return clamp_cast<Xapian::valueno>(values->size());
459  }
460 
462 
464  std::string get_description() const;
465 };
466 
467 }
468 
469 #endif // XAPIAN_INCLUDED_DOCUMENTINTERNAL_H
Cast a value to a type, clamping out of range values.
Iteration over terms in a document.
Iteration over values in a document.
Metadata for a term in a document.
Definition: terminfo.h:28
A document which gets its values from a ValueStreamManager.
Virtual base class for Database internals.
virtual TermList * open_term_list(docid did) const =0
virtual bool has_positions() const =0
Check whether this database contains any positional information.
Abstract base class for a document.
void set_index(Xapian::doccount new_index)
Internal method used by MSet::diversify().
Xapian::docid did
The document ID this document came from in database.
std::unique_ptr< std::map< std::string, TermInfo, std::less<> > > terms
Terms in the document and their associated metadata.
void add_value(Xapian::valueno slot, std::string_view value)
Add a value to a slot in this document.
Xapian::termcount termlist_count() const
Return the number of distinct terms in this document.
virtual void fetch_all_values(std::map< Xapian::valueno, std::string > &values_) const
Fetch all set values from the database.
Internal(Xapian::Internal::intrusive_ptr< const Xapian::Database::Internal > database_, Xapian::docid did_)
Constructor used by subclasses.
void ensure_values_fetched() const
Ensure values have been fetched from database.
std::unique_ptr< std::map< Xapian::valueno, std::string > > values
Document value slots and their contents.
std::unique_ptr< std::string > data
The document data.
void ensure_terms_fetched() const
Ensure terms have been fetched from database.
void add_term(std::string_view term, Xapian::termcount wdf_inc)
Add a term to this document.
Xapian::docid get_docid() const
Get the document ID this document came from.
bool modified() const
Return true if the document might have been modified in any way.
bool data_modified() const
Return true if the document data might have been modified.
bool positions_modified_
Are there any changes to term positions in terms?
bool remove_term(std::string_view term)
Remove a term from this document.
void add_posting(std::string_view term, Xapian::termpos term_pos, Xapian::termcount wdf_inc)
Add a posting for a term.
Xapian::doccount index
An index value, unused by Document itself.
void set_data(std::string_view data_)
Set the document data.
virtual std::string fetch_data() const
Fetch the document data from the database.
Xapian::doccount get_index() const
Internal method used by MSet::diversify().
Xapian::ValueIterator values_begin() const
bool values_modified() const
Return true if the document's values might have been modified.
bool positions_modified() const
Return true if the document's term positions might have been modified.
std::string get_description() const
Return a string describing this object.
Xapian::termcount termlist_size
The number of distinct terms in terms.
virtual std::string fetch_value(Xapian::valueno slot) const
Fetch a single value from the database.
remove_posting_result remove_postings(std::string_view term, Xapian::termpos term_pos_first, Xapian::termpos term_pos_last, Xapian::termcount wdf_dec, Xapian::termpos &n_removed)
Remove a range of postings for a term.
Internal()
Construct an empty document.
remove_posting_result remove_posting(std::string_view term, Xapian::termpos term_pos, Xapian::termcount wdf_dec)
Remove a posting for a term.
Internal(const Internal &)=delete
Don't allow copying.
std::string get_data() const
Get the document data.
void operator=(const Internal &)=delete
Don't allow assignment.
Xapian::valueno values_count() const
Count the value slots used in this document.
void clear_terms()
Clear all terms from the document.
std::string get_value(Xapian::valueno slot) const
Read a value slot in this document.
TermList * open_term_list() const
Start iterating the terms in this document.
virtual ~Internal()
We have virtual methods and want to be able to delete derived classes using a pointer to the base cla...
void clear_values()
Clear all value slots in this document.
Xapian::Internal::intrusive_ptr< const Xapian::Database::Internal > database
Database this document came from.
bool terms_modified() const
Return true if the document's terms might have been modified.
Internal(const Xapian::Database::Internal *database_, Xapian::docid did_, std::string &&data_, std::map< Xapian::valueno, std::string > &&values_)
Constructor used by RemoteDocument subclass.
Base class for objects managed by intrusive_ptr.
Definition: intrusive_ptr.h:50
Abstract base class for termlists.
Definition: termlist.h:42
Class for iterating over document values.
Definition: valueiterator.h:39
string term
Virtual base class for Database internals.
Class representing a document.
The Xapian namespace contains public interfaces for the Xapian library.
Definition: compactor.cc:82
unsigned XAPIAN_TERMCOUNT_BASE_TYPE termcount
A counts of terms.
Definition: types.h:64
unsigned valueno
The number for a value slot in a document.
Definition: types.h:90
unsigned XAPIAN_DOCID_BASE_TYPE doccount
A count of documents.
Definition: types.h:37
unsigned XAPIAN_DOCID_BASE_TYPE docid
A unique identifier for a document.
Definition: types.h:51
unsigned XAPIAN_TERMPOS_BASE_TYPE termpos
A term position within a document or query.
Definition: types.h:75
Arithmetic operations with overflow checks.
std::enable_if_t< std::is_unsigned_v< T1 > &&std::is_unsigned_v< T2 > &&std::is_unsigned_v< R >, bool > mul_overflows(T1 a, T2 b, R &res)
Multiplication with overflow checking.
Definition: overflow.h:188
Metadata for a term in a document.
Abstract base class for termlists.
typedefs for Xapian