Ticket #295: remotepostsource.patch
File remotepostsource.patch, 31.5 KB (added by , 16 years ago) |
---|
-
xapian-core/matcher/externalpostlist.cc
29 29 30 30 using namespace std; 31 31 32 ExternalPostList::ExternalPostList(Xapian::PostingSource *source_, 32 ExternalPostList::ExternalPostList(const Xapian::Database & db, 33 Xapian::PostingSource *source_, 33 34 double factor_) 34 : source(source_), current(0), factor(factor_)35 : source(source_), source_is_owned(false), current(0), factor(factor_) 35 36 { 36 37 Assert(source); 37 source->reset(); 38 Xapian::PostingSource * newsource = source->clone(); 39 if (newsource != NULL) { 40 source = newsource; 41 source_is_owned = true; 42 } 43 source->reset(db); 38 44 } 39 45 46 ExternalPostList::~ExternalPostList() 47 { 48 if (source_is_owned) { 49 delete source; 50 } 51 } 52 40 53 Xapian::doccount 41 54 ExternalPostList::get_termfreq_min() const 42 55 { -
xapian-core/matcher/queryoptimiser.cc
64 64 65 65 case Xapian::Query::Internal::OP_EXTERNAL_SOURCE: 66 66 Assert(query->external_source); 67 RETURN(new ExternalPostList(query->external_source, factor)); 67 RETURN(new ExternalPostList( 68 Xapian::Database(const_cast<Xapian::Database::Internal *>(&db)), 69 query->external_source, factor)); 68 70 69 71 case Xapian::Query::OP_AND: 70 72 case Xapian::Query::OP_FILTER: -
xapian-core/matcher/externalpostlist.h
29 29 30 30 class ExternalPostList : public PostList { 31 31 Xapian::PostingSource * source; 32 bool source_is_owned; 32 33 33 34 Xapian::docid current; 34 35 … … 43 44 PostList * update_after_advance(); 44 45 45 46 public: 46 ExternalPostList(Xapian::PostingSource *source_, double factor_); 47 ExternalPostList(const Xapian::Database & db, 48 Xapian::PostingSource *source_, 49 double factor_); 50 ~ExternalPostList(); 47 51 48 52 Xapian::doccount get_termfreq_min() const; 49 53 -
xapian-core/tests/api_db.cc
1887 1887 : num_docs(db.get_doccount()), last_docid(db.get_lastdocid()), did(0) 1888 1888 { } 1889 1889 1890 void reset() { did = 0; } 1890 MyOddPostingSource(Xapian::doccount num_docs_, 1891 Xapian::doccount last_docid_) 1892 : num_docs(num_docs_), last_docid(last_docid_), did(0) 1893 { } 1891 1894 1895 PostingSource * clone() const { return new MyOddPostingSource(num_docs, last_docid); } 1896 1897 void reset(const Xapian::Database &) { did = 0; } 1898 1892 1899 // These bounds could be better, but that's not important here. 1893 1900 Xapian::doccount get_termfreq_min() const { return 0; } 1894 1901 … … 1925 1932 Xapian::Enquire enq(db); 1926 1933 MyOddPostingSource src(db); 1927 1934 1928 // Check that passing NULL is rejected as intended. 1929 TEST_EXCEPTION(Xapian::InvalidArgumentError, Xapian::Query bad(NULL)); 1930 Xapian::PostingSource * nullsrc = NULL; 1931 TEST_EXCEPTION(Xapian::InvalidArgumentError, Xapian::Query bad(nullsrc)); 1932 1933 enq.set_query(Xapian::Query(&src)); 1935 enq.set_query(Xapian::Query(src)); 1934 1936 1935 1937 Xapian::MSet mset = enq.get_mset(0, 10); 1936 1938 mset_expect_order(mset, 1, 3, 5, 7, 9, 11, 13, 15, 17); 1937 1939 1938 1940 Xapian::Query q(Xapian::Query::OP_FILTER, 1939 1941 Xapian::Query("leav"), 1940 Xapian::Query( &src));1942 Xapian::Query(src)); 1941 1943 enq.set_query(q); 1942 1944 1943 1945 mset = enq.get_mset(0, 10); … … 1953 1955 Xapian::Enquire enq(db); 1954 1956 MyOddPostingSource src(db); 1955 1957 1956 enq.set_query(Xapian::Query( &src));1958 enq.set_query(Xapian::Query(src)); 1957 1959 1958 1960 TEST_EXCEPTION(Xapian::UnimplementedError, 1959 1961 Xapian::MSet mset = enq.get_mset(0, 10)); 1960 1962 1961 1963 Xapian::Query q(Xapian::Query::OP_FILTER, 1962 1964 Xapian::Query("leav"), 1963 Xapian::Query( &src));1965 Xapian::Query(src)); 1964 1966 enq.set_query(q); 1965 1967 1966 1968 TEST_EXCEPTION(Xapian::UnimplementedError, … … 1981 1983 : num_docs(db.get_doccount()), last_docid(db.get_lastdocid()), did(0) 1982 1984 { } 1983 1985 1984 void reset() { did = 0; } 1986 MyOddWeightingPostingSource(Xapian::doccount num_docs_, 1987 Xapian::doccount last_docid_) 1988 : num_docs(num_docs_), last_docid(last_docid_), did(0) 1989 { } 1985 1990 1991 PostingSource * clone() const { return new MyOddWeightingPostingSource(num_docs, last_docid); } 1992 1993 void reset(const Xapian::Database &) { did = 0; } 1994 1986 1995 Xapian::weight get_weight() const { 1987 1996 return (did % 2) ? 1000 : 0.001; 1988 1997 } … … 2028 2037 Xapian::Enquire enq(db); 2029 2038 MyOddWeightingPostingSource src(db); 2030 2039 2031 enq.set_query(Xapian::Query( &src));2040 enq.set_query(Xapian::Query(src)); 2032 2041 2033 2042 Xapian::MSet mset = enq.get_mset(0, 10); 2034 2043 mset_expect_order(mset, 1, 3, 5, 7, 9, 11, 13, 15, 17, 2); 2035 2044 2036 2045 Xapian::Query q(Xapian::Query::OP_OR, 2037 2046 Xapian::Query("leav"), 2038 Xapian::Query( &src));2047 Xapian::Query(src)); 2039 2048 enq.set_query(q); 2040 2049 2041 2050 mset = enq.get_mset(0, 5); … … 2051 2060 tout << "max possible weight = " << mset.get_max_possible() << endl; 2052 2061 TEST(mset.get_max_possible() > 1000); 2053 2062 2054 enq.set_query(Xapian::Query(q.OP_SCALE_WEIGHT, Xapian::Query( &src), 0.5));2063 enq.set_query(Xapian::Query(q.OP_SCALE_WEIGHT, Xapian::Query(src), 0.5)); 2055 2064 mset = enq.get_mset(0, 10); 2056 2065 TEST(mset.empty()); 2057 2066 2058 2067 TEST_EQUAL(mset.get_max_possible(), 500); 2059 2068 2060 enq.set_query(Xapian::Query(q.OP_SCALE_WEIGHT, Xapian::Query( &src), 2));2069 enq.set_query(Xapian::Query(q.OP_SCALE_WEIGHT, Xapian::Query(src), 2)); 2061 2070 mset = enq.get_mset(0, 10); 2062 2071 mset_expect_order(mset, 1, 3, 5, 7, 9, 11, 13, 15, 17); 2063 2072 … … 2078 2087 : num_docs(db.get_doccount()), last_docid(db.get_lastdocid()), did(0) 2079 2088 { } 2080 2089 2081 void reset() { did = 0; } 2090 MyDontAskWeightPostingSource(Xapian::doccount num_docs_, 2091 Xapian::doccount last_docid_) 2092 : num_docs(num_docs_), last_docid(last_docid_), did(0) 2093 { } 2082 2094 2095 PostingSource * clone() const { return new MyDontAskWeightPostingSource(num_docs, last_docid); } 2096 2097 void reset(const Xapian::Database &) { did = 0; } 2098 2083 2099 Xapian::weight get_weight() const { 2084 2100 FAIL_TEST("MyDontAskWeightPostingSource::get_weight() called"); 2085 2101 } … … 2126 2142 MyDontAskWeightPostingSource src(db); 2127 2143 2128 2144 tout << "OP_SCALE_WEIGHT 0" << endl; 2129 enq.set_query(Xapian::Query(Xapian::Query::OP_SCALE_WEIGHT, Xapian::Query( &src), 0));2145 enq.set_query(Xapian::Query(Xapian::Query::OP_SCALE_WEIGHT, Xapian::Query(src), 0)); 2130 2146 2131 2147 Xapian::MSet mset = enq.get_mset(0, 5); 2132 2148 mset_expect_order(mset, 1, 2, 3, 4, 5); … … 2134 2150 tout << "OP_FILTER" << endl; 2135 2151 Xapian::Query q(Xapian::Query::OP_FILTER, 2136 2152 Xapian::Query("leav"), 2137 Xapian::Query( &src));2153 Xapian::Query(src)); 2138 2154 enq.set_query(q); 2139 2155 2140 2156 mset = enq.get_mset(0, 5); 2141 2157 mset_expect_order(mset, 8, 6, 4, 5, 7); 2142 2158 2143 2159 tout << "BoolWeight" << endl; 2144 enq.set_query(Xapian::Query( &src));2160 enq.set_query(Xapian::Query(src)); 2145 2161 enq.set_weighting_scheme(Xapian::BoolWeight()); 2146 2162 2147 2163 //mset = enq.get_mset(0, 5); … … 2151 2167 } 2152 2168 2153 2169 // Check that valueweightsource works correctly. 2154 DEFINE_TESTCASE(valueweightsource1, backend && !remote) { 2155 // FIXME: PostingSource doesn't currently work well with multi databases 2156 // but we should try to resolve that issue. 2157 SKIP_TEST_FOR_BACKEND("multi"); 2170 DEFINE_TESTCASE(valueweightsource1, backend) { 2158 2171 Xapian::Database db(get_database("apitest_phrase")); 2159 2172 Xapian::Enquire enq(db); 2160 Xapian::ValueWeightPostingSource src( db,11);2173 Xapian::ValueWeightPostingSource src(11); 2161 2174 2162 2175 // Should be in descending order of length 2163 2176 tout << "RAW" << endl; 2164 enq.set_query(Xapian::Query( &src));2177 enq.set_query(Xapian::Query(src)); 2165 2178 Xapian::MSet mset = enq.get_mset(0, 5); 2166 2179 mset_expect_order(mset, 3, 1, 2, 8, 14); 2167 2180 … … 2169 2182 tout << "OP_FILTER" << endl; 2170 2183 Xapian::Query q(Xapian::Query::OP_FILTER, 2171 2184 Xapian::Query("leav"), 2172 Xapian::Query( &src));2185 Xapian::Query(src)); 2173 2186 enq.set_query(q); 2174 2187 mset = enq.get_mset(0, 5); 2175 2188 mset_expect_order(mset, 8, 6, 4, 5, 7); … … 2177 2190 // Should be in descending order of length 2178 2191 tout << "OP_FILTER other way" << endl; 2179 2192 q = Xapian::Query(Xapian::Query::OP_FILTER, 2180 Xapian::Query( &src),2193 Xapian::Query(src), 2181 2194 Xapian::Query("leav")); 2182 2195 enq.set_query(q); 2183 2196 mset = enq.get_mset(0, 5); … … 2189 2202 // Check that valueweightsource gives the correct bounds for those databases 2190 2203 // which support value statistics. 2191 2204 DEFINE_TESTCASE(valueweightsource2, backend && valuestats) { 2192 // FIXME: PostingSource doesn't currently work well with multi databases2193 // but we should try to resolve that issue.2194 SKIP_TEST_FOR_BACKEND("multi");2195 2205 Xapian::Database db(get_database("apitest_phrase")); 2196 Xapian::ValueWeightPostingSource src(db, 11); 2206 Xapian::ValueWeightPostingSource src(11); 2207 src.reset(db); 2197 2208 TEST_EQUAL(src.get_termfreq_min(), 17); 2198 2209 TEST_EQUAL(src.get_termfreq_est(), 17); 2199 2210 TEST_EQUAL(src.get_termfreq_max(), 17); … … 2204 2215 2205 2216 // Check that valueweightsource skip_to() can stay in the same position. 2206 2217 DEFINE_TESTCASE(valueweightsource3, backend && valuestats) { 2207 // FIXME: PostingSource doesn't currently work well with multi databases2208 // but we should try to resolve that issue.2209 SKIP_TEST_FOR_BACKEND("multi");2210 2218 Xapian::Database db(get_database("apitest_phrase")); 2211 Xapian::ValueWeightPostingSource src(db, 11); 2219 Xapian::ValueWeightPostingSource src(11); 2220 src.reset(db); 2212 2221 TEST(!src.at_end()); 2213 2222 src.skip_to(8, 0.0); 2214 2223 TEST(!src.at_end()); -
xapian-core/tests/api_percentages.cc
45 45 : maxwt(0.0), started(false) 46 46 {} 47 47 48 MyPostingSource(const std::vector<std::pair<Xapian::docid, Xapian::weight> > &weights_, 49 Xapian::weight maxwt_) 50 : weights(weights_), maxwt(maxwt_), started(false) 51 {} 52 53 54 PostingSource * clone() const 55 { 56 return new MyPostingSource(weights, maxwt); 57 } 58 48 59 void append_docweight(Xapian::docid did, Xapian::weight wt) 49 60 { 50 61 weights.push_back(make_pair(did, wt)); … … 55 66 if (wt > maxwt) maxwt = wt; 56 67 } 57 68 58 void reset( ) { started = false; }69 void reset(const Xapian::Database &) { started = false; } 59 70 60 71 Xapian::weight get_weight() const { 61 72 return i->second; … … 103 114 MyPostingSource source; 104 115 source.append_docweight(1, 100); 105 116 source.append_docweight(2, 50 - epsilons * DBL_EPSILON); 106 enquire.set_query(Xapian::Query( &source));117 enquire.set_query(Xapian::Query(source)); 107 118 Xapian::MSet mset = enquire.get_mset(0, 10); 108 119 TEST_EQUAL(mset.size(), 2); 109 120 if (mset[1].get_percent() != 50) break; … … 120 131 source.append_docweight(4, 50 - epsilons * DBL_EPSILON); 121 132 source.append_docweight(5, 25); 122 133 123 enquire.set_query(Xapian::Query( &source));134 enquire.set_query(Xapian::Query(source)); 124 135 Xapian::MSet mset1 = enquire.get_mset(0, 10); 125 136 TEST_EQUAL(mset1.size(), 5); 126 137 TEST_EQUAL(mset1[2].get_percent(), 50); -
xapian-core/include/xapian/postingsource.h
137 137 /// Return the current docid. 138 138 virtual Xapian::docid get_docid() const = 0; 139 139 140 /** Clone the posting source. 141 * 142 * The clone should inherit the configuration of the parent, but need not 143 * inherit the state. ie, the clone does not need to be in the same 144 * iteration position as the original: the matcher will always call 145 * reset() on the clone before attempting to move the iterator, or read 146 * the information about the current position of the iterator. 147 */ 148 virtual PostingSource * clone() const = 0; 149 150 /** Name of the posting source, for performing remote searches. 151 * 152 * If the subclass is called FooPostingSource, this should return "Foo". 153 * 154 * This should only be implemented if serialise() and unserialise() are 155 * also implemented. 156 * 157 * The default implmenentation returns an empty string, to indicate that 158 * serialise() and unserialise() are not implemented. 159 */ 160 virtual std::string name() const; 161 162 /** Serialise object parameters into a string. 163 * 164 * The serialised parameters should represent the configuration of the 165 * posting source, but need not (indeed, should not) represent the current 166 * iteration state. 167 */ 168 virtual std::string serialise() const; 169 170 /** Create object given string serialisation returned by serialise(). 171 * 172 * @param s A serialised instance of this PostingSource subclass. 173 */ 174 virtual PostingSource * unserialise(const std::string &s) const; 175 140 176 /** Reset this PostingSource to its freshly constructed state. 141 177 * 142 178 * This is called automatically by the matcher prior to each query being 143 179 * processed. 180 * 181 * FIXME - document the db parameter. 144 182 */ 145 virtual void reset( ) = 0;183 virtual void reset(const Database & db) = 0; 146 184 147 185 /** Return a string describing this object. 148 186 * … … 196 234 /// An upper bound on the value returned. 197 235 double max_value; 198 236 237 /// Upper bound on the value returned specified in constructor. 238 double specified_max_value; 239 199 240 public: 200 241 /** Construct a ValueWeightPostingSource. 201 242 * 202 243 * @param db_ The database to read values from. 203 244 * @param valno_ The value slot to read values from. 204 245 */ 205 ValueWeightPostingSource(Xapian:: Database db_, Xapian::valueno valno_);246 ValueWeightPostingSource(Xapian::valueno valno_); 206 247 207 248 /** Construct a ValueWeightPostingSource. 208 249 * … … 214 255 * constructor need only be used if more accurate information is 215 256 * available. 216 257 */ 217 ValueWeightPostingSource(Xapian::Database db_, Xapian::valueno valno_, 218 double max_weight_); 258 ValueWeightPostingSource(Xapian::valueno valno_, double max_weight_); 219 259 220 260 Xapian::doccount get_termfreq_min() const; 221 261 Xapian::doccount get_termfreq_est() const; … … 232 272 233 273 Xapian::docid get_docid() const; 234 274 235 void reset(); 275 ValueWeightPostingSource * clone() const; 276 std::string name() const; 277 std::string serialise() const; 278 PostingSource * unserialise(const std::string &s) const; 236 279 280 void reset(const Database & db_); 281 237 282 std::string get_description() const; 238 283 }; 239 284 -
xapian-core/include/xapian/query.h
25 25 #ifndef XAPIAN_INCLUDED_QUERY_H 26 26 #define XAPIAN_INCLUDED_QUERY_H 27 27 28 #include <map> 28 29 #include <string> 29 30 #include <vector> 30 31 … … 204 205 */ 205 206 Query(Query::op op_, Xapian::valueno valno, const std::string &value); 206 207 207 /// Construct an external source query. 208 explicit Query(Xapian::PostingSource * external_source); 208 /** Construct an external source query. 209 * 210 * The posting source will be cloned immediately, so the source 211 * supplied may be safely deallocated after this call. 212 * 213 * @param external_source The source to use in the query. 214 */ 215 explicit Query(const Xapian::PostingSource & external_source); 209 216 210 217 /** A query which matches all documents in the database. */ 211 218 static Xapian::Query MatchAll; … … 405 412 /** Destructor. */ 406 413 ~Internal(); 407 414 408 static Xapian::Query::Internal * unserialise(const std::string &s); 415 static Xapian::Query::Internal * unserialise(const std::string &s, 416 const std::map<std::string, Xapian::PostingSource *> &sources); 409 417 410 418 /** Add a subquery. 411 419 */ -
xapian-core/net/remoteserver.cc
114 114 wtschemes[weight->name()] = weight; 115 115 weight = new Xapian::TradWeight; 116 116 wtschemes[weight->name()] = weight; 117 118 Xapian::PostingSource * source; 119 source = new Xapian::ValueWeightPostingSource(0); 120 postingsources[source->name()] = source; 117 121 } 118 122 119 123 RemoteServer::~RemoteServer() … … 121 125 delete db; 122 126 // wdb is either NULL or equal to db, so we shouldn't delete it too! 123 127 124 map<string, Xapian::Weight*>::const_iterator i; 125 for (i = wtschemes.begin(); i != wtschemes.end(); ++i) { 126 delete i->second; 128 { 129 map<string, Xapian::Weight*>::const_iterator i; 130 for (i = wtschemes.begin(); i != wtschemes.end(); ++i) { 131 delete i->second; 132 } 127 133 } 134 135 { 136 map<string, Xapian::PostingSource *>::const_iterator i; 137 for (i = postingsources.begin(); i != postingsources.end(); ++i) { 138 delete i->second; 139 } 140 } 128 141 } 129 142 130 143 message_type … … 365 378 366 379 // Unserialise the Query. 367 380 len = decode_length(&p, p_end, true); 368 AutoPtr<Xapian::Query::Internal> query(Xapian::Query::Internal::unserialise(string(p, len) ));381 AutoPtr<Xapian::Query::Internal> query(Xapian::Query::Internal::unserialise(string(p, len), postingsources)); 369 382 p += len; 370 383 371 384 // Unserialise assorted Enquire settings. … … 610 623 611 624 send_message(REPLY_ADDDOCUMENT, encode_length(did)); 612 625 } 626 627 628 void 629 RemoteServer::register_posting_source(const Xapian::PostingSource &source) 630 { 631 if (source.name().empty()) { 632 throw Xapian::InvalidOperationError("Unable to register posting source - name() method returns empty string."); 633 } 634 Xapian::PostingSource * sourceclone = source.clone(); 635 if (!sourceclone) { 636 throw Xapian::InvalidOperationError("Unable to register posting source - clone() method returns NULL."); 637 } 638 try { 639 postingsources[source.name()] = sourceclone; 640 } catch(...) { 641 delete sourceclone; 642 throw; 643 } 644 } -
xapian-core/common/remoteserver.h
24 24 25 25 #include "xapian/database.h" 26 26 #include "xapian/enquire.h" 27 #include "xapian/postingsource.h" 27 28 #include "xapian/visibility.h" 28 29 29 30 #include "remoteconnection.h" … … 31 32 #include <map> 32 33 #include <string> 33 34 34 // Forward declaration35 namespace Xapian { class Weight; }36 37 35 using namespace std; 38 36 39 37 /** Remote backend server base class. */ … … 70 68 /// Registered weighting schemes. 71 69 map<string, Xapian::Weight *> wtschemes; 72 70 71 /// Registered external posting sources. 72 map<string, Xapian::PostingSource *> postingsources; 73 73 74 /// Accept a message from the client. 74 75 message_type get_message(Xapian::timeout timeout, string & result, 75 76 message_type required_type = MSG_MAX); … … 173 174 void register_weighting_scheme(const Xapian::Weight &wt) { 174 175 wtschemes[wt.name()] = wt.clone(); 175 176 } 177 178 /** Register a user-defined posting source class. 179 */ 180 void register_posting_source(const Xapian::PostingSource &source); 176 181 }; 177 182 178 183 #endif // XAPIAN_INCLUDED_REMOTESERVER_H -
xapian-core/api/omqueryinternal.cc
42 42 #include <cfloat> 43 43 #include <climits> 44 44 #include <cmath> 45 #include <map> 45 46 #include <set> 46 47 #include <vector> 47 48 … … 142 143 result += '['; 143 144 result += encode_length(tname.length()); 144 145 result += tname; 145 if (term_pos != curpos) result += '@' + om_tostring(term_pos); 146 if (wqf != 1) result += '#' + om_tostring(wqf); 146 if (term_pos != curpos) result += '@' + om_tostring(term_pos); // FIXME - should this use encode_length()? 147 if (wqf != 1) result += '#' + om_tostring(wqf); // FIXME - should this use encode_length()? 147 148 ++curpos; 148 149 } else if (op == Xapian::Query::Internal::OP_EXTERNAL_SOURCE) { 149 throw Xapian::UnimplementedError("Remote backend doesn't support PostingSource"); 150 string sourcename = external_source->name(); 151 if (sourcename.empty()) 152 throw Xapian::UnimplementedError("This PostingSource doesn't support remote use."); 153 result += '!'; 154 result += encode_length(sourcename.length()); 155 result += sourcename; 156 string sourcedata = external_source->serialise(); 157 result += encode_length(sourcedata.length()); 158 result += sourcedata; 150 159 } else { 151 160 result += "("; 152 161 for (subquery_list::const_iterator i = subqs.begin(); … … 158 167 case Xapian::Query::Internal::OP_LEAF: 159 168 Assert(false); 160 169 break; 170 case Xapian::Query::Internal::OP_EXTERNAL_SOURCE: 171 Assert(false); 172 break; 161 173 case Xapian::Query::OP_AND: 162 174 result += "&"; 163 175 break; … … 380 392 const char *p; 381 393 const char *end; 382 394 Xapian::termpos curpos; 395 const map<string, Xapian::PostingSource *> & sources; 383 396 384 397 Xapian::Query::Internal * readquery(); 398 Xapian::Query::Internal * readexternal(); 385 399 Xapian::Query::Internal * readcompound(); 386 400 387 401 public: 388 QUnserial(const string & s) : p(s.c_str()), end(p + s.size()), curpos(1) { } 402 QUnserial(const string & s, 403 const map<string, Xapian::PostingSource *> & sources_) 404 : p(s.c_str()), end(p + s.size()), curpos(1), sources(sources_) { } 389 405 Xapian::Query::Internal * decode(); 390 406 }; 391 407 … … 424 440 ++curpos; 425 441 return new Xapian::Query::Internal(tname, wqf, term_pos); 426 442 } 443 case '!': 444 return readexternal(); 427 445 case '(': 428 446 return readcompound(); 429 447 default: … … 432 450 } 433 451 } 434 452 453 Xapian::Query::Internal * 454 QUnserial::readexternal() 455 { 456 if (p == end) 457 throw Xapian::InvalidArgumentError("Bad serialised query"); 458 459 size_t length = decode_length(&p, end, true); 460 string sourcename(p, length); 461 map<string, Xapian::PostingSource *>::const_iterator i; 462 i = sources.find(string(p, length)); 463 if (i == sources.end()) { 464 throw Xapian::InvalidArgumentError("PostingSource " + string(p, length) + " not registered"); 465 } 466 467 p += length; 468 length = decode_length(&p, end, true); 469 string sourcedata(p, length); 470 p += length; 471 472 return new Xapian::Query::Internal(i->second->unserialise(sourcedata)); 473 } 474 435 475 static Xapian::Query::Internal * 436 476 qint_from_vector(Xapian::Query::op op, 437 477 const vector<Xapian::Query::Internal *> & vec, … … 476 516 --p; 477 517 subqs.push_back(readquery()); 478 518 break; 519 case '!': 520 subqs.push_back(readexternal()); 521 break; 479 522 case '(': { 480 523 subqs.push_back(readcompound()); 481 524 break; … … 563 606 } 564 607 565 608 Xapian::Query::Internal * 566 Xapian::Query::Internal::unserialise(const string &s) 609 Xapian::Query::Internal::unserialise(const string &s, 610 const map<string, Xapian::PostingSource *> & sources) 567 611 { 568 612 Assert(s.length() > 1); 569 QUnserial u(s );613 QUnserial u(s, sources); 570 614 Xapian::Query::Internal * qint = u.decode(); 571 615 AssertEq(s, qint->serialise()); 572 616 return qint; … … 608 652 str_parameter(copyme.str_parameter), 609 653 term_pos(copyme.term_pos), 610 654 wqf(copyme.wqf), 611 external_source( copyme.external_source)655 external_source(NULL) 612 656 { 613 657 for (subquery_list::const_iterator i = copyme.subqs.begin(); 614 658 i != copyme.subqs.end(); 615 659 ++i) { 616 660 subqs.push_back(new Xapian::Query::Internal(**i)); 617 661 } 662 if (copyme.external_source) { 663 external_source = copyme.external_source->clone(); 664 } 618 665 } 619 666 620 667 ////////////////////////////////////////// … … 627 674 parameter(0), 628 675 tname(tname_), 629 676 term_pos(term_pos_), 630 wqf(wqf_) 677 wqf(wqf_), 678 external_source(NULL) 631 679 { 632 680 validate_query(); 633 681 } … … 638 686 parameter(parameter_), 639 687 tname(), 640 688 term_pos(0), 641 wqf(0) 689 wqf(0), 690 external_source(NULL) 642 691 { 643 692 if (parameter != 0 && op != OP_PHRASE && op != OP_NEAR && op != OP_ELITE_SET) 644 693 throw Xapian::InvalidArgumentError("parameter is only meaningful for OP_NEAR, OP_PHRASE, or OP_ELITE_SET"); … … 649 698 : op(op_), 650 699 parameter(Xapian::termcount(valno)), 651 700 tname(begin), 652 str_parameter(end) 701 str_parameter(end), 702 external_source(NULL) 653 703 { 654 704 if (op != OP_VALUE_RANGE) 655 705 throw Xapian::InvalidArgumentError("This constructor is only meaningful for OP_VALUE_RANGE"); … … 660 710 const std::string &value) 661 711 : op(op_), 662 712 parameter(Xapian::termcount(valno)), 663 tname(value) 713 tname(value), 714 external_source(NULL) 664 715 { 665 716 if (op != OP_VALUE_GE && op != OP_VALUE_LE) 666 717 throw Xapian::InvalidArgumentError("This constructor is only meaningful for OP_VALUE_GE or OP_VALUE_LE"); … … 677 728 Xapian::Query::Internal::Internal(PostingSource * external_source_) 678 729 : op(OP_EXTERNAL_SOURCE), external_source(external_source_) 679 730 { 680 if (!external_source) 681 throw Xapian::InvalidArgumentError("The external_source parameter can not be NULL"); 731 Assert(external_source); 682 732 } 683 733 684 734 Xapian::Query::Internal::~Internal() … … 687 737 for (i = subqs.begin(); i != subqs.end(); i++) { 688 738 delete *i; 689 739 } 740 delete external_source; 690 741 } 691 742 692 743 Xapian::Query::Internal * -
xapian-core/api/omquery.cc
30 30 31 31 #include <xapian/error.h> 32 32 #include <xapian/enquire.h> 33 33 #include <xapian/postingsource.h> 34 34 #include <xapian/termiterator.h> 35 35 36 36 #include <vector> … … 161 161 op_ << ", " << valno << ", " << value); 162 162 } 163 163 164 Query::Query( PostingSource *external_source)165 : internal( new Query::Internal(external_source))164 Query::Query(const PostingSource & external_source) 165 : internal(NULL) 166 166 { 167 167 DEBUGAPICALL(void, "Xapian::Query::Query", external_source); 168 PostingSource * clone = external_source.clone(); 169 internal = new Query::Internal(clone); 168 170 } 169 171 170 172 // Copy constructor -
xapian-core/api/postingsource.cc
32 32 #include "xapian/queryparser.h" // For sortable_unserialise 33 33 34 34 #include "omassert.h" 35 #include "serialise.h" 36 #include "serialise-double.h" 35 37 #include "utils.h" 36 38 37 39 #include <cfloat> … … 68 70 } 69 71 70 72 std::string 73 PostingSource::name() const 74 { 75 return std::string(); 76 } 77 78 std::string 79 PostingSource::serialise() const 80 { 81 throw Xapian::InvalidOperationError("serialise() not supported for this PostingSource"); 82 } 83 84 PostingSource * 85 PostingSource::unserialise(const std::string &) const 86 { 87 throw Xapian::InvalidOperationError("unserialise() not supported for this PostingSource"); 88 } 89 90 std::string 71 91 PostingSource::get_description() const 72 92 { 73 93 return "Xapian::PostingSource subclass"; 74 94 } 75 95 76 96 77 ValueWeightPostingSource::ValueWeightPostingSource(Xapian::Database db_, 78 Xapian::valueno valno_) 79 : db(db_), 80 valno(valno_), 81 current_docid(0), 82 last_docid(db.get_lastdocid()), 83 current_value(0.0) 97 ValueWeightPostingSource::ValueWeightPostingSource(Xapian::valueno valno_) 98 : valno(valno_), 99 specified_max_value(DBL_MAX) 84 100 { 85 try {86 termfreq_max = db.get_value_freq(valno);87 termfreq_est = termfreq_max;88 termfreq_min = termfreq_max;89 max_value = sortable_unserialise(db.get_value_upper_bound(valno));90 } catch (const Xapian::UnimplementedError &) {91 termfreq_max = db.get_doccount();92 termfreq_est = termfreq_max / 2;93 termfreq_min = 0;94 max_value = DBL_MAX;95 }96 101 } 97 102 98 ValueWeightPostingSource::ValueWeightPostingSource(Xapian::Database db_, 99 Xapian::valueno valno_, 103 ValueWeightPostingSource::ValueWeightPostingSource(Xapian::valueno valno_, 100 104 double max_weight_) 101 : db(db_), 102 valno(valno_), 103 current_docid(0), 104 last_docid(db.get_lastdocid()), 105 current_value(0.0), 106 max_value(max_weight_) 105 : valno(valno_), 106 specified_max_value(max_weight_) 107 107 { 108 try {109 termfreq_max = db.get_value_freq(valno);110 termfreq_est = termfreq_max;111 termfreq_min = termfreq_max;112 max_value = std::min(max_value,113 sortable_unserialise(db.get_value_upper_bound(valno)));114 } catch (const Xapian::UnimplementedError &) {115 termfreq_max = db.get_doccount();116 termfreq_est = termfreq_max / 2;117 termfreq_min = 0;118 }119 108 } 120 109 121 110 Xapian::doccount … … 232 221 return current_docid; 233 222 } 234 223 224 ValueWeightPostingSource * 225 ValueWeightPostingSource::clone() const 226 { 227 return new ValueWeightPostingSource(valno, specified_max_value); 228 } 229 230 std::string 231 ValueWeightPostingSource::name() const 232 { 233 return std::string("ValueWeight"); 234 } 235 236 std::string 237 ValueWeightPostingSource::serialise() const 238 { 239 return encode_length(valno) + serialise_double(specified_max_value); 240 } 241 242 PostingSource * 243 ValueWeightPostingSource::unserialise(const std::string &s) const 244 { 245 const char * p = s.data(); 246 const char * end = p + s.size(); 247 248 Xapian::valueno new_valno = decode_length(&p, end, false); 249 double new_spec_max = unserialise_double(&p, end); 250 251 return new ValueWeightPostingSource(new_valno, new_spec_max); 252 } 253 235 254 void 236 ValueWeightPostingSource::reset( )255 ValueWeightPostingSource::reset(const Database & db_) 237 256 { 257 db = db_; 238 258 current_docid = 0; 259 current_value = 0.0; 260 last_docid = db.get_lastdocid(); 261 try { 262 termfreq_max = db.get_value_freq(valno); 263 termfreq_est = termfreq_max; 264 termfreq_min = termfreq_max; 265 max_value = std::min(specified_max_value, 266 sortable_unserialise(db.get_value_upper_bound(valno))); 267 } catch (const Xapian::UnimplementedError &) { 268 termfreq_max = db.get_doccount(); 269 termfreq_est = termfreq_max / 2; 270 termfreq_min = 0; 271 max_value = specified_max_value; 272 } 239 273 } 240 274 241 275 std::string -
xapian-bindings/python/pythontest2.py
913 913 xapian.PostingSource.__init__(self) 914 914 self.max = max 915 915 916 def reset(self ):916 def reset(self, db): 917 917 self.current = -1 918 918 919 919 def get_termfreq_min(self): return 0 … … 954 954 doc.add_value(1, xapian.sortable_serialise(vals[id])) 955 955 db.add_document(doc) 956 956 957 source = xapian.ValueWeightPostingSource( db,1)957 source = xapian.ValueWeightPostingSource(1) 958 958 query = xapian.Query(source) 959 959 # del source # Check that query keeps a reference to it. 960 960 -
xapian-bindings/python/generate-python-exceptions.in
43 43 get_docid 44 44 get_description 45 45 reset 46 name 47 serialise 46 48 ); 47 49 48 50 open FD, ">except.i" or die $!; -
xapian-bindings/xapian.i
194 194 195 195 #ifdef XAPIAN_SWIG_DIRECTORS 196 196 %feature("director") Xapian::PostingSource; 197 %ignore Xapian::PostingSource::clone; 198 %ignore Xapian::PostingSource::unserialise; 197 199 %include <xapian/postingsource.h> 198 200 #else 199 201 %ignore Xapian::Query(Xapian::PostingSource *);