Ticket #452: sortemptylast.patch

File sortemptylast.patch, 5.4 KB (added by Richard Boulton, 15 years ago)

Patch to add option to sort empty values to last (or other position based on default parameter)

  • tests/api_sorting.cc

     
    22 * @brief tests of MSet sorting
    33 */
    44/* Copyright (C) 2007,2008,2009 Olly Betts
     5 * Copyright (C) 2010 Richard Boulton
    56 *
    67 * This program is free software; you can redistribute it and/or modify
    78 * it under the terms of the GNU General Public License as published by
     
    150151    return true;
    151152}
    152153
     154// Test sort functor with some empty values.
     155DEFINE_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
    153215class NeverUseMeKeyMaker : public Xapian::KeyMaker {
    154216  public:
    155217    std::string operator() (const Xapian::Document &) const
     
    218280    doc.add_value(3, "xyz");
    219281    TEST_EQUAL(sorter(doc), string("\0\0f\0\xffo\0\0\0\0xyz", 13));
    220282
     283    // An empty slot at the end, in reverse order, is terminated with \xff\xff
    221284    sorter.add_value(4, true);
    222285    TEST_EQUAL(sorter(doc), string("\0\0f\0\xffo\0\0\0\0xyz\0\0\xff\xff", 17));
    223286
     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
    224301    return true;
    225302}
    226303
  • include/xapian/keymaker.h

     
    6161 *  Other than this, it isn't useful to set @a reverse for collapsing.
    6262 */
    6363class 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;
    6574
    6675  public:
    6776    MultiValueKeyMaker() { }
     
    7382
    7483    virtual std::string operator()(const Xapian::Document & doc) const;
    7584
    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));
    7888    }
    7989};
    8090
  • api/keymaker.cc

     
    3838{
    3939    string result;
    4040
    41     vector<pair<Xapian::valueno, bool> >::const_iterator i = valnos.begin();
     41    vector<KeySpec>::const_iterator i = valnos.begin();
    4242    // Don't crash if valnos is empty.
    4343    if (rare(i == valnos.end())) return result;
    4444
     
    4848        // be adjusted.
    4949        //
    5050        // 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;
    5353
     54        if (v.empty()) {
     55            v = i->defvalue;
     56        }
     57
    5458        if (reverse_sort || !v.empty())
    5559            last_not_empty_forwards = result.size();
    5660