Ticket #52: revpostlist.patch

File revpostlist.patch, 22.4 kB (added by olly, 22 months ago)

Patch to implement this for quartz

  • backends/quartz/quartz_database.cc

    RCS file: /usr/data/cvs/xapian/xapian-core/backends/quartz/quartz_database.cc,v
    retrieving revision 1.145
    diff -p -u -r1.145 quartz_database.cc
     
    585585                              tname)); 
    586586} 
    587587 
     588LeafPostList * 
     589QuartzDatabase::do_open_post_list_rev(const string& tname) const 
     590{ 
     591    DEBUGCALL(DB, LeafPostList *, "QuartzDatabase::do_open_post_list_rev", 
     592              tname); 
     593    Assert(!tname.empty()); 
     594 
     595    Xapian::Internal::RefCntPtr<const QuartzDatabase> ptrtothis(this); 
     596    return(new QuartzRevPostList(ptrtothis, 
     597                                 &postlist_table, 
     598                                 &positionlist_table, 
     599                                 tname)); 
     600} 
     601 
    588602LeafTermList * 
    589603QuartzDatabase::open_term_list(Xapian::docid did) const 
    590604{ 
     
    11021116                              &database_ro.postlist_table, 
    11031117                              &database_ro.positionlist_table, 
    11041118                              tname)); 
     1119} 
     1120 
     1121LeafPostList * 
     1122QuartzWritableDatabase::do_open_post_list_rev(const string& tname) const 
     1123{ 
     1124    DEBUGCALL(DB, LeafPostList *, "QuartzWritableDatabase::do_open_post_list_rev", tname); 
     1125    Assert(!tname.empty()); 
     1126 
     1127    // Need to flush iff we've got buffered changes to this term's postlist. 
     1128    map<string, map<docid, pair<char, termcount> > >::const_iterator j; 
     1129    j = mod_plists.find(tname); 
     1130    if (j != mod_plists.end()) do_flush_const(); 
     1131 
     1132    Xapian::Internal::RefCntPtr<const QuartzWritableDatabase> ptrtothis(this); 
     1133    return(new QuartzRevPostList(ptrtothis, 
     1134                                 &database_ro.postlist_table, 
     1135                                 &database_ro.positionlist_table, 
     1136                                 tname)); 
    11051137} 
    11061138 
    11071139LeafTermList * 
  • backends/quartz/quartz_database.h

    RCS file: /usr/data/cvs/xapian/xapian-core/backends/quartz/quartz_database.h,v
    retrieving revision 1.78
    diff -p -u -r1.78 quartz_database.h
     
    210210        bool term_exists(const string & tname) const; 
    211211 
    212212        LeafPostList * do_open_post_list(const string & tname) const; 
     213        LeafPostList * do_open_post_list_rev(const string & tname) const; 
    213214        LeafTermList * open_term_list(Xapian::docid did) const; 
    214215        Xapian::Document::Internal * open_document(Xapian::docid did, bool lazy = false) const; 
    215216        PositionList * open_position_list(Xapian::docid did, 
     
    289290        bool term_exists(const string & tname) const; 
    290291 
    291292        LeafPostList * do_open_post_list(const string & tname) const; 
     293        LeafPostList * do_open_post_list_rev(const string & tname) const; 
    292294        LeafTermList * open_term_list(Xapian::docid did) const; 
    293295        Xapian::Document::Internal * open_document(Xapian::docid did, bool lazy = false) const; 
    294296        PositionList * open_position_list(Xapian::docid did, 
  • backends/quartz/quartz_postlist.cc

    RCS file: /usr/data/cvs/xapian/xapian-core/backends/quartz/quartz_postlist.cc,v
    retrieving revision 1.82
    diff -p -u -r1.82 quartz_postlist.cc
     
    604604    } 
    605605} 
    606606 
     607/*****************************************************************************/ 
     608 
    607609/** Read the number of entries in the posting list. 
    608610 *  This must only be called when *posptr is pointing to the start of 
    609611 *  the first chunk of the posting list. 
     
    913915{ 
    914916    return tname + ":" + om_tostring(number_of_entries); 
    915917} 
     918 
     919/*****************************************************************************/ 
     920 
     921QuartzRevPostList::QuartzRevPostList(Xapian::Internal::RefCntPtr<const Xapian::Database::Internal> this_db_, 
     922                               const Btree * table_, 
     923                               const Btree * positiontable_, 
     924                               const string & tname_) 
     925        : this_db(this_db_), 
     926          table(table_), 
     927          positiontable(positiontable_), 
     928          tname(tname_), 
     929          cursor(table->cursor_get()), 
     930          is_at_end(false), 
     931          have_started(false) 
     932{ 
     933    DEBUGCALL(DB, void, "QuartzRevPostList::QuartzRevPostList", 
     934              this_db_.get() << ", " << table_ << ", " << 
     935              positiontable_ << ", " << tname_); 
     936    string key; 
     937    make_key(tname, key); 
     938    int found = cursor->find_entry(key); 
     939    if (!found) { 
     940        number_of_entries = 0; 
     941        collection_freq = 0; 
     942        is_at_end = true; 
     943        pos = 0; 
     944        end = 0; 
     945        first_did_in_chunk = 0; 
     946        last_did_in_chunk = 0; 
     947        return; 
     948    } 
     949    cursor->read_tag(); 
     950    pos = cursor->current_tag.data(); 
     951    end = pos + cursor->current_tag.size(); 
     952 
     953    did = read_start_of_first_chunk(&pos, end, 
     954                              &number_of_entries, &collection_freq); 
     955    first_did_in_chunk = did; 
     956    last_did_in_chunk = read_start_of_chunk(&pos, end, first_did_in_chunk, 
     957                                            &is_last_chunk); 
     958    read_wdf_and_length(&pos, end, &wdf, &doclength); 
     959    if (!is_last_chunk) { 
     960        make_key(tname, (Xapian::docid)-1, key); 
     961        (void) cursor->find_entry(key); 
     962        const char * keypos = cursor->current_key.data(); 
     963        const char * keyend = keypos + cursor->current_key.size(); 
     964        if (!check_tname_in_key_lite(&keypos, keyend, tname)) { 
     965            throw Xapian::DatabaseCorruptError("Chunk for wrong term"); 
     966        } 
     967 
     968        if (!unpack_uint_preserving_sort(&keypos, keyend, &first_did_in_chunk)) { 
     969            report_read_error(keypos); 
     970        } 
     971 
     972        cursor->read_tag(); 
     973        pos = cursor->current_tag.data(); 
     974        end = pos + cursor->current_tag.size(); 
     975 
     976        last_did_in_chunk = read_start_of_chunk(&pos, end, first_did_in_chunk, 
     977                                                &is_last_chunk); 
     978        read_wdf_and_length(&pos, end, &wdf, &doclength); 
     979    } 
     980 
     981    buffer.clear(); 
     982    did = first_did_in_chunk; 
     983    while (pos != end) { 
     984        buffer.push_back(PLEntry(did, wdf, doclength)); 
     985        read_did_increase(&pos, end, &did); 
     986        read_wdf_and_length(&pos, end, &wdf, &doclength); 
     987        // Either not at last doc in chunk, or pos == end, but not both. 
     988        Assert(did <= last_did_in_chunk); 
     989        Assert(did < last_did_in_chunk || pos == end); 
     990        Assert(pos != end || did == last_did_in_chunk); 
     991    } 
     992} 
     993 
     994QuartzRevPostList::~QuartzRevPostList() 
     995{ 
     996    DEBUGCALL(DB, void, "QuartzRevPostList::~QuartzRevPostList", ""); 
     997} 
     998 
     999bool 
     1000QuartzRevPostList::next_in_chunk() 
     1001{ 
     1002    DEBUGCALL(DB, bool, "QuartzRevPostList::next_in_chunk", ""); 
     1003    if (buffer.empty()) RETURN(false); 
     1004 
     1005    did = buffer.back().did; 
     1006    wdf = buffer.back().wdf; 
     1007    doclength = buffer.back().doclength; 
     1008    buffer.pop_back(); 
     1009 
     1010    RETURN(true); 
     1011} 
     1012 
     1013void 
     1014QuartzRevPostList::next_chunk() 
     1015{ 
     1016    DEBUGCALL(DB, void, "QuartzRevPostList::next_chunk", ""); 
     1017    if (is_last_chunk) { 
     1018        is_at_end = true; 
     1019        return; 
     1020    } 
     1021     
     1022    cursor->prev(); 
     1023    const char * keypos = cursor->current_key.data(); 
     1024    const char * keyend = keypos + cursor->current_key.size(); 
     1025    if (!check_tname_in_key_lite(&keypos, keyend, tname)) { 
     1026        throw Xapian::DatabaseCorruptError("Chunk for wrong term"); 
     1027    } 
     1028 
     1029    if (keypos == keyend) { 
     1030        is_last_chunk = true; 
     1031        first_did_in_chunk = read_start_of_first_chunk(&pos, end, 
     1032                &number_of_entries, &collection_freq); 
     1033    } else { 
     1034        if (!unpack_uint_preserving_sort(&keypos, keyend, &first_did_in_chunk)) { 
     1035            report_read_error(keypos); 
     1036        } 
     1037 
     1038        cursor->read_tag(); 
     1039        pos = cursor->current_tag.data(); 
     1040        end = pos + cursor->current_tag.size(); 
     1041 
     1042        last_did_in_chunk = read_start_of_chunk(&pos, end, first_did_in_chunk, 
     1043                                                &is_last_chunk); 
     1044    } 
     1045    read_wdf_and_length(&pos, end, &wdf, &doclength); 
     1046    buffer.clear(); 
     1047    did = first_did_in_chunk; 
     1048    while (pos != end) { 
     1049        buffer.push_back(PLEntry(did, wdf, doclength)); 
     1050        read_did_increase(&pos, end, &did); 
     1051        read_wdf_and_length(&pos, end, &wdf, &doclength); 
     1052        // Either not at last doc in chunk, or pos == end, but not both. 
     1053        Assert(did <= last_did_in_chunk); 
     1054        Assert(did < last_did_in_chunk || pos == end); 
     1055        Assert(pos != end || did == last_did_in_chunk); 
     1056    } 
     1057} 
     1058 
     1059PositionList * 
     1060QuartzRevPostList::read_position_list() 
     1061{ 
     1062    DEBUGCALL(DB, PositionList *, "QuartzRevPostList::read_position_list", ""); 
     1063 
     1064    positionlist.read_data(positiontable, did, tname); 
     1065 
     1066    RETURN(&positionlist); 
     1067} 
     1068 
     1069PositionList * 
     1070QuartzRevPostList::open_position_list() const 
     1071{ 
     1072    DEBUGCALL(DB, PositionList *, "QuartzRevPostList::open_position_list", ""); 
     1073 
     1074    AutoPtr<QuartzPositionList> poslist(new QuartzPositionList()); 
     1075    poslist->read_data(positiontable, did, tname); 
     1076 
     1077    RETURN(poslist.release()); 
     1078} 
     1079 
     1080PostList * 
     1081QuartzRevPostList::next(Xapian::weight w_min) 
     1082{ 
     1083    DEBUGCALL(DB, PostList *, "QuartzRevPostList::next", w_min); 
     1084    (void)w_min; // no warning 
     1085 
     1086    if (!have_started) { 
     1087        have_started = true; 
     1088    } else { 
     1089        if (!next_in_chunk()) next_chunk(); 
     1090    } 
     1091 
     1092    DEBUGLINE(DB, string("Moved to ") << 
     1093              (is_at_end ? string("end.") : string("docid, wdf, doclength = ") + 
     1094               om_tostring(did) + ", " + om_tostring(wdf) + ", " + 
     1095               om_tostring(doclength))); 
     1096 
     1097    RETURN(NULL); 
     1098} 
     1099 
     1100bool 
     1101QuartzRevPostList::current_chunk_contains(Xapian::docid desired_did) 
     1102{ 
     1103    DEBUGCALL(DB, bool, "QuartzRevPostList::current_chunk_contains", desired_did); 
     1104    if (desired_did >= first_did_in_chunk && 
     1105        desired_did <= last_did_in_chunk) { 
     1106        RETURN(true); 
     1107    } 
     1108    RETURN(false); 
     1109} 
     1110 
     1111void 
     1112QuartzRevPostList::move_to_chunk_containing(Xapian::docid desired_did) 
     1113{ 
     1114    DEBUGCALL(DB, void, 
     1115              "QuartzRevPostList::move_to_chunk_containing", desired_did); 
     1116    string key; 
     1117    make_key(tname, desired_did, key); 
     1118    (void) cursor->find_entry(key); 
     1119    Assert(!cursor->after_end()); 
     1120 
     1121    const char * keypos = cursor->current_key.data(); 
     1122    const char * keyend = keypos + cursor->current_key.size(); 
     1123    // Check we're still in same postlist 
     1124    if (!check_tname_in_key_lite(&keypos, keyend, tname)) { 
     1125        // This should only happen if the postlist doesn't exist at all. 
     1126        is_at_end = true; 
     1127        is_last_chunk = true; 
     1128        return; 
     1129    } 
     1130    is_at_end = false; 
     1131 
     1132    cursor->read_tag(); 
     1133    pos = cursor->current_tag.data(); 
     1134    end = pos + cursor->current_tag.size(); 
     1135 
     1136    if (keypos == keyend) { 
     1137        // In first chunk 
     1138#ifdef XAPIAN_DEBUG 
     1139        Xapian::termcount old_number_of_entries = number_of_entries; 
     1140        Xapian::termcount old_collection_freq = collection_freq; 
     1141        first_did_in_chunk = read_start_of_first_chunk(&pos, end, &number_of_entries, 
     1142                                        &collection_freq); 
     1143        Assert(old_number_of_entries == number_of_entries); 
     1144        Assert(old_collection_freq == collection_freq); 
     1145#else 
     1146        first_did_in_chunk = read_start_of_first_chunk(&pos, end, 0, 0); 
     1147#endif 
     1148    } else { 
     1149        // In normal chunk 
     1150        if (!unpack_uint_preserving_sort(&keypos, keyend, &first_did_in_chunk)) { 
     1151            report_read_error(keypos); 
     1152        } 
     1153    } 
     1154 
     1155    last_did_in_chunk = read_start_of_chunk(&pos, end, first_did_in_chunk, 
     1156                                            &is_last_chunk); 
     1157    read_wdf_and_length(&pos, end, &wdf, &doclength); 
     1158    buffer.clear(); 
     1159    did = first_did_in_chunk; 
     1160    while (pos != end) { 
     1161        buffer.push_back(PLEntry(did, wdf, doclength)); 
     1162        read_did_increase(&pos, end, &did); 
     1163        read_wdf_and_length(&pos, end, &wdf, &doclength); 
     1164        // Either not at last doc in chunk, or pos == end, but not both. 
     1165        Assert(did <= last_did_in_chunk); 
     1166        Assert(did < last_did_in_chunk || pos == end); 
     1167        Assert(pos != end || did == last_did_in_chunk); 
     1168    } 
     1169} 
     1170 
     1171bool 
     1172QuartzRevPostList::move_forward_in_chunk_to_at_least(Xapian::docid desired_did) 
     1173{ 
     1174    DEBUGCALL(DB, bool, 
     1175              "QuartzRevPostList::move_forward_in_chunk_to_at_least", desired_did); 
     1176    if (desired_did > last_did_in_chunk) { 
     1177        pos = end; 
     1178        RETURN(false); 
     1179    } 
     1180    while (did < desired_did) { 
     1181        // FIXME: perhaps we don't need to decode the wdf and document length 
     1182        // for documents we're skipping past. 
     1183        bool at_end_of_chunk = !next_in_chunk(); 
     1184        if (at_end_of_chunk) RETURN(false); 
     1185    } 
     1186    RETURN(true); 
     1187} 
     1188 
     1189PostList * 
     1190QuartzRevPostList::skip_to(Xapian::docid desired_did, Xapian::weight w_min) 
     1191{ 
     1192    DEBUGCALL(DB, PostList *, 
     1193              "QuartzRevPostList::skip_to", desired_did << ", " << w_min); 
     1194    (void)w_min; // no warning 
     1195    // We've started now - if we hadn't already, we're already positioned 
     1196    // at start so there's no need to actually do anything. 
     1197    have_started = true; 
     1198 
     1199    // Don't skip back, and don't need to do anything if already there. 
     1200    if (desired_did <= did) RETURN(NULL); 
     1201 
     1202    // Move to correct chunk 
     1203    if (!current_chunk_contains(desired_did)) { 
     1204        move_to_chunk_containing(desired_did); 
     1205        // Might be at_end now - this is why we need the test before moving 
     1206        // forward in chunk. 
     1207    } 
     1208 
     1209    // Move to correct position in chunk 
     1210    if (!is_at_end) { 
     1211#ifdef XAPIAN_DEBUG 
     1212        bool have_document = 
     1213#else 
     1214                (void) 
     1215#endif 
     1216                move_forward_in_chunk_to_at_least(desired_did); 
     1217        Assert(have_document); 
     1218    } 
     1219 
     1220    DEBUGLINE(DB, string("Skipped to ") << 
     1221              (is_at_end ? string("end.") : string("docid, wdf, doclength = ") + 
     1222               om_tostring(did) + ", " + om_tostring(wdf) + ", " + 
     1223               om_tostring(doclength) + ".")); 
     1224 
     1225    RETURN(NULL); 
     1226} 
     1227 
     1228string 
     1229QuartzRevPostList::get_description() const 
     1230{ 
     1231    return tname + ":" + om_tostring(number_of_entries); 
     1232} 
     1233 
     1234/*****************************************************************************/ 
    9161235 
    9171236// Returns the last did to allow in this chunk. 
    9181237Xapian::docid 
  • backends/quartz/quartz_postlist.h

    RCS file: /usr/data/cvs/xapian/xapian-core/backends/quartz/quartz_postlist.h,v
    retrieving revision 1.33
    diff -p -u -r1.33 quartz_postlist.h
     
    247247                                           Xapian::termcount * collection_freq_ptr); 
    248248}; 
    249249 
     250/** A postlist in a quartz database. 
     251 */ 
     252class QuartzRevPostList : public LeafPostList { 
     253    private: 
     254        /** The database we are searching.  This pointer is held so that the 
     255         *  database doesn't get deleted before us. 
     256         */ 
     257        Xapian::Internal::RefCntPtr<const Xapian::Database::Internal> this_db; 
     258 
     259        /// The table containing the postlist. 
     260        const Btree * table; 
     261 
     262        /// The table containing positionlists. 
     263        const Btree * positiontable; 
     264 
     265        /// The termname for this postlist. 
     266        string tname; 
     267 
     268        /// Cursor pointing to current chunk of postlist. 
     269        AutoPtr<Bcursor> cursor; 
     270 
     271        /// True if this is the last chunk. 
     272        bool is_last_chunk; 
     273 
     274        /// The first document id in this chunk. 
     275        Xapian::docid first_did_in_chunk; 
     276 
     277        /// The last document id in this chunk. 
     278        Xapian::docid last_did_in_chunk; 
     279 
     280        /// Position of iteration through current chunk. 
     281        const char * pos; 
     282 
     283        /// Pointer to byte after end of current chunk. 
     284        const char * end; 
     285 
     286        /// Document id we're currently at. 
     287        Xapian::docid did; 
     288 
     289        /// The (absolute) length of the current document. 
     290        quartz_doclen_t doclength; 
     291 
     292        /// The wdf of the current document. 
     293        Xapian::termcount wdf; 
     294 
     295        /// Whether we've run off the end of the list yet. 
     296        bool is_at_end; 
     297 
     298        /// Whether we've started reading the list yet. 
     299        bool have_started; 
     300 
     301        /// The number of entries in the posting list. 
     302        Xapian::doccount number_of_entries; 
     303 
     304        /// The number of occurrences of the term in the posting list. 
     305        Xapian::termcount collection_freq; 
     306 
     307        /// The position list object for this posting list. 
     308        QuartzPositionList positionlist; 
     309 
     310        struct PLEntry { 
     311            Xapian::docid did; 
     312            Xapian::doccount wdf; 
     313            Xapian::termcount doclength; 
     314            PLEntry(Xapian::docid did_, Xapian::termcount wdf_, quartz_doclen_t doclength_) : did(did_), wdf(wdf_), doclength(doclength_) { } 
     315        }; 
     316 
     317        vector<PLEntry> buffer; 
     318 
     319        /// Copying is not allowed. 
     320        QuartzRevPostList(const QuartzRevPostList &); 
     321 
     322        /// Assignment is not allowed. 
     323        void operator=(const QuartzRevPostList &); 
     324 
     325        /** Move to the next item in the chunk, if possible. 
     326         *  If already at the end of the chunk, returns false. 
     327         */ 
     328        bool next_in_chunk(); 
     329 
     330        /** Move to the next chunk. 
     331         * 
     332         *  If there are no more chunks in this postlist, this will set 
     333         *  is_at_end to true. 
     334         */ 
     335        void next_chunk(); 
     336 
     337        /** Return true if the given document ID lies in the range covered 
     338         *  by the current chunk.  This does not say whether the document ID 
     339         *  is actually present.  It will return false if the document ID 
     340         *  is greater than the last document ID in the chunk, even if it is 
     341         *  less than the first document ID in the next chunk: it is possible 
     342         *  for no chunk to contain a particular document ID. 
     343         */ 
     344        bool current_chunk_contains(Xapian::docid desired_did); 
     345 
     346        /** Move to chunk containing the specified document ID. 
     347         * 
     348         *  This moves to the chunk whose starting document ID is 
     349         *  <= desired_did, but such that the next chunk's starting 
     350         *  document ID is > desired_did. 
     351         * 
     352         *  It is thus possible that current_chunk_contains(desired_did) 
     353         *  will return false after this call, since the document ID 
     354         *  might lie after the end of this chunk, but before the start 
     355         *  of the next chunk. 
     356         */ 
     357        void move_to_chunk_containing(Xapian::docid desired_did); 
     358 
     359        /** Scan forward in the current chunk for the specified document ID. 
     360         * 
     361         *  This is particularly efficient if the desired document ID is 
     362         *  greater than the last in the chunk - it then skips straight 
     363         *  to the end. 
     364         * 
     365         *  @return true if we moved to a valid document, 
     366         *          false if we reached the end of the chunk. 
     367         */ 
     368        bool move_forward_in_chunk_to_at_least(Xapian::docid desired_did); 
     369 
     370    public: 
     371        /// Default constructor. 
     372        QuartzRevPostList(Xapian::Internal::RefCntPtr<const Xapian::Database::Internal> this_db_, 
     373                       const Btree * table_, 
     374                       const Btree * positiontable_, 
     375                       const string & tname); 
     376 
     377        /// Destructor. 
     378        ~QuartzRevPostList(); 
     379 
     380        /** Returns number of docs indexed by this term. 
     381         * 
     382         *  This is the length of the postlist. 
     383         */ 
     384        Xapian::doccount get_termfreq() const { return number_of_entries; } 
     385 
     386        /** Returns the number of occurrences of the term in the database. 
     387         * 
     388         *  This is the sum of the wdfs in the postlist. 
     389         */ 
     390        Xapian::termcount get_collection_freq() const { return collection_freq; } 
     391 
     392        /// Returns the current docid. 
     393        Xapian::docid get_docid() const { Assert(have_started); return did; } 
     394 
     395        /// Returns the length of current document. 
     396        Xapian::doclength get_doclength() const { 
     397            Assert(have_started); 
     398            return static_cast<Xapian::doclength>(doclength); 
     399        } 
     400 
     401        /** Returns the Within Document Frequency of the term in the current 
     402         *  document. 
     403         */ 
     404        Xapian::termcount get_wdf() const { Assert(have_started); return wdf; } 
     405 
     406        /** Get the list of positions of the term in the current document. 
     407         */ 
     408        PositionList *read_position_list(); 
     409 
     410        /** Get the list of positions of the term in the current document. 
     411         */ 
     412        PositionList * open_position_list() const; 
     413 
     414        /// Move to the next document. 
     415        PostList * next(Xapian::weight w_min); 
     416 
     417        /// Skip to next document with docid >= docid. 
     418        PostList * skip_to(Xapian::docid desired_did, Xapian::weight w_min); 
     419 
     420        /// Return true if and only if we're off the end of the list. 
     421        bool at_end() const { return is_at_end; } 
     422 
     423        /// Get a description of the document. 
     424        std::string get_description() const; 
     425}; 
     426 
    250427#endif /* OM_HGUARD_QUARTZ_POSTLIST_H */ 
  • common/database.h

    RCS file: /usr/data/cvs/xapian/xapian-core/common/database.h,v
    retrieving revision 1.138
    diff -p -u -r1.138 database.h
     
    8989         *                use. 
    9090         */ 
    9191        virtual LeafPostList * do_open_post_list(const string & tname) const = 0; 
     92        virtual LeafPostList * do_open_post_list_rev(const string & tname) const = 0; 
    9293 
    9394    public: 
    9495        /** Destroy the database. 
     
    189190         *                This object must be deleted by the caller after 
    190191         *                use. 
    191192         */ 
    192         LeafPostList * open_post_list(const string & tname) const { 
     193        LeafPostList * open_post_list(const string & tname, bool rev = false) const { 
    193194            if (!term_exists(tname)) { 
    194195                DEBUGLINE(MATCH, tname + " is not in database."); 
    195196                // Term doesn't exist in this database.  However, we create 
     
    197198                // cleaner (term might exist in other databases). 
    198199                return new EmptyPostList(); 
    199200            } 
    200             return do_open_post_list(tname); 
     201            return rev ? do_open_post_list_rev(tname) : do_open_post_list(tname); 
    201202        } 
    202203 
    203204        /** Open a term list. 
  • common/multimatch.h

    RCS file: /usr/data/cvs/xapian/xapian-core/common/multimatch.h,v
    retrieving revision 1.75
    diff -p -u -r1.75 multimatch.h
     
    143143         *  and the maxweight now possible is smaller. 
    144144         */ 
    145145        void recalc_maxweight(); 
     146 
     147        /** Called by LocalSubMatch to find out the sort direction so it 
     148         * can decide whether to use reverse postlists or not. 
     149         */ 
     150        bool get_sort_forward() const { return sort_forward; } 
    146151}; 
    147152 
    148153#endif /* OM_HGUARD_MULTIMATCH_H */ 
  • matcher/localmatch.cc

    RCS file: /usr/data/cvs/xapian/xapian-core/matcher/localmatch.cc,v
    retrieving revision 1.119
    diff -p -u -r1.119 localmatch.cc
     
    410410            } 
    411411 
    412412            // MULTI 
    413             LeafPostList * pl = db->open_post_list(query->tname); 
     413            LeafPostList * pl; 
     414            pl = db->open_post_list(query->tname, !matcher->get_sort_forward()); 
    414415            pl->set_termweight(wt); 
    415416            RETURN(pl); 
    416417        } 
  • matcher/multimatch.cc

    RCS file: /usr/data/cvs/xapian/xapian-core/matcher/multimatch.cc,v
    retrieving revision 1.171
    diff -p -u -r1.171 multimatch.cc
     
    738738                if (!sort_bands && items.size() == max_msize) { 
    739739                    // We're done if this is a forward boolean match 
    740740                    // (bodgetastic, FIXME better if we can) 
    741                     if (max_weight == 0 && sort_forward) break; 
     741                    if (max_weight == 0) break; 
    742742                } 
    743743            } 
    744744        }