1 /** @file 2 * @brief Xapian::Query internals 3 */ 4 /* Copyright (C) 2011,2012,2013,2014,2015,2016,2018 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, write to the Free Software 18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 19 */ 20 21 #ifndef XAPIAN_INCLUDED_QUERYINTERNAL_H 22 #define XAPIAN_INCLUDED_QUERYINTERNAL_H 23 24 #include "postlist.h" 25 #include "queryvector.h" 26 #include "xapian/intrusive_ptr.h" 27 #include "xapian/query.h" 28 29 /// Default set_size for OP_ELITE_SET: 30 const Xapian::termcount DEFAULT_ELITE_SET_SIZE = 10; 31 32 class QueryOptimiser; 33 34 namespace Xapian { 35 namespace Internal { 36 37 class QueryTerm : public Query::Internal { 38 std::string term; 39 40 Xapian::termcount wqf; 41 42 Xapian::termpos pos; 43 44 public: 45 // Construct a "MatchAll" QueryTerm. QueryTerm()46 QueryTerm() : term(), wqf(1), pos(0) { } 47 QueryTerm(const std::string & term_,Xapian::termcount wqf_,Xapian::termpos pos_)48 QueryTerm(const std::string & term_, 49 Xapian::termcount wqf_, 50 Xapian::termpos pos_) 51 : term(term_), wqf(wqf_), pos(pos_) { } 52 53 Xapian::Query::op get_type() const XAPIAN_NOEXCEPT XAPIAN_PURE_FUNCTION; 54 get_term()55 const std::string & get_term() const { return term; } 56 57 PostingIterator::Internal * postlist(QueryOptimiser * qopt, double factor) const; 58 get_length()59 termcount get_length() const XAPIAN_NOEXCEPT XAPIAN_PURE_FUNCTION { 60 return wqf; 61 } 62 63 void serialise(std::string & result) const; 64 65 std::string get_description() const; 66 67 void gather_terms(void * void_terms) const; 68 }; 69 70 class QueryPostingSource : public Query::Internal { 71 Xapian::Internal::opt_intrusive_ptr<PostingSource> source; 72 73 public: 74 explicit QueryPostingSource(PostingSource * source_); 75 76 PostingIterator::Internal * postlist(QueryOptimiser *qopt, double factor) const; 77 78 void serialise(std::string & result) const; 79 80 Xapian::Query::op get_type() const XAPIAN_NOEXCEPT XAPIAN_PURE_FUNCTION; 81 82 std::string get_description() const; 83 }; 84 85 class QueryScaleWeight : public Query::Internal { 86 double scale_factor; 87 88 Query subquery; 89 90 public: 91 QueryScaleWeight(double factor, const Query & subquery_); 92 93 PostingIterator::Internal * postlist(QueryOptimiser *qopt, double factor) const; 94 get_length()95 termcount get_length() const XAPIAN_NOEXCEPT XAPIAN_PURE_FUNCTION { 96 return subquery.internal->get_length(); 97 } 98 99 void serialise(std::string & result) const; 100 101 Xapian::Query::op get_type() const XAPIAN_NOEXCEPT XAPIAN_PURE_FUNCTION; 102 size_t get_num_subqueries() const XAPIAN_NOEXCEPT XAPIAN_PURE_FUNCTION; 103 const Query get_subquery(size_t n) const; 104 105 std::string get_description() const; 106 107 void gather_terms(void * void_terms) const; 108 }; 109 110 class QueryValueBase : public Query::Internal { 111 protected: 112 Xapian::valueno slot; 113 114 public: QueryValueBase(Xapian::valueno slot_)115 explicit QueryValueBase(Xapian::valueno slot_) 116 : slot(slot_) { } 117 get_slot()118 Xapian::valueno get_slot() const { return slot; } 119 }; 120 121 class QueryValueRange : public QueryValueBase { 122 std::string begin, end; 123 124 public: QueryValueRange(Xapian::valueno slot_,const std::string & begin_,const std::string & end_)125 QueryValueRange(Xapian::valueno slot_, 126 const std::string &begin_, 127 const std::string &end_) 128 : QueryValueBase(slot_), begin(begin_), end(end_) { } 129 130 PostingIterator::Internal * postlist(QueryOptimiser *qopt, double factor) const; 131 132 void serialise(std::string & result) const; 133 134 Xapian::Query::op get_type() const XAPIAN_NOEXCEPT XAPIAN_PURE_FUNCTION; 135 136 std::string get_description() const; 137 }; 138 139 class QueryValueLE : public QueryValueBase { 140 std::string limit; 141 142 public: QueryValueLE(Xapian::valueno slot_,const std::string & limit_)143 QueryValueLE(Xapian::valueno slot_, const std::string &limit_) 144 : QueryValueBase(slot_), limit(limit_) { } 145 146 PostingIterator::Internal * postlist(QueryOptimiser *qopt, double factor) const; 147 148 void serialise(std::string & result) const; 149 150 Xapian::Query::op get_type() const XAPIAN_NOEXCEPT XAPIAN_PURE_FUNCTION; 151 152 std::string get_description() const; 153 }; 154 155 class QueryValueGE : public QueryValueBase { 156 std::string limit; 157 158 public: QueryValueGE(Xapian::valueno slot_,const std::string & limit_)159 QueryValueGE(Xapian::valueno slot_, const std::string &limit_) 160 : QueryValueBase(slot_), limit(limit_) { } 161 162 PostingIterator::Internal * postlist(QueryOptimiser *qopt, double factor) const; 163 164 void serialise(std::string & result) const; 165 166 Xapian::Query::op get_type() const XAPIAN_NOEXCEPT XAPIAN_PURE_FUNCTION; 167 168 std::string get_description() const; 169 }; 170 171 class QueryBranch : public Query::Internal { 172 virtual Xapian::Query::op get_op() const = 0; 173 174 protected: 175 QueryVector subqueries; 176 QueryBranch(size_t n_subqueries)177 explicit QueryBranch(size_t n_subqueries) : subqueries(n_subqueries) { } 178 179 void serialise_(std::string & result, Xapian::termcount parameter = 0) const; 180 181 void do_or_like(OrContext& ctx, QueryOptimiser * qopt, double factor, 182 Xapian::termcount elite_set_size = 0, size_t first = 0) const; 183 184 PostList * do_synonym(QueryOptimiser * qopt, double factor) const; 185 186 PostList * do_max(QueryOptimiser * qopt, double factor) const; 187 188 const std::string get_description_helper(const char * op, 189 Xapian::termcount window = 0) const; 190 191 public: 192 termcount get_length() const XAPIAN_NOEXCEPT XAPIAN_PURE_FUNCTION; 193 194 void serialise(std::string & result) const; 195 196 void gather_terms(void * void_terms) const; 197 198 virtual void add_subquery(const Xapian::Query & subquery) = 0; 199 200 Xapian::Query::op get_type() const XAPIAN_NOEXCEPT XAPIAN_PURE_FUNCTION; 201 size_t get_num_subqueries() const XAPIAN_NOEXCEPT XAPIAN_PURE_FUNCTION; 202 const Query get_subquery(size_t n) const; 203 204 virtual Query::Internal * done() = 0; 205 }; 206 207 class QueryAndLike : public QueryBranch { 208 protected: QueryAndLike(size_t num_subqueries_)209 explicit QueryAndLike(size_t num_subqueries_) 210 : QueryBranch(num_subqueries_) { } 211 212 public: 213 void add_subquery(const Xapian::Query & subquery); 214 215 Query::Internal * done(); 216 217 PostingIterator::Internal * postlist(QueryOptimiser * qopt, double factor) const; 218 219 void postlist_sub_and_like(AndContext& ctx, QueryOptimiser * qopt, double factor) const; 220 }; 221 222 class QueryOrLike : public QueryBranch { 223 protected: QueryOrLike(size_t num_subqueries_)224 explicit QueryOrLike(size_t num_subqueries_) 225 : QueryBranch(num_subqueries_) { } 226 227 public: 228 void add_subquery(const Xapian::Query & subquery); 229 230 Query::Internal * done(); 231 }; 232 233 class QueryAnd : public QueryAndLike { 234 Xapian::Query::op get_op() const; 235 236 public: QueryAnd(size_t n_subqueries)237 explicit QueryAnd(size_t n_subqueries) : QueryAndLike(n_subqueries) { } 238 239 std::string get_description() const; 240 }; 241 242 class QueryOr : public QueryOrLike { 243 Xapian::Query::op get_op() const; 244 245 public: QueryOr(size_t n_subqueries)246 explicit QueryOr(size_t n_subqueries) : QueryOrLike(n_subqueries) { } 247 248 PostingIterator::Internal * postlist(QueryOptimiser * qopt, double factor) const; 249 250 void postlist_sub_or_like(OrContext& ctx, QueryOptimiser * qopt, double factor) const; 251 252 std::string get_description() const; 253 }; 254 255 class QueryAndNot : public QueryBranch { 256 Xapian::Query::op get_op() const; 257 258 public: QueryAndNot(size_t n_subqueries)259 explicit QueryAndNot(size_t n_subqueries) : QueryBranch(n_subqueries) { } 260 261 PostingIterator::Internal * postlist(QueryOptimiser * qopt, double factor) const; 262 263 void postlist_sub_and_like(AndContext& ctx, 264 QueryOptimiser* qopt, 265 double factor) const; 266 267 void add_subquery(const Xapian::Query & subquery); 268 269 Query::Internal * done(); 270 271 std::string get_description() const; 272 }; 273 274 class QueryXor : public QueryOrLike { 275 Xapian::Query::op get_op() const; 276 277 public: QueryXor(size_t n_subqueries)278 explicit QueryXor(size_t n_subqueries) : QueryOrLike(n_subqueries) { } 279 280 PostingIterator::Internal * postlist(QueryOptimiser * qopt, double factor) const; 281 282 void postlist_sub_xor(XorContext& ctx, QueryOptimiser * qopt, double factor) const; 283 284 std::string get_description() const; 285 }; 286 287 class QueryAndMaybe : public QueryBranch { 288 Xapian::Query::op get_op() const; 289 290 public: QueryAndMaybe(size_t n_subqueries)291 explicit QueryAndMaybe(size_t n_subqueries) : QueryBranch(n_subqueries) { } 292 293 PostingIterator::Internal * postlist(QueryOptimiser * qopt, double factor) const; 294 295 void postlist_sub_and_like(AndContext& ctx, 296 QueryOptimiser* qopt, 297 double factor) const; 298 299 void add_subquery(const Xapian::Query & subquery); 300 301 Query::Internal * done(); 302 303 std::string get_description() const; 304 }; 305 306 class QueryFilter : public QueryAndLike { 307 Xapian::Query::op get_op() const; 308 309 public: QueryFilter(size_t n_subqueries)310 explicit QueryFilter(size_t n_subqueries) : QueryAndLike(n_subqueries) { } 311 312 PostingIterator::Internal * postlist(QueryOptimiser * qopt, double factor) const; 313 314 void postlist_sub_and_like(AndContext& ctx, QueryOptimiser * qopt, double factor) const; 315 316 std::string get_description() const; 317 }; 318 319 class QueryWindowed : public QueryAndLike { 320 protected: 321 Xapian::termcount window; 322 QueryWindowed(size_t n_subqueries,Xapian::termcount window_)323 QueryWindowed(size_t n_subqueries, Xapian::termcount window_) 324 : QueryAndLike(n_subqueries), window(window_) { } 325 326 void postlist_windowed(Xapian::Query::op op, AndContext& ctx, 327 QueryOptimiser * qopt, double factor) const; 328 329 public: get_window()330 size_t get_window() const { return window; } 331 332 Query::Internal * done(); 333 }; 334 335 class QueryNear : public QueryWindowed { 336 Xapian::Query::op get_op() const; 337 338 public: QueryNear(size_t n_subqueries,Xapian::termcount window_)339 QueryNear(size_t n_subqueries, Xapian::termcount window_) 340 : QueryWindowed(n_subqueries, window_) { } 341 342 void serialise(std::string & result) const; 343 344 void postlist_sub_and_like(AndContext& ctx, QueryOptimiser * qopt, double factor) const; 345 346 std::string get_description() const; 347 }; 348 349 class QueryPhrase : public QueryWindowed { 350 Xapian::Query::op get_op() const; 351 352 public: QueryPhrase(size_t n_subqueries,Xapian::termcount window_)353 QueryPhrase(size_t n_subqueries, Xapian::termcount window_) 354 : QueryWindowed(n_subqueries, window_) { } 355 356 void serialise(std::string & result) const; 357 358 void postlist_sub_and_like(AndContext& ctx, QueryOptimiser * qopt, double factor) const; 359 360 std::string get_description() const; 361 }; 362 363 class QueryEliteSet : public QueryOrLike { 364 Xapian::Query::op get_op() const; 365 366 Xapian::termcount set_size; 367 368 public: QueryEliteSet(size_t n_subqueries,Xapian::termcount set_size_)369 QueryEliteSet(size_t n_subqueries, Xapian::termcount set_size_) 370 : QueryOrLike(n_subqueries), 371 set_size(set_size_ ? set_size_ : DEFAULT_ELITE_SET_SIZE) { } 372 373 void serialise(std::string & result) const; 374 375 PostingIterator::Internal * postlist(QueryOptimiser * qopt, double factor) const; 376 377 void postlist_sub_or_like(OrContext& ctx, QueryOptimiser * qopt, double factor) const; 378 379 std::string get_description() const; 380 }; 381 382 class QuerySynonym : public QueryOrLike { 383 Xapian::Query::op get_op() const; 384 385 public: QuerySynonym(size_t n_subqueries)386 explicit QuerySynonym(size_t n_subqueries) : QueryOrLike(n_subqueries) { } 387 388 PostingIterator::Internal * postlist(QueryOptimiser * qopt, double factor) const; 389 390 Query::Internal * done(); 391 392 std::string get_description() const; 393 }; 394 395 class QueryMax : public QueryOrLike { 396 Xapian::Query::op get_op() const; 397 398 public: QueryMax(size_t n_subqueries)399 explicit QueryMax(size_t n_subqueries) : QueryOrLike(n_subqueries) { } 400 401 PostingIterator::Internal * postlist(QueryOptimiser * qopt, double factor) const; 402 403 std::string get_description() const; 404 }; 405 406 class QueryWildcard : public Query::Internal { 407 std::string pattern; 408 409 Xapian::termcount max_expansion; 410 411 int max_type; 412 413 Query::op combiner; 414 415 Xapian::Query::op get_op() const; 416 417 public: QueryWildcard(const std::string & pattern_,Xapian::termcount max_expansion_,int max_type_,Query::op combiner_)418 QueryWildcard(const std::string &pattern_, 419 Xapian::termcount max_expansion_, 420 int max_type_, 421 Query::op combiner_) 422 : pattern(pattern_), 423 max_expansion(max_expansion_), 424 max_type(max_type_), 425 combiner(combiner_) 426 { } 427 428 Xapian::Query::op get_type() const XAPIAN_NOEXCEPT XAPIAN_PURE_FUNCTION; 429 get_pattern()430 const std::string & get_pattern() const { return pattern; } 431 432 PostingIterator::Internal * postlist(QueryOptimiser * qopt, double factor) const; 433 434 termcount get_length() const XAPIAN_NOEXCEPT XAPIAN_PURE_FUNCTION; 435 436 void serialise(std::string & result) const; 437 438 /** Change the combining operator. 439 * 440 * If there's only one reference to this object we change in-place 441 * and return a pointer to the existing object; otherwise we create and 442 * return a new QueryWildcard object. 443 */ change_combiner(Xapian::Query::op new_op)444 QueryWildcard* change_combiner(Xapian::Query::op new_op) { 445 if (_refs == 1) { 446 combiner = new_op; 447 return this; 448 } 449 return new QueryWildcard(pattern, 450 max_expansion, 451 max_type, 452 new_op); 453 } 454 455 std::string get_description() const; 456 }; 457 458 class QueryInvalid : public Query::Internal { 459 public: QueryInvalid()460 QueryInvalid() { } 461 462 Xapian::Query::op get_type() const XAPIAN_NOEXCEPT XAPIAN_PURE_FUNCTION; 463 464 PostingIterator::Internal * postlist(QueryOptimiser * qopt, double factor) const; 465 466 void serialise(std::string & result) const; 467 468 std::string get_description() const; 469 }; 470 471 } 472 473 } 474 475 #endif // XAPIAN_INCLUDED_QUERYINTERNAL_H 476