Ticket #452: sortemptylast.patch
File sortemptylast.patch, 5.4 KB (added by , 15 years ago) |
---|
-
tests/api_sorting.cc
2 2 * @brief tests of MSet sorting 3 3 */ 4 4 /* Copyright (C) 2007,2008,2009 Olly Betts 5 * Copyright (C) 2010 Richard Boulton 5 6 * 6 7 * This program is free software; you can redistribute it and/or modify 7 8 * it under the terms of the GNU General Public License as published by … … 150 151 return true; 151 152 } 152 153 154 // Test sort functor with some empty values. 155 DEFINE_TESTCASE(sortfunctor3, backend && !remote && valuestats) { 156 Xapian::Database db(get_database("apitest_sortrel")); 157 Xapian::Enquire enquire(db); 158 enquire.set_query(Xapian::Query("woman")); 159 160 // Value 10 is set to 'a' for 1, 3, 4, 5, 8, 9, and not set otherwise. 161 { 162 // Test default sort order - missing values come first. 163 Xapian::MultiValueKeyMaker sorter; 164 sorter.add_value(10); 165 166 enquire.set_sort_by_key(&sorter, false); 167 Xapian::MSet mset = enquire.get_mset(0, 10); 168 mset_expect_order(mset, 2, 6, 7, 1, 3, 4, 5, 8, 9); 169 } 170 171 { 172 // Use a default value to put the missing values to the end. 173 Xapian::MultiValueKeyMaker sorter; 174 sorter.add_value(10, false, db.get_value_upper_bound(10) + '\xff'); 175 176 enquire.set_sort_by_key(&sorter, false); 177 Xapian::MSet mset = enquire.get_mset(0, 10); 178 mset_expect_order(mset, 1, 3, 4, 5, 8, 9, 2, 6, 7); 179 } 180 181 { 182 // Test using a default value and sorting in reverse order 183 Xapian::MultiValueKeyMaker sorter; 184 sorter.add_value(10, false, db.get_value_upper_bound(10) + '\xff'); 185 186 enquire.set_sort_by_key(&sorter, true); 187 Xapian::MSet mset = enquire.get_mset(0, 10); 188 mset_expect_order(mset, 2, 6, 7, 1, 3, 4, 5, 8, 9); 189 } 190 191 { 192 // Test using a default value and generating reverse order keys 193 Xapian::MultiValueKeyMaker sorter; 194 sorter.add_value(10, true, db.get_value_upper_bound(10) + '\xff'); 195 196 enquire.set_sort_by_key(&sorter, false); 197 Xapian::MSet mset = enquire.get_mset(0, 10); 198 mset_expect_order(mset, 2, 6, 7, 1, 3, 4, 5, 8, 9); 199 } 200 201 { 202 // Test using a default value, generating reverse order keys, and 203 // sorting in reverse order 204 Xapian::MultiValueKeyMaker sorter; 205 sorter.add_value(10, true, db.get_value_upper_bound(10) + '\xff'); 206 207 enquire.set_sort_by_key(&sorter, true); 208 Xapian::MSet mset = enquire.get_mset(0, 10); 209 mset_expect_order(mset, 1, 3, 4, 5, 8, 9, 2, 6, 7); 210 } 211 212 return true; 213 } 214 153 215 class NeverUseMeKeyMaker : public Xapian::KeyMaker { 154 216 public: 155 217 std::string operator() (const Xapian::Document &) const … … 218 280 doc.add_value(3, "xyz"); 219 281 TEST_EQUAL(sorter(doc), string("\0\0f\0\xffo\0\0\0\0xyz", 13)); 220 282 283 // An empty slot at the end, in reverse order, is terminated with \xff\xff 221 284 sorter.add_value(4, true); 222 285 TEST_EQUAL(sorter(doc), string("\0\0f\0\xffo\0\0\0\0xyz\0\0\xff\xff", 17)); 223 286 287 // An empty slot at the end, in ascending order, has no effect 288 sorter.add_value(0); 289 TEST_EQUAL(sorter(doc), string("\0\0f\0\xffo\0\0\0\0xyz\0\0\xff\xff", 17)); 290 291 // An empty slot at the end, with a default value 292 sorter.add_value(0, false, "hi"); 293 TEST_EQUAL(sorter(doc), string("\0\0f\0\xffo\0\0\0\0xyz\0\0\xff\xff\0\0hi", 294 21)); 295 296 // An empty slot at the end, with a default value, in reverse sort order 297 sorter.add_value(0, true, "hi"); 298 TEST_EQUAL(sorter(doc), string("\0\0f\0\xffo\0\0\0\0xyz\0\0\xff\xff\0\0hi" 299 "\0\0\x97\x96\xff\xff", 27)); 300 224 301 return true; 225 302 } 226 303 -
include/xapian/keymaker.h
61 61 * Other than this, it isn't useful to set @a reverse for collapsing. 62 62 */ 63 63 class XAPIAN_VISIBILITY_DEFAULT MultiValueKeyMaker : public KeyMaker { 64 std::vector<std::pair<Xapian::valueno, bool> > valnos; 64 struct KeySpec { 65 Xapian::valueno valno; 66 bool reverse; 67 std::string defvalue; 68 KeySpec(Xapian::valueno valno_, bool reverse_, 69 const std::string & defvalue_) 70 : valno(valno_), reverse(reverse_), defvalue(defvalue_) 71 {} 72 }; 73 std::vector<KeySpec> valnos; 65 74 66 75 public: 67 76 MultiValueKeyMaker() { } … … 73 82 74 83 virtual std::string operator()(const Xapian::Document & doc) const; 75 84 76 void add_value(Xapian::valueno valno, bool reverse = false) { 77 valnos.push_back(std::make_pair(valno, reverse)); 85 void add_value(Xapian::valueno valno, bool reverse = false, 86 const std::string & defvalue = std::string()) { 87 valnos.push_back(KeySpec(valno, reverse, defvalue)); 78 88 } 79 89 }; 80 90 -
api/keymaker.cc
38 38 { 39 39 string result; 40 40 41 vector< pair<Xapian::valueno, bool>>::const_iterator i = valnos.begin();41 vector<KeySpec>::const_iterator i = valnos.begin(); 42 42 // Don't crash if valnos is empty. 43 43 if (rare(i == valnos.end())) return result; 44 44 … … 48 48 // be adjusted. 49 49 // 50 50 // FIXME: allow Xapian::BAD_VALNO to mean "relevance?" 51 string v = doc.get_value(i-> first);52 bool reverse_sort = i-> second;51 string v = doc.get_value(i->valno); 52 bool reverse_sort = i->reverse; 53 53 54 if (v.empty()) { 55 v = i->defvalue; 56 } 57 54 58 if (reverse_sort || !v.empty()) 55 59 last_not_empty_forwards = result.size(); 56 60