xapian-core  2.0.0
query.h
Go to the documentation of this file.
1 
4 /* Copyright (C) 2011-2026 Olly Betts
5  * Copyright (C) 2008 Richard Boulton
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 #ifndef XAPIAN_INCLUDED_QUERY_H
23 #define XAPIAN_INCLUDED_QUERY_H
24 
25 #if !defined XAPIAN_IN_XAPIAN_H && !defined XAPIAN_LIB_BUILD
26 # error Never use <xapian/query.h> directly; include <xapian.h> instead.
27 #endif
28 
29 #include <string>
30 #include <string_view>
31 
32 #include <xapian/attributes.h>
33 #include <xapian/intrusive_ptr.h>
34 #include <xapian/postingiterator.h>
35 #include <xapian/registry.h>
36 #include <xapian/termiterator.h>
37 #include <xapian/types.h>
38 #include <xapian/visibility.h>
39 
40 namespace Xapian {
41 
42 class PostingSource;
43 
46  public:
48  class Internal;
51 
65 
75  static const Xapian::Query MatchAll;
76 
78  enum op {
84  OP_AND = 0,
85 
92  OP_OR = 1,
93 
99  OP_AND_NOT = 2,
100 
107  OP_XOR = 3,
108 
118  OP_AND_MAYBE = 4,
119 
128  OP_FILTER = 5,
129 
140  OP_NEAR = 6,
141 
152  OP_PHRASE = 7,
153 
158  OP_VALUE_RANGE = 8,
159 
166  OP_SCALE_WEIGHT = 9,
167 
215  OP_ELITE_SET = 10,
216 
223  OP_VALUE_GE = 11,
224 
231  OP_VALUE_LE = 12,
232 
239  OP_SYNONYM = 13,
240 
249  OP_MAX = 14,
250 
255  OP_WILDCARD = 15,
256 
269  OP_EDIT_DISTANCE = 16,
270 
277  OP_INVALID = 99,
278 
280  LEAF_TERM = 100,
281 
284 
291 
296  LEAF_MATCH_NOTHING
297  };
298 
299  enum {
305  WILDCARD_LIMIT_ERROR = 0x00,
311  WILDCARD_LIMIT_FIRST = 0x01,
321  WILDCARD_LIMIT_MOST_FREQUENT = 0x02,
322 
324  WILDCARD_LIMIT_MASK_ = 0x03,
325 
330  WILDCARD_PATTERN_MULTI = 0x10,
331 
336  WILDCARD_PATTERN_SINGLE = 0x20,
337 
342  WILDCARD_PATTERN_GLOB = WILDCARD_PATTERN_MULTI|WILDCARD_PATTERN_SINGLE
343  };
344 
354  Query() noexcept { }
355 
357  ~Query() { }
358 
363  Query(const Query & o) : internal(o.internal) { }
364 
369  Query & operator=(const Query & o) { internal = o.internal; return *this; }
370 
372  Query(Query &&) = default;
373 
375  Query & operator=(Query &&) = default;
376 
386  Query(const std::string& term,
387  Xapian::termcount wqf = 1,
388  Xapian::termpos pos = 0)
389  : Query(std::string_view(term), wqf, pos)
390  { }
391 
401  Query(const char* term,
402  Xapian::termcount wqf = 1,
403  Xapian::termpos pos = 0)
404  : Query(std::string_view(term), wqf, pos)
405  { }
406 
416  Query(std::string_view term,
417  Xapian::termcount wqf = 1,
418  Xapian::termpos pos = 0);
419 
421  explicit Query(Xapian::PostingSource * source);
422 
428  Query(double factor, const Xapian::Query & subquery);
429 
439  Query(op op_, const Xapian::Query & subquery, double factor);
440 
447  Query(op op_, const Xapian::Query & a, const Xapian::Query & b)
448  {
449  init(op_, 2);
450  bool positional = (op_ == OP_NEAR || op_ == OP_PHRASE);
451  add_subquery(positional, a);
452  add_subquery(positional, b);
453  done();
454  }
455 
462  template<typename S1, typename S2,
463  typename
464  std::enable_if<std::is_constructible<std::string_view, S1>::value &&
465  std::is_constructible<std::string_view, S2>::value,
466  bool>::type = true>
467  Query(op op_, S1 a, S2 b)
468  {
469  init(op_, 2);
470  add_subquery(false, std::string_view(a));
471  add_subquery(false, std::string_view(b));
472  done();
473  }
474 
481  Query(op op_, Xapian::valueno slot, std::string_view range_limit);
482 
490  Query(op op_, Xapian::valueno slot,
491  std::string_view range_lower, std::string_view range_upper);
492 
531  Query(op op_,
532  std::string_view pattern,
533  Xapian::termcount max_expansion = 0,
534  int flags = WILDCARD_LIMIT_ERROR,
535  op combiner = OP_SYNONYM);
536 
571  Query(op op_,
572  std::string_view pattern,
573  Xapian::termcount max_expansion,
574  int flags,
575  op combiner,
576  unsigned edit_distance,
577  size_t min_prefix_len = 0);
578 
594  template<typename I,
595  typename std::enable_if<
596  std::is_convertible<typename std::iterator_traits<I>::value_type,
597  Xapian::Query>::value ||
598  std::is_convertible<typename std::iterator_traits<I>::value_type,
599  Xapian::Query*>::value ||
600  std::is_convertible<typename std::iterator_traits<I>::value_type,
601  std::string_view>::value,
602  bool>::type = true,
603  typename iterator_category =
604  typename std::iterator_traits<I>::iterator_category>
605  Query(op op_, I begin, I end, Xapian::termcount window = 0)
606  {
607  if (begin != end) {
608  init(op_, window, begin, end, iterator_category());
609  bool positional = (op_ == OP_NEAR || op_ == OP_PHRASE);
610  for (I i = begin; i != end; ++i) {
611  add_subquery(positional, *i);
612  }
613  done();
614  }
615  }
616 
617 #ifdef SWIG
618  // SWIG's %template doesn't seem to handle a templated ctor so we
619  // provide this fake specialised form of the above prototype.
620  Query(op op_, XapianSWIGQueryItor qbegin, XapianSWIGQueryItor qend,
621  Xapian::termcount parameter = 0);
622 
623 # ifdef SWIGJAVA
624  Query(op op_, XapianSWIGStrItor qbegin, XapianSWIGStrItor qend,
625  Xapian::termcount parameter = 0);
626 # endif
627 #endif
628 
636  const TermIterator get_terms_begin() const;
637 
639  const TermIterator get_terms_end() const noexcept {
640  return TermIterator();
641  }
642 
650  const TermIterator get_unique_terms_begin() const;
651 
653  const TermIterator get_unique_terms_end() const noexcept {
654  return TermIterator();
655  }
656 
658  Xapian::termcount get_length() const noexcept XAPIAN_PURE_FUNCTION;
659 
661  bool empty() const noexcept {
662  return !internal;
663  }
664 
666  std::string serialise() const;
667 
675  static const Query unserialise(std::string_view serialised,
676  const Registry & reg = Registry());
677 
679  op get_type() const noexcept XAPIAN_PURE_FUNCTION;
680 
682  size_t get_num_subqueries() const noexcept XAPIAN_PURE_FUNCTION;
683 
688  Xapian::termcount get_leaf_wqf() const;
689 
694  Xapian::termpos get_leaf_pos() const;
695 
701  const Query get_subquery(size_t n) const;
702 
704  std::string get_description() const;
705 
713  const Query operator&=(const Query & o);
714 
722  const Query operator|=(const Query & o);
723 
731  const Query operator^=(const Query & o);
732 
737  const Query operator*=(double factor) {
738  return (*this = Query(factor, *this));
739  }
740 
745  const Query operator/=(double factor) {
746  return (*this = Query(1.0 / factor, *this));
747  }
748 
750  explicit Query(Internal * internal_) : internal(internal_) { }
751 
756  explicit Query(Query::op op_) {
757  init(op_, 0);
758  if (op_ != Query::OP_INVALID) done();
759  }
760 
761  private:
762  void init(Query::op op_, size_t n_subqueries, Xapian::termcount window = 0);
763 
764  template<typename I>
765  void init(Query::op op_, Xapian::termcount window,
766  const I & begin, const I & end, std::random_access_iterator_tag)
767  {
768  init(op_, end - begin, window);
769  }
770 
771  template<typename I>
772  void init(Query::op op_, Xapian::termcount window,
773  const I &, const I &, std::input_iterator_tag)
774  {
775  init(op_, 0, window);
776  }
777 
778  void add_subquery(bool positional, const Xapian::Query & subquery);
779 
780  void add_subquery(bool, const std::string& subquery) {
781  add_subquery(false, Xapian::Query(subquery));
782  }
783 
784  void add_subquery(bool, const char* subquery) {
785  add_subquery(false, Xapian::Query(subquery));
786  }
787 
788  void add_subquery(bool, std::string_view subquery) {
789  add_subquery(false, Xapian::Query(subquery));
790  }
791 
792  void add_subquery(bool positional, const Xapian::Query * subquery) {
793  // FIXME: subquery NULL?
794  add_subquery(positional, *subquery);
795  }
796 
797  void done();
798 };
799 
801 inline const Query
802 operator&(const Query & a, const Query & b)
803 {
804  return Query(Query::OP_AND, a, b);
805 }
806 
808 inline const Query
809 operator|(const Query & a, const Query & b)
810 {
811  return Query(Query::OP_OR, a, b);
812 }
813 
815 inline const Query
816 operator^(const Query & a, const Query & b)
817 {
818  return Query(Query::OP_XOR, a, b);
819 }
820 
826 inline const Query
827 operator*(double factor, const Query & q)
828 {
829  return Query(factor, q);
830 }
831 
837 inline const Query
838 operator*(const Query & q, double factor)
839 {
840  return Query(factor, q);
841 }
842 
848 inline const Query
849 operator/(const Query & q, double factor)
850 {
851  return Query(1.0 / factor, q);
852 }
853 
856  const Query & query;
857 
858  void operator=(const InvertedQuery_ &);
859 
860  explicit InvertedQuery_(const Query & query_) : query(query_) { }
861 
862  public:
863  // GCC 4.2 seems to needs a copy ctor.
865 
866  operator Query() const {
867  return Query(Query::OP_AND_NOT, Query(std::string_view{}), query);
868  }
869 
870  friend const InvertedQuery_ operator~(const Query &q);
871 
872  friend const Query operator&(const Query & a, const InvertedQuery_ & b);
873 
874  friend const Query operator&=(Query & a, const InvertedQuery_ & b);
875 };
876 
881 inline const Query
882 operator&(const Query & a, const InvertedQuery_ & b)
883 {
884  return Query(Query::OP_AND_NOT, a, b.query);
885 }
886 
891 inline const Query
893 {
894  return (a = Query(Query::OP_AND_NOT, a, b.query));
895 }
896 
897 #ifndef DOXYGEN /* @internal doesn't seem to avoid a warning here. */
899 inline const InvertedQuery_
900 operator~(const Query &q)
901 {
902  return InvertedQuery_(q);
903 }
904 #endif
905 
906 namespace Internal {
907 class AndContext;
908 class OrContext;
909 class XorContext;
910 
911 struct PostListAndEstimate;
912 class QueryOptimiser;
913 struct TermFreqs;
914 }
915 
918  public:
919  Internal() noexcept { }
920 
921  virtual ~Internal();
922 
926  double factor,
927  Xapian::Internal::TermFreqs* termfreqs) const = 0;
928 
930  virtual bool
933  double factor,
934  Xapian::Internal::TermFreqs* termfreqs) const;
935 
937  virtual void
940  Xapian::Internal::TermFreqs* termfreqs) const;
941 
943  virtual void
946  double factor,
947  Xapian::Internal::TermFreqs* termfreqs,
948  bool keep_zero_weight = true) const;
949 
951  virtual void
954  double factor,
955  Xapian::Internal::TermFreqs* termfreqs) const;
956 
958  virtual termcount get_length() const noexcept XAPIAN_PURE_FUNCTION;
959 
961  virtual void serialise(std::string & result) const = 0;
962 
964  static Query::Internal* unserialise(const char** p, const char* end,
965  const Registry& reg);
966 
968  virtual Query::op get_type() const noexcept XAPIAN_PURE_FUNCTION = 0;
970  virtual size_t get_num_subqueries() const noexcept XAPIAN_PURE_FUNCTION;
972  virtual const Query get_subquery(size_t n) const;
974  virtual termcount get_wqf() const;
976  virtual termpos get_pos() const;
977 
979  virtual std::string get_description() const = 0;
980 
981  // Pass argument as void* to avoid need to include <vector>.
983  virtual void gather_terms(void * void_terms) const;
984 };
985 
986 inline const Query
987 Query::operator&=(const Query & o)
988 {
989  if (o.empty()) {
990  // q &= empty_query sets q to empty_query.
991  *this = o;
992  } else if (this != &o &&
993  internal &&
994  internal->_refs == 1 &&
995  get_type() == OP_AND) {
996  // Appending a subquery to an existing AND.
997  add_subquery(false, o);
998  } else {
999  *this = Query(OP_AND, *this, o);
1000  }
1001  return *this;
1002 }
1003 
1004 inline const Query
1006 {
1007  if (o.empty()) {
1008  // q |= empty_query is a no-op.
1009  } else if (this != &o &&
1010  internal &&
1011  internal->_refs == 1 &&
1012  get_type() == OP_OR) {
1013  // Appending a subquery to an existing OR.
1014  add_subquery(false, o);
1015  } else {
1016  *this = Query(OP_OR, *this, o);
1017  }
1018  return *this;
1019 }
1020 
1021 inline const Query
1023 {
1024  if (o.empty()) {
1025  // q ^= empty_query is a no-op.
1026  } else if (internal.get() == o.internal.get()) {
1027  // q ^= q gives MatchNothing.
1028  internal = NULL;
1029  } else if (internal &&
1030  internal->_refs == 1 &&
1031  get_type() == OP_XOR) {
1032  // Appending a subquery to an existing XOR.
1033  add_subquery(false, o);
1034  } else {
1035  *this = Query(OP_XOR, *this, o);
1036  }
1037  return *this;
1038 }
1039 
1040 }
1041 
1042 #endif // XAPIAN_INCLUDED_QUERY_H
Compiler attribute macros.
#define XAPIAN_PURE_FUNCTION
Like XAPIAN_CONST_FUNCTION, but such a function can also examine global memory, perhaps via pointer o...
Definition: attributes.h:59
Base class for objects managed by intrusive_ptr.
Definition: intrusive_ptr.h:50
A smart pointer that uses intrusive reference counting.
Definition: intrusive_ptr.h:83
friend const InvertedQuery_ operator~(const Query &q)
void operator=(const InvertedQuery_ &)
friend const Query operator&(const Query &a, const InvertedQuery_ &b)
Combine two Xapian::Query objects using OP_AND_NOT.
Definition: query.h:882
InvertedQuery_(const InvertedQuery_ &o)
Definition: query.h:864
const Query & query
Definition: query.h:856
InvertedQuery_(const Query &query_)
Definition: query.h:860
friend const Query operator&=(Query &a, const InvertedQuery_ &b)
Combine two Xapian::Query objects using OP_AND_NOT with result in the first.
Definition: query.h:892
Base class which provides an "external" source of postings.
Definition: postingsource.h:47
virtual termpos get_pos() const
virtual void postlist_sub_bool_or_like(Xapian::Internal::OrContext &ctx, Xapian::Internal::QueryOptimiser *qopt, Xapian::Internal::TermFreqs *termfreqs) const
virtual termcount get_length() const noexcept
virtual termcount get_wqf() const
static Query::Internal * unserialise(const char **p, const char *end, const Registry &reg)
virtual const Query get_subquery(size_t n) const
virtual bool postlist_sub_and_like(Xapian::Internal::AndContext &ctx, Xapian::Internal::QueryOptimiser *qopt, double factor, Xapian::Internal::TermFreqs *termfreqs) const
virtual void postlist_sub_or_like(Xapian::Internal::OrContext &ctx, Xapian::Internal::QueryOptimiser *qopt, double factor, Xapian::Internal::TermFreqs *termfreqs, bool keep_zero_weight=true) const
virtual std::string get_description() const =0
virtual void gather_terms(void *void_terms) const
virtual void postlist_sub_xor(Xapian::Internal::XorContext &ctx, Xapian::Internal::QueryOptimiser *qopt, double factor, Xapian::Internal::TermFreqs *termfreqs) const
virtual Query::op get_type() const noexcept=0
virtual Xapian::Internal::PostListAndEstimate postlist(Xapian::Internal::QueryOptimiser *qopt, double factor, Xapian::Internal::TermFreqs *termfreqs) const =0
virtual size_t get_num_subqueries() const noexcept
virtual void serialise(std::string &result) const =0
Internal() noexcept
Definition: query.h:919
Class representing a query.
Definition: query.h:45
void add_subquery(bool, const char *subquery)
Definition: query.h:784
const Query operator/=(double factor)
Inverse scale using OP_SCALE_WEIGHT.
Definition: query.h:745
Query(const char *term, Xapian::termcount wqf=1, Xapian::termpos pos=0)
Construct a Query object for a term.
Definition: query.h:401
~Query()
Destructor.
Definition: query.h:357
Query(Query &&)=default
Move constructor.
const Query operator^=(const Query &o)
Combine with another Xapian::Query object using OP_XOR.
Definition: query.h:1022
const TermIterator get_unique_terms_end() const noexcept
End iterator for unique terms in the query object.
Definition: query.h:653
Query & operator=(Query &&)=default
Move assignment operator.
const TermIterator get_terms_end() const noexcept
End iterator for terms in the query object.
Definition: query.h:639
Query(const std::string &term, Xapian::termcount wqf=1, Xapian::termpos pos=0)
Construct a Query object for a term.
Definition: query.h:386
op
Query operators.
Definition: query.h:78
@ LEAF_POSTING_SOURCE
Value returned by get_type() for a PostingSource.
Definition: query.h:283
@ OP_XOR
Match documents which an odd number of subqueries match.
Definition: query.h:107
@ LEAF_MATCH_ALL
Value returned by get_type() for MatchAll or equivalent.
Definition: query.h:290
@ 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_AND_NOT
Match documents which the first subquery matches but no others do.
Definition: query.h:99
@ OP_INVALID
Construct an invalid query.
Definition: query.h:277
void add_subquery(bool positional, const Xapian::Query &subquery)
Definition: query.cc:371
Query(op op_, I begin, I end, Xapian::termcount window=0)
Construct a Query object from a begin/end iterator pair.
Definition: query.h:605
void init(Query::op op_, Xapian::termcount window, const I &begin, const I &end, std::random_access_iterator_tag)
Definition: query.h:765
void add_subquery(bool, const std::string &subquery)
Definition: query.h:780
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
const Query operator|=(const Query &o)
Combine with another Xapian::Query object using OP_OR.
Definition: query.h:1005
Query(Internal *internal_)
Definition: query.h:750
Query(const Query &o)
Copying is allowed.
Definition: query.h:363
void add_subquery(bool, std::string_view subquery)
Definition: query.h:788
void add_subquery(bool positional, const Xapian::Query *subquery)
Definition: query.h:792
Query(op op_, S1 a, S2 b)
Construct a Query object by combining two terms.
Definition: query.h:467
Query(op op_, const Xapian::Query &a, const Xapian::Query &b)
Construct a Query object by combining two others.
Definition: query.h:447
Xapian::Internal::intrusive_ptr< Internal > internal
Definition: query.h:48
void init(Query::op op_, Xapian::termcount window, const I &, const I &, std::input_iterator_tag)
Definition: query.h:772
Query(Query::op op_)
Construct with just an operator.
Definition: query.h:756
Query() noexcept
Construct a query matching no documents.
Definition: query.h:354
Query & operator=(const Query &o)
Copying is allowed.
Definition: query.h:369
static const Xapian::Query MatchAll
A query matching all documents.
Definition: query.h:75
Registry for user subclasses.
Definition: registry.h:47
Class for iterating over a list of terms.
Definition: termiterator.h:41
string term
PositionList * p
Xapian::termpos pos
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
const Query operator^(const Query &a, const Query &b)
Combine two Xapian::Query objects using OP_XOR.
Definition: query.h:816
const Query operator|(const Query &a, const Query &b)
Combine two Xapian::Query objects using OP_OR.
Definition: query.h:809
const Query operator&(const Query &a, const Query &b)
Combine two Xapian::Query objects using OP_AND.
Definition: query.h:802
unsigned valueno
The number for a value slot in a document.
Definition: types.h:90
const Query operator&=(Query &a, const InvertedQuery_ &b)
Combine two Xapian::Query objects using OP_AND_NOT with result in the first.
Definition: query.h:892
const Query operator*(double factor, const Query &q)
Scale a Xapian::Query object using OP_SCALE_WEIGHT.
Definition: query.h:827
unsigned XAPIAN_TERMPOS_BASE_TYPE termpos
A term position within a document or query.
Definition: types.h:75
const Query operator/(const Query &q, double factor)
Inverse-scale a Xapian::Query object using OP_SCALE_WEIGHT.
Definition: query.h:849
Class for iterating over a list of document ids.
Class for looking up user subclasses during unserialisation.
The frequencies for a term.
Class for iterating over a list of terms.
typedefs for Xapian
Define XAPIAN_VISIBILITY_* macros.
#define XAPIAN_VISIBILITY_DEFAULT
Definition: visibility.h:28
#define XAPIAN_VISIBILITY_INTERNAL
Definition: visibility.h:29