Ticket #198: multiple_values.patch

File multiple_values.patch, 13.1 KB (added by Richard Boulton, 15 years ago)

Patch from 2007 which I found lying around - no idea if it's of much use

  • xapian-core/tests/internaltest.cc

     
    3232
    3333#include <string>
    3434#include <list>
     35#include <map>
    3536
    3637using namespace std;
    3738
     
    527528    return true;
    528529}
    529530
     531// The C++ standard doesn't specify the ordering of inserts when a key with the
     532// existing value exists, but we want to be able to rely on this.  A future C++
     533// standard is likely to specify that inserts (without a hint) always happen at
     534// the upper_bound of the equal range for the key, and all known
     535// implementations obey this, but we'd better check that whatever
     536// implementation we're compiling with also obeys this.
     537//
     538// See: http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1780.html
     539static bool test_multimapinsert1()
     540{
     541    multimap<int, string> m;
     542    vector<string> v;
     543
     544    int i;
     545    for (i = 0; i != 100; ++i) {
     546        string val("val");
     547        val += om_tostring(i);
     548        v.push_back(val);
     549        m.insert(pair<int, string>(3, val));
     550    }
     551
     552    multimap<int, string>::const_iterator mi;
     553    for (i = 1, mi = m.begin(); i != 100; ++i, ++mi) {
     554        TEST_EQUAL(v[i], mi.second);
     555    }
     556
     557    return true;
     558}
     559
    530560// ##################################################################
    531561// # End of actual tests                                            #
    532562// ##################################################################
     
    543573    {"omstringstream1",         test_omstringstream1},
    544574    {"tostring1",               test_tostring1},
    545575    {"serialisedouble1",        test_serialisedouble1},
     576    {"multimapinsert1",         test_multimapinsert1},
    546577#ifdef XAPIAN_HAS_REMOTE_BACKEND
    547578    {"serialiselength1",        test_serialiselength1},
    548579    {"serialiselength2",        test_serialiselength2},
  • xapian-core/include/xapian/document.h

     
    6666
    6767        /** Get value by number.
    6868         *
    69          *  Returns an empty string if no value with the given number is present
    70          *  in the document.
     69         *  Returns an empty string if no value with the given number is
     70         *  present in the document.
    7171         *
     72         *  If multiple values are present with the given number, this will
     73         *  only return the first of them.  Use values_begin(valueno) to get an
     74         *  iterator over all such values.
     75         *
    7276         *  @param valueno The number of the value.
    7377         */
    7478        std::string get_value(Xapian::valueno valueno) const;
    7579
    76         /** Add a new value.  It will replace any existing value with the
     80        /** Get an iterator over all values with a given number.
     81         */
     82        ValueIterator values_begin(Xapian::valueno valueno) const;
     83
     84        /// End iterator corresponding to values_begin(valueno).
     85        ValueIterator values_end(Xapian::valueno valueno) const;
     86
     87        /** Add a new value.  It will replace any existing values with the
    7788         *  same number.
    7889         */
    7990        void add_value(Xapian::valueno valueno, const std::string &value);
    8091
    81         /// Remove any value with the given number.
     92        /** Append a value.  Unlike add_value(), existing values with the same
     93         *  number will not be replaced.
     94         */
     95        void append_value(Xapian::valueno valueno, const std::string &value);
     96
     97        /// Remove any values with the given number.
    8298        void remove_value(Xapian::valueno valueno);
    8399
    84100        /// Remove all values associated with the document.
     
    169185            return TermIterator(NULL);
    170186        }
    171187
    172         /// Count the values in this document.
     188        /** Count the values in this document.
     189         *
     190         *  This counts the number of non-empty values held in the document,
     191         *  which is the same as the number of entries returned by the
     192         *  values_begin() iterator.  This is not the same as the number of
     193         *  value slots which are used, because multiple values may be stored
     194         *  in a single slot.
     195         */
    173196        Xapian::termcount values_count() const;
    174197
    175198        /// Iterator for the values in this document.
  • xapian-core/include/xapian/valueiterator.h

     
    2727#define OM_HGUARD_OMVALUEITERATOR_H
    2828
    2929#include <iterator>
     30#include <map>
    3031#include <string>
    3132#include <xapian/types.h>
    3233#include <xapian/document.h>
     
    4243        friend bool operator==(const ValueIterator &a, const ValueIterator &b);
    4344        friend bool operator!=(const ValueIterator &a, const ValueIterator &b);
    4445
    45         ValueIterator(Xapian::valueno index_, const Document & doc_)
    46             : index(index_), doc(doc_) { }
     46        ValueIterator(multimap<Xapian::valueno, string>::const_iterator pos_,
     47                      const Document & doc_)
     48            : pos(pos_), doc(doc_) { }
    4749
    48         Xapian::valueno index;
     50        multimap<Xapian::valueno, string>::const_iterator pos;
    4951        Document doc;
    5052
    5153    public:
    5254        /** Create an uninitialised iterator; this cannot be used, but is
    5355         *  convenient syntactically.
    5456         */
    55         ValueIterator() : index(0), doc() { }
     57        ValueIterator() : pos(), doc() { }
    5658
    5759        ~ValueIterator() { }
    5860
    5961        /// Copying is allowed (and is cheap).
    6062        ValueIterator(const ValueIterator &other) {
    61             index = other.index;
     63            pos = other.pos;
    6264            doc = other.doc;
    6365        }
    6466
    6567        /// Assignment is allowed (and is cheap).
    6668        void operator=(const ValueIterator &other) {
    67             index = other.index;
     69            pos = other.pos;
    6870            doc = other.doc;
    6971        }
    7072
    7173        /// Advance the iterator.
    7274        ValueIterator & operator++() {
    73             ++index;
     75            ++pos;
    7476            return *this;
    7577        }
    7678
    7779        /// Advance the iterator (postfix variant).
    7880        ValueIterator operator++(int) {
    7981            ValueIterator tmp = *this;
    80             ++index;
     82            ++pos;
    8183            return tmp;
    8284        }
    8385
    8486        /// Get the value for the current position.
    85         const std::string & operator*() const;
     87        const std::string & operator*() const {
     88            return pos->second;
     89        }
    8690
    8791        /// Get the value for the current position.
    88         const std::string * operator->() const;
     92        const std::string * operator->() const {
     93            return &(pos->second);
     94        }
    8995
    9096        /// Get the number of the value at the current position
    91         Xapian::valueno get_valueno() const;
     97        Xapian::valueno get_valueno() const {
     98            return pos->first;
     99        }
    92100
    93101        /** Returns a string describing this object.
    94102         *  Introspection method.
     
    107115
    108116inline bool operator==(const ValueIterator &a, const ValueIterator &b)
    109117{
    110     return (a.index == b.index);
     118    return (a.pos == b.pos);
    111119}
    112120
    113121inline bool operator!=(const ValueIterator &a, const ValueIterator &b)
    114122{
    115     return (a.index != b.index);
     123    return (a.pos != b.pos);
    116124}
    117125
    118126}
  • xapian-core/common/document.h

     
    3737class Xapian::Document::Internal : public Xapian::Internal::RefCntBase {
    3838    friend class Xapian::ValueIterator;
    3939    public:
    40         /// Type to store values in.
    41         typedef map<Xapian::valueno, string> document_values;
     40        /** Type to store values in.
     41         *
     42         * Note that we rely on multimaps being stable (ie, preserving the
     43         * order of items with equal keys).  This is not currently guaranteed
     44         * by the standard, but an amendment to guarantee it was accepted for
     45         * the working paper in April 2006, and all known implementations
     46         * guarantee it.
     47         *
     48         * See http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#371
     49         *
     50         * We also rely on the insertion order being preserved for items added
     51         * without a hint.  This is also not currently guaranteed by the
     52         * standard, but an amendment to guarantee it was accepted for the
     53         * working paper in March 2007, and all known implementations guarantee
     54         * it.
     55         *
     56         * See http://www.open-std.org/jtc1/sc22/wg21/docs/lwg-defects.html#233
     57         * and
     58         * http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2005/n1780.html
     59         *
     60         * Note that we cannot rely on insertions using a "hint" iterator to
     61         * use the iterator, or to use it in a reliable way.  In particular,
     62         * some implementations will insert before the hint, and some will
     63         * insert after the hint, if the hint points to an existing item with
     64         * the specified key.  Amendment #233 will standardise this when
     65         * adopted, but existing implementations differ on how this is handled.
     66         */
     67        typedef multimap<Xapian::valueno, string> document_values;
    4268
    4369        /// Type to store terms in.
    4470        typedef map<string, OmDocumentTerm> document_terms;
     
    78104    private:
    79105        // Functions for backend to implement
    80106        virtual string do_get_value(Xapian::valueno /*valueno*/) const { return ""; }
    81         virtual map<Xapian::valueno, string> do_get_all_values() const {
    82             map<Xapian::valueno, string> none;
     107        virtual multimap<Xapian::valueno, string> do_get_all_values() const {
     108            multimap<Xapian::valueno, string> none;
    83109            return none;
    84110        }
    85111        virtual string do_get_data() const { return ""; }
     
    107133         *
    108134         *  Values are quickly accessible fields, for use during the match
    109135         *  operation.  Each document may have a set of values, each of which
    110          *  having a different valueid.  Duplicate values with the same valueid
    111          *  are not supported in a single document.
     136         *  has a valueid.  Multiple values with the same valueid may be
     137         *  contained in a single document.
    112138         *
    113          *  @return   A map of strings containing all the values.
     139         *  @return   A multimap of strings containing all the values.
    114140         */
    115         map<Xapian::valueno, string> get_all_values() const;
     141        multimap<Xapian::valueno, string> get_all_values() const;
    116142
    117143        Xapian::valueno values_count() const;
    118144        void add_value(Xapian::valueno, const string &);
     145        void append_value(Xapian::valueno, const string &);
    119146        void remove_value(Xapian::valueno);
    120147        void clear_values();
    121148        void add_posting(const string &, Xapian::termpos, Xapian::termcount);
  • xapian-core/api/omdocument.cc

     
    5454    RETURN(internal->get_value(value));
    5555}
    5656
     57ValueIterator
     58Document::values_begin(Xapian::valueno valueno) const
     59{
     60    DEBUGAPICALL(ValueIterator, "Document::values_begin", "");
     61    need_values();
     62    RETURN(ValueIterator(internal->document_values, *this));
     63}
     64
     65ValueIterator
     66Document::values_end(Xapian::valueno valueno) const
     67{
     68    DEBUGAPICALL(ValueIterator, "Document::values_end", "");
     69    RETURN(ValueIterator(FIXME, *this));
     70}
     71
     72
    5773string
    5874Document::get_data() const
    5975{
     
    98114}
    99115
    100116void
     117Document::append_value(Xapian::valueno valueno, const string &value)
     118{
     119    DEBUGAPICALL(void, "Document::add_value", valueno << ", " << value);
     120    internal->append_value(valueno, value);
     121}
     122
     123void
    101124Document::remove_value(Xapian::valueno valueno)
    102125{
    103126    DEBUGAPICALL(void, "Document::remove_value", valueno);
     
    306329void
    307330Xapian::Document::Internal::add_value(Xapian::valueno valueno, const string &value)
    308331{
     332    FIXME
    309333    need_values();
    310334    values[valueno] = value;
    311335    value_nos.clear();
    312336}
    313337
    314338void
     339Xapian::Document::Internal::append_value(Xapian::valueno valueno, const string &value)
     340{
     341    FIXME
     342    need_values();
     343    values[valueno] = value;
     344    value_nos.clear();
     345}
     346
     347void
    315348Xapian::Document::Internal::remove_value(Xapian::valueno valueno)
    316349{
    317350    need_values();
  • xapian-core/api/omvalueiterator.cc

     
    2828
    2929namespace Xapian {
    3030
    31 const string &
    32 ValueIterator::operator *() const
    33 {
    34     DEBUGAPICALL(const string &, "ValueIterator::operator*", "");
    35     Xapian::Internal::RefCntPtr<Xapian::Document::Internal> d(doc.internal);
    36     if (d->value_nos.empty()) {
    37         d->value_nos.reserve(d->values.size());
    38         map<Xapian::valueno, string>::const_iterator i;
    39         for (i = d->values.begin(); i != d->values.end(); ++i) {
    40             d->value_nos.push_back(i->first);
    41         }
    42     }
    43     Assert(index < d->value_nos.size());
    44     RETURN(d->values[d->value_nos[index]]);
    45 }
    46 
    47 const string *
    48 ValueIterator::operator->() const
    49 {
    50     DEBUGAPICALL(const string *, "ValueIterator::operator->", "");
    51     Xapian::Internal::RefCntPtr<Xapian::Document::Internal> d(doc.internal);
    52     if (d->value_nos.empty()) {
    53         d->value_nos.reserve(d->values.size());
    54         map<Xapian::valueno, string>::const_iterator i;
    55         for (i = d->values.begin(); i != d->values.end(); ++i) {
    56             d->value_nos.push_back(i->first);
    57         }
    58     }
    59     Assert(index < d->value_nos.size());
    60     RETURN(&(d->values[d->value_nos[index]]));
    61 }
    62 
    63 Xapian::valueno
    64 ValueIterator::get_valueno() const
    65 {
    66     DEBUGAPICALL(Xapian::valueno, "ValueIterator::get_valueno", "");
    67     Xapian::Internal::RefCntPtr<Xapian::Document::Internal> d(doc.internal);
    68     if (d->value_nos.empty()) {
    69         d->value_nos.reserve(d->values.size());
    70         map<Xapian::valueno, string>::const_iterator i;
    71         for (i = d->values.begin(); i != d->values.end(); ++i) {
    72             d->value_nos.push_back(i->first);
    73         }
    74     }
    75     Assert(index < d->value_nos.size());
    76     RETURN(d->value_nos[index]);
    77 }
    78 
    7931std::string
    8032ValueIterator::get_description() const
    8133{