Ticket #280: patch
File patch, 21.5 KB (added by , 16 years ago) |
---|
-
tests/internaltest.cc
451 451 for (query = queries.begin(); query != queries.end(); query++) { 452 452 Xapian::Query::Internal * qint; 453 453 454 s = query->internal ->serialise();454 s = query->internalptr->get()->serialise(); 455 455 qint = Xapian::Query::Internal::unserialise(s); 456 456 457 457 TEST(qint->serialise() == s); -
include/xapian/query.h
33 33 #include <xapian/termiterator.h> 34 34 #include <xapian/visibility.h> 35 35 36 // FIXME: sort this out so we avoid exposing Xapian::Query::Internal37 // - we need to at present so that the Xapian::Query's template ctors38 // compile.39 class LocalSubMatch;40 class MultiMatch;41 class QueryOptimiser;42 struct SortPosName;43 44 36 namespace Xapian { 45 37 46 38 class PostingSource; … … 53 45 public: 54 46 /// Class holding details of the query 55 47 class Internal; 56 /// @private @internal Reference counted internals.57 Xapian::Internal::RefCntPtr<Internal> internal;58 48 49 /// Refcount pointer to class holding details of the query. 50 struct InternalPtr; 51 52 /// @private @internal Pointer to reference counted internals. 53 InternalPtr * internalptr; 54 59 55 /// Enum of possible query operations 60 56 typedef enum { 61 57 /// Return iff both subqueries are satisfied … … 252 248 253 249 template <class Iterator> 254 250 Query::Query(Query::op op_, Iterator qbegin, Iterator qend, termcount parameter) 255 : internal (0)251 : internalptr(0) 256 252 { 257 253 try { 258 254 start_construction(op_, parameter); … … 270 266 } 271 267 } 272 268 273 #ifndef SWIG // SWIG has no interest in the internal class, so hide it completely.274 275 /// @internal Internal class, implementing most of Xapian::Query.276 class XAPIAN_VISIBILITY_DEFAULT Query::Internal : public Xapian::Internal::RefCntBase {277 friend class ::LocalSubMatch;278 friend class ::MultiMatch;279 friend class ::QueryOptimiser;280 friend struct ::SortPosName;281 friend class Query;282 public:283 static const int OP_LEAF = -1;284 static const int OP_EXTERNAL_SOURCE = -2;285 286 /// The container type for storing pointers to subqueries287 typedef std::vector<Internal *> subquery_list;288 289 /// Type storing the operation290 typedef int op_t;291 292 private:293 /// Operation to be performed at this node294 Xapian::Query::Internal::op_t op;295 296 /// Sub queries on which to perform operation297 subquery_list subqs;298 299 /** For NEAR or PHRASE, how close terms must be to match: all terms300 * within the operation must occur in a window of this size.301 *302 * For ELITE_SET, the number of terms to select from those specified.303 *304 * For RANGE, the value number to apply the range test to.305 */306 Xapian::termcount parameter;307 308 /** Term that this node represents, or start of a range query.309 *310 * For a leaf node, this holds the term name. For an OP_VALUE_RANGE311 * query this holds the start of the range. For an OP_VALUE_GE or312 * OP_VALUE_LE query this holds the value to compare against.313 */314 std::string tname;315 316 /** Used to store the end of a range query. */317 std::string str_parameter;318 319 /// Position in query of this term - leaf node only320 Xapian::termpos term_pos;321 322 /// Within query frequency of this term - leaf node only323 Xapian::termcount wqf;324 325 /// External posting source.326 Xapian::PostingSource * external_source;327 328 /** swap the contents of this with another Xapian::Query::Internal,329 * in a way which is guaranteed not to throw. This is330 * used with the assignment operator to make it exception331 * safe.332 * It's important to adjust swap with any addition of333 * member variables!334 */335 void swap(Query::Internal &other);336 337 /// Copy another Xapian::Query::Internal into self.338 void initialise_from_copy(const Query::Internal & copyme);339 340 void accumulate_terms(341 std::vector<std::pair<std::string, Xapian::termpos> > &terms) const;342 343 /** Simplify the query.344 * For example, an AND query with only one subquery would become the345 * subquery itself.346 */347 Internal * simplify_query();348 349 /** Perform checks that query is valid. (eg, has correct number of350 * sub queries.) Throw an exception if not. This is initially called351 * on the query before any simplifications have been made, and after352 * simplications.353 */354 void validate_query() const;355 356 /** Simplify any matchnothing subqueries, either eliminating them,357 * or setting this query to matchnothing, depending on the query358 * operator. Returns true if simplification resulted in a359 * matchnothing query.360 */361 bool simplify_matchnothing();362 363 /** Get a string describing the given query type.364 */365 static std::string get_op_name(Xapian::Query::Internal::op_t op);366 367 /** Collapse the subqueries together if appropriate.368 */369 void collapse_subqs();370 371 /** Flatten a query structure, by changing, for example,372 * "A NEAR (B AND C)" to "(A NEAR B) AND (A NEAR C)"373 */374 void flatten_subqs();375 376 /** Implementation of serialisation; called recursively.377 */378 std::string serialise(Xapian::termpos & curpos) const;379 380 public:381 /** Copy constructor. */382 Internal(const Query::Internal & copyme);383 384 /** Assignment. */385 void operator=(const Query::Internal & copyme);386 387 /** A query consisting of a single term. */388 explicit Internal(const std::string & tname_, Xapian::termcount wqf_ = 1,389 Xapian::termpos term_pos_ = 0);390 391 /** Create internals given only the operator and a parameter. */392 Internal(op_t op_, Xapian::termcount parameter);393 394 /** Construct a range query on a document value. */395 Internal(op_t op_, Xapian::valueno valno,396 const std::string &begin, const std::string &end);397 398 /** Construct a value greater-than-or-equal query on a document value.399 */400 Internal(op_t op_, Xapian::valueno valno, const std::string &value);401 402 /// Construct an external source query.403 explicit Internal(Xapian::PostingSource * external_source_);404 405 /** Destructor. */406 ~Internal();407 408 static Xapian::Query::Internal * unserialise(const std::string &s);409 410 /** Add a subquery.411 */412 void add_subquery(const Query::Internal * subq);413 414 void set_dbl_parameter(double dbl_parameter_);415 416 double get_dbl_parameter() const;417 418 /** Finish off the construction.419 */420 Query::Internal * end_construction();421 422 /** Return a string in an easily parsed form423 * which contains all the information in a query.424 */425 std::string serialise() const {426 Xapian::termpos curpos = 1;427 return serialise(curpos);428 }429 430 /// Return a string describing this object.431 std::string get_description() const;432 433 /** Get the numeric parameter used in this query.434 *435 * This is used by the QueryParser to get the value number for436 * VALUE_RANGE queries. It should be replaced by a public method on437 * the Query class at some point, but the API which should be used for438 * that is unclear, so this is a temporary workaround.439 */440 Xapian::termcount get_parameter() const { return parameter; }441 442 /** Get the length of the query, used by some ranking formulae.443 * This value is calculated automatically - if you want to override444 * it you can pass a different value to Enquire::set_query().445 */446 Xapian::termcount get_length() const;447 448 /** Return an iterator over all the terms in the query,449 * in order of termpos. If multiple terms have the same term450 * position, their order is unspecified. Duplicates (same term and451 * termpos) will be removed.452 */453 TermIterator get_terms() const;454 };455 456 #endif // SWIG457 458 269 } 459 270 460 271 #endif /* XAPIAN_INCLUDED_QUERY_H */ -
common/omqueryinternal.h
24 24 // because of the templated members of Xapian::Query. 25 25 #include <xapian/query.h> 26 26 27 class LocalSubMatch; 28 class MultiMatch; 29 class QueryOptimiser; 30 struct SortPosName; 31 32 namespace Xapian { 33 34 /// @internal Internal class, implementing most of Xapian::Query. 35 class XAPIAN_VISIBILITY_DEFAULT Query::Internal : public Xapian::Internal::RefCntBase { 36 friend class ::LocalSubMatch; 37 friend class ::MultiMatch; 38 friend class ::QueryOptimiser; 39 friend struct ::SortPosName; 40 friend class Query; 41 public: 42 static const int OP_LEAF = -1; 43 static const int OP_EXTERNAL_SOURCE = -2; 44 45 /// The container type for storing pointers to subqueries 46 typedef std::vector<Internal *> subquery_list; 47 48 /// Type storing the operation 49 typedef int op_t; 50 51 private: 52 /// Operation to be performed at this node 53 Xapian::Query::Internal::op_t op; 54 55 /// Sub queries on which to perform operation 56 subquery_list subqs; 57 58 /** For NEAR or PHRASE, how close terms must be to match: all terms 59 * within the operation must occur in a window of this size. 60 * 61 * For ELITE_SET, the number of terms to select from those specified. 62 * 63 * For RANGE, the value number to apply the range test to. 64 */ 65 Xapian::termcount parameter; 66 67 /** Term that this node represents, or start of a range query. 68 * 69 * For a leaf node, this holds the term name. For an OP_VALUE_RANGE 70 * query this holds the start of the range. For an OP_VALUE_GE or 71 * OP_VALUE_LE query this holds the value to compare against. 72 */ 73 std::string tname; 74 75 /** Used to store the end of a range query. */ 76 std::string str_parameter; 77 78 /// Position in query of this term - leaf node only 79 Xapian::termpos term_pos; 80 81 /// Within query frequency of this term - leaf node only 82 Xapian::termcount wqf; 83 84 /// External posting source. 85 Xapian::PostingSource * external_source; 86 87 /** swap the contents of this with another Xapian::Query::Internal, 88 * in a way which is guaranteed not to throw. This is 89 * used with the assignment operator to make it exception 90 * safe. 91 * It's important to adjust swap with any addition of 92 * member variables! 93 */ 94 void swap(Query::Internal &other); 95 96 /// Copy another Xapian::Query::Internal into self. 97 void initialise_from_copy(const Query::Internal & copyme); 98 99 void accumulate_terms( 100 std::vector<std::pair<std::string, Xapian::termpos> > &terms) const; 101 102 /** Simplify the query. 103 * For example, an AND query with only one subquery would become the 104 * subquery itself. 105 */ 106 Internal * simplify_query(); 107 108 /** Perform checks that query is valid. (eg, has correct number of 109 * sub queries.) Throw an exception if not. This is initially called 110 * on the query before any simplifications have been made, and after 111 * simplications. 112 */ 113 void validate_query() const; 114 115 /** Simplify any matchnothing subqueries, either eliminating them, 116 * or setting this query to matchnothing, depending on the query 117 * operator. Returns true if simplification resulted in a 118 * matchnothing query. 119 */ 120 bool simplify_matchnothing(); 121 122 /** Get a string describing the given query type. 123 */ 124 static std::string get_op_name(Xapian::Query::Internal::op_t op); 125 126 /** Collapse the subqueries together if appropriate. 127 */ 128 void collapse_subqs(); 129 130 /** Flatten a query structure, by changing, for example, 131 * "A NEAR (B AND C)" to "(A NEAR B) AND (A NEAR C)" 132 */ 133 void flatten_subqs(); 134 135 /** Implementation of serialisation; called recursively. 136 */ 137 std::string serialise(Xapian::termpos & curpos) const; 138 139 public: 140 /** Copy constructor. */ 141 Internal(const Query::Internal & copyme); 142 143 /** Assignment. */ 144 void operator=(const Query::Internal & copyme); 145 146 /** A query consisting of a single term. */ 147 explicit Internal(const std::string & tname_, Xapian::termcount wqf_ = 1, 148 Xapian::termpos term_pos_ = 0); 149 150 /** Create internals given only the operator and a parameter. */ 151 Internal(op_t op_, Xapian::termcount parameter); 152 153 /** Construct a range query on a document value. */ 154 Internal(op_t op_, Xapian::valueno valno, 155 const std::string &begin, const std::string &end); 156 157 /** Construct a value greater-than-or-equal query on a document value. 158 */ 159 Internal(op_t op_, Xapian::valueno valno, const std::string &value); 160 161 /// Construct an external source query. 162 explicit Internal(Xapian::PostingSource * external_source_); 163 164 /** Destructor. */ 165 ~Internal(); 166 167 static Xapian::Query::Internal * unserialise(const std::string &s); 168 169 /** Add a subquery. 170 */ 171 void add_subquery(const Query::Internal * subq); 172 173 void set_dbl_parameter(double dbl_parameter_); 174 175 double get_dbl_parameter() const; 176 177 /** Finish off the construction. 178 */ 179 Query::Internal * end_construction(); 180 181 /** Return a string in an easily parsed form 182 * which contains all the information in a query. 183 */ 184 std::string serialise() const { 185 Xapian::termpos curpos = 1; 186 return serialise(curpos); 187 } 188 189 /// Return a string describing this object. 190 std::string get_description() const; 191 192 /** Get the numeric parameter used in this query. 193 * 194 * This is used by the QueryParser to get the value number for 195 * VALUE_RANGE queries. It should be replaced by a public method on 196 * the Query class at some point, but the API which should be used for 197 * that is unclear, so this is a temporary workaround. 198 */ 199 Xapian::termcount get_parameter() const { return parameter; } 200 201 /** Get the length of the query, used by some ranking formulae. 202 * This value is calculated automatically - if you want to override 203 * it you can pass a different value to Enquire::set_query(). 204 */ 205 Xapian::termcount get_length() const; 206 207 /** Return an iterator over all the terms in the query, 208 * in order of termpos. If multiple terms have the same term 209 * position, their order is unspecified. Duplicates (same term and 210 * termpos) will be removed. 211 */ 212 TermIterator get_terms() const; 213 }; 214 215 struct XAPIAN_VISIBILITY_DEFAULT Query::InternalPtr { 216 Xapian::Internal::RefCntPtr<Query::Internal> ptr; 217 218 InternalPtr() : ptr(0) {} 219 ~InternalPtr() { ptr = 0; } 220 Query::Internal * get() const { return ptr.get(); } 221 }; 222 223 } 224 27 225 #endif // XAPIAN_INCLUDED_OMQUERYINTERNAL_H -
api/omquery.cc
45 45 Query::add_subquery(const Query & subq) 46 46 { 47 47 DEBUGAPICALL(void, "Xapian::Query::add_subquery", subq); 48 Assert(internal.get()); 49 internal->add_subquery(subq.internal.get()); 48 Assert(internalptr); 49 Assert(internalptr->get()); 50 internalptr->get()->add_subquery(subq.internalptr->get()); 50 51 } 51 52 52 53 /// Add a subquery by pointer … … 57 58 if (subq == 0) { 58 59 throw InvalidArgumentError("Pointer to subquery may not be null"); 59 60 } 60 Assert(internal.get()); 61 internal->add_subquery(subq->internal.get()); 61 Assert(internalptr); 62 Assert(internalptr->get()); 63 internalptr->get()->add_subquery(subq->internalptr->get()); 62 64 } 63 65 64 66 /// Add a subquery which is a single term … … 66 68 Query::add_subquery(const string & tname) 67 69 { 68 70 DEBUGAPICALL(void, "Xapian::Query::add_subquery", tname); 69 Assert(internal.get()); 71 Assert(internalptr); 72 Assert(internalptr->get()); 70 73 Query::Internal subqint(tname); 71 internal ->add_subquery(&subqint);74 internalptr->ptr->add_subquery(&subqint); 72 75 } 73 76 74 77 /// Setup the internals for the query, with the appropriate operator. … … 76 79 Query::start_construction(Query::op op_, termcount parameter) 77 80 { 78 81 DEBUGAPICALL(void, "Xapian::Query::start_construction", op_); 79 Assert(!internal.get()); 80 internal = new Query::Internal(op_, parameter); 82 Assert(!internalptr); 83 internalptr = new Query::InternalPtr(); 84 internalptr->ptr = new Query::Internal(op_, parameter); 81 85 } 82 86 83 87 /// Check that query has an appropriate number of arguments, etc, … … 85 89 Query::end_construction() 86 90 { 87 91 DEBUGAPICALL(void, "Xapian::Query::end_construction", ""); 88 Assert(internal.get()); 89 internal = internal->end_construction(); 92 Assert(internalptr); 93 Assert(internalptr->get()); 94 internalptr->ptr = internalptr->get()->end_construction(); 90 95 } 91 96 92 97 /// Abort construction of the query: delete internal. … … 94 99 Query::abort_construction() 95 100 { 96 101 DEBUGAPICALL(void, "Xapian::Query::abort_construction", ""); 97 Assert(internal.get()); 98 internal = 0; 102 if (internalptr) { 103 internalptr->ptr = 0; 104 } 99 105 } 100 106 101 107 Query::Query(const string & tname_, termcount wqf_, termpos pos_) 102 : internal (new Query::Internal(tname_, wqf_, pos_))108 : internalptr(new Query::InternalPtr()) 103 109 { 104 110 DEBUGAPICALL(void, "Xapian::Query::Query", 105 111 tname_ << ", " << wqf_ << ", " << pos_); 112 internalptr->ptr = new Query::Internal(tname_, wqf_, pos_); 106 113 } 107 114 108 115 Query::Query(Query::op op_, const Query &left, const Query &right) 109 : internal (new Query::Internal(op_, 0u))116 : internalptr(new Query::InternalPtr()) 110 117 { 111 118 DEBUGAPICALL(void, "Xapian::Query::Query", 112 119 op_ << ", " << left << ", " << right); 120 internalptr->ptr = new Query::Internal(op_, 0u); 113 121 try { 114 122 add_subquery(left); 115 123 add_subquery(right); … … 125 133 DEBUGAPICALL(void, "Xapian::Query::Query", 126 134 op_ << ", " << q << ", " << parameter); 127 135 if (op_ == OP_SCALE_WEIGHT) { 128 if (!q.internal .get() ||129 q.internal ->op == OP_VALUE_RANGE ||130 q.internal ->op == OP_VALUE_GE ||131 q.internal ->op == OP_VALUE_LE) {136 if (!q.internalptr->get() || 137 q.internalptr->get()->op == OP_VALUE_RANGE || 138 q.internalptr->get()->op == OP_VALUE_GE || 139 q.internalptr->get()->op == OP_VALUE_LE) { 132 140 // Applying OP_SCALE_WEIGHT to Xapian::Query or OP_VALUE_* 133 141 // has no effect as they're all pure-boolean. 134 internal = q.internal; 142 Assert(!internalptr); 143 internalptr = new Query::InternalPtr(); 144 internalptr->ptr = q.internalptr->ptr; 135 145 return; 136 146 } 137 147 } 138 148 try { 139 149 start_construction(op_, 0); 140 internal ->set_dbl_parameter(parameter);150 internalptr->get()->set_dbl_parameter(parameter); 141 151 add_subquery(q); 142 152 end_construction(); 143 153 } catch (...) { … … 148 158 149 159 Query::Query(Query::op op_, Xapian::valueno valno, 150 160 const string &begin, const string &end) 151 : internal(new Query::Internal(op_, valno, begin, end))161 : internalptr(new Query::InternalPtr()) 152 162 { 153 163 DEBUGAPICALL(void, "Xapian::Query::Query", 154 164 op_ << ", " << valno << ", " << begin << ", " << end); 165 internalptr->ptr = new Query::Internal(op_, valno, begin, end); 155 166 } 156 167 157 168 Query::Query(Query::op op_, Xapian::valueno valno, const std::string &value) 158 : internal(new Query::Internal(op_, valno, value))169 : internalptr(new Query::InternalPtr()) 159 170 { 160 171 DEBUGAPICALL(void, "Xapian::Query::Query", 161 172 op_ << ", " << valno << ", " << value); 173 internalptr->ptr = new Query::Internal(op_, valno, value); 162 174 } 163 175 164 176 Query::Query(PostingSource * external_source) 165 : internal (new Query::Internal(external_source))177 : internalptr(new Query::InternalPtr()) 166 178 { 167 179 DEBUGAPICALL(void, "Xapian::Query::Query", external_source); 180 internalptr->ptr = new Query::Internal(external_source); 168 181 } 169 182 170 183 // Copy constructor 171 184 Query::Query(const Query & copyme) 172 : internal (copyme.internal)185 : internalptr(new Query::InternalPtr()) 173 186 { 174 187 DEBUGAPICALL(void, "Xapian::Query::Query", copyme); 188 internalptr->ptr = copyme.internalptr->ptr; 175 189 } 176 190 177 191 // Assignment … … 179 193 Query::operator=(const Query & copyme) 180 194 { 181 195 DEBUGAPICALL(Xapian::Query &, "Xapian::Query::operator=", copyme); 182 internal = copyme.internal;196 internalptr->ptr = copyme.internalptr->ptr; 183 197 RETURN(*this); 184 198 } 185 199 186 200 // Default constructor 187 Query::Query() : internal (0)201 Query::Query() : internalptr(new Query::InternalPtr()) 188 202 { 189 203 DEBUGAPICALL(void, "Xapian::Query::Query", ""); 190 204 } … … 193 207 Query::~Query() 194 208 { 195 209 DEBUGAPICALL(void, "Xapian::Query::~Query", ""); 210 delete internalptr; 196 211 } 197 212 198 213 std::string 199 214 Query::get_description() const 200 215 { 201 216 std::string res("Xapian::Query("); 202 if (internal .get()) res += internal->get_description();217 if (internalptr->get()) res += internalptr->get()->get_description(); 203 218 res += ")"; 204 219 return res; 205 220 } … … 207 222 termcount Query::get_length() const 208 223 { 209 224 DEBUGAPICALL(Xapian::termcount, "Xapian::Query::get_length", ""); 210 RETURN(internal .get() ? internal->get_length() : 0);225 RETURN(internalptr->get() ? internalptr->get()->get_length() : 0); 211 226 } 212 227 213 228 TermIterator Query::get_terms_begin() const 214 229 { 215 230 DEBUGAPICALL(Xapian::TermIterator, "Xapian::Query::get_terms_begin", ""); 216 if (!internal .get()) RETURN(TermIterator(NULL));217 RETURN(internal ->get_terms());231 if (!internalptr->get()) RETURN(TermIterator(NULL)); 232 RETURN(internalptr->get()->get_terms()); 218 233 } 219 234 220 235 bool 221 236 Query::empty() const 222 237 { 223 238 DEBUGAPICALL(void, "Xapian::Query::empty", ""); 224 return internal .get() == 0;239 return internalptr->get() == 0; 225 240 } 226 241 227 242 Query::Query(Query::op op_, const std::string & left, const std::string & right) 228 : internal(0)243 : internalptr(0) 229 244 { 230 245 try { 231 246 start_construction(op_, 0); -
api/omenquire.cc
631 631 } 632 632 633 633 Stats stats; 634 ::MultiMatch match(db, query.internal .get(), qlen, rset, collapse_key,634 ::MultiMatch match(db, query.internalptr->get(), qlen, rset, collapse_key, 635 635 percent_cutoff, weight_cutoff, 636 636 order, sort_key, sort_by, sort_value_forward, sorter, 637 637 errorhandler, stats, weight);