Ticket #473: postingiterator-from-query-wip.patch

File postingiterator-from-query-wip.patch, 5.5 KB (added by Olly Betts, 9 days ago)

Untested sketch of patch for PostingIterator from Query

  • xapian-core/api/database.cc

    commit bfcef51795c034d31fe3cd6595484f176c4d4b4a
    Author: Olly Betts <olly@survex.com>
    Date:   Mon Feb 23 13:21:22 2026 +1300
    
        WIP
    
    diff --git a/xapian-core/api/database.cc b/xapian-core/api/database.cc
    index 5e36a50dfc6d..1cc7d0de1671 100644
    a b Database::postlist_begin(string_view term) const  
    196196    return PostingIterator(new PostingIterator::Internal(pl, *this));
    197197}
    198198
     199PostingIterator
     200Database::postlist_begin(const Xapian::Query& query, bool prestart) const
     201{
     202    PostList* pl = internal->open_post_list(query, prestart);
     203    if (!pl) return PostingIterator();
     204    return PostingIterator(new PostingIterator::Internal(pl, *this));
     205}
     206
    199207TermIterator
    200208Database::termlist_begin(Xapian::docid did) const
    201209{
  • xapian-core/api/postingiteratorinternal.h

    diff --git a/xapian-core/api/postingiteratorinternal.h b/xapian-core/api/postingiteratorinternal.h
    index e85020d623e4..a8a44501be16 100644
    a b class PostingIterator::Internal {  
    6969    }
    7070
    7171    bool next() {
    72         (void)pl->next();
     72        auto prune = pl->next();
     73        if (rare(prune)) {
     74            delete pl;
     75            pl = prune;
     76        }
    7377        return !pl->at_end();
    7478    }
    7579
    7680    bool skip_to(Xapian::docid did) {
    77         (void)pl->skip_to(did);
     81        auto prune = pl->skip_to(did);
     82        if (rare(prune)) {
     83            delete pl;
     84            pl = prune;
     85        }
    7886        return !pl->at_end();
    7987    }
    8088
  • xapian-core/backends/databaseinternal.cc

    diff --git a/xapian-core/backends/databaseinternal.cc b/xapian-core/backends/databaseinternal.cc
    index 43bc9970f219..e5b608c0e0ff 100644
    a b  
    2525
    2626#include "api/termlist.h"
    2727#include "heap.h"
     28#include "matcher/localsubmatch.h"
     29#include "matcher/postlisttree.h"
    2830#include "omassert.h"
    2931#include "postlist.h"
    3032#include "slowvaluelist.h"
    Database::Internal::get_unique_terms_upper_bound() const  
    7779    return get_doclength_upper_bound();
    7880}
    7981
     82PostList*
     83Database::Internal::open_post_list(const Query& query, bool prestart) const
     84{
     85    // FIXME: query_length wtscheme
     86    Xapian::termcount query_length = query.get_length();
     87    // FIXME: Move to Enquire?
     88    // FIXME: Also need special implementations for multi and remote (or UnimplementedError)
     89    BoolWeight wtscheme;
     90    LocalSubMatch localsubmatch(this, query, query_length, wtscheme, 0);
     91    Xapian::Database db(const_cast<Database::Internal*>(this));
     92
     93    // FIXME: Need to arrange for these to be deleted.
     94    ValueStreamDocument* vsdoc = new ValueStreamDocument{db};
     95    PostListTree* pltree = new PostListTree(*vsdoc, db, wtscheme);
     96
     97    Xapian::termcount total_subqs_i = 0;
     98    auto plest = localsubmatch.get_postlist(pltree, &total_subqs_i);
     99    PostList* pl = plest.pl;
     100    if (!prestart) {
     101        auto prune = pl->next();
     102        if (rare(prune)) {
     103            delete pl;
     104            pl = prune;
     105        }
     106    }
     107    return pl;
     108}
     109
    80110// Discard any exceptions - we're called from the destructors of derived
    81111// classes so we can't safely throw.
    82112void
  • xapian-core/backends/databaseinternal.h

    diff --git a/xapian-core/backends/databaseinternal.h b/xapian-core/backends/databaseinternal.h
    index 67d95f502cd7..e36da3c4b9ca 100644
    a b class Database::Internal : public Xapian::Internal::intrusive_base {  
    218218    /** Return a PostList suitable for use in a PostingIterator. */
    219219    virtual PostList* open_post_list(std::string_view term) const = 0;
    220220
     221    /*virtual*/ PostList* open_post_list(const Query& query, bool prestart) const;
     222
    221223    /** Create a LeafPostList for use during a match.
    222224     *
    223225     *  @param term             The term to open a postlist for, or the empty
  • xapian-core/include/xapian/database.h

    diff --git a/xapian-core/include/xapian/database.h b/xapian-core/include/xapian/database.h
    index 2a15fe6b9283..3e2c4f626e3a 100644
    a b namespace Xapian {  
    4747
    4848class Compactor;
    4949class Document;
     50class Query;
    5051class WritableDatabase;
    5152
    5253/** An indexed database of documents.
    class XAPIAN_VISIBILITY_DEFAULT Database {  
    260261        return PostingIterator();
    261262    }
    262263
     264    PostingIterator postlist_begin(const std::string& term) const {
     265        return postlist_begin(std::string_view{term});
     266    }
     267
     268    /** End iterator corresponding to postlist_begin(). */
     269    PostingIterator postlist_end(const std::string&) const noexcept {
     270        return PostingIterator();
     271    }
     272
     273    /** Start iterating the postings of a Query object.
     274     *
     275     *  This returns the document ids matching a query.  The key difference
     276     *  compared to Enquire::get_mset() are that it can only return in
     277     *  ascending document id order.  However get_mset() needs O(n) memory
     278     *  so this can be useful if you want to process a lot of results.
     279     *
     280     *  @param query    The query to iterate the postings from.
     281     *  @param prestart If true the returned iterator needs incrementing to
     282     *                  be at the first result.  This is mainly useful as
     283     *                  you can call get_description() and see the results
     284     *                  of Xapian's query optimisation.  (Default: false)
     285     *
     286     *  @since Added in 1.5.0.
     287     */
     288    PostingIterator postlist_begin(const Xapian::Query& query,
     289                                   bool prestart = false) const;
     290
     291    /** End iterator corresponding to postlist_begin(). */
     292    PostingIterator postlist_end(const Xapian::Query&,
     293                                 bool = false) const noexcept {
     294        return PostingIterator();
     295    }
     296
    263297    /** Start iterating the terms in a document.
    264298     *
    265299     *  @param did      The document id to iterate terms from