https://bugs.openldap.org/show_bug.cgi?id=8447

--- Comment #3 from [email protected] ---
I can reproduce this without using any cursors. I am using the lmdb++ header
for simplicity (https://github.com/hoytech/lmdbxx), but it also reproduces
using the plain C API. Full repro:

    #include <iostream>
    #include <stdlib.h>

    #include "lmdb++.h"

    #define PROJECT_NAME "mdb-dup-bug"

        static int compare_state_key(const MDB_val *a, const MDB_val *b)
        {
            auto get_skey = [](const MDB_val *v) {
                         std::string_view data(static_cast<const char
*>(v->mv_data), v->mv_size);
                         return data.substr(0,  data.find(','));
            };

            return get_skey(a).compare(get_skey(b));
        }

    int main(int argc, char **argv) {
        if(argc != 1) {
            std::cout << argv[0] <<  "takes no arguments.\n";
            return 1;
        }
        std::cout << "This is project " << PROJECT_NAME << ".\n";

        auto env = lmdb::env::create();
        env.set_max_dbs(10);

        char dirname[] = "/tmp/lmdb-bug.XXXXXX";
        env.open(mkdtemp(dirname));

        lmdb::dbi db;

        {
            auto txn = lmdb::txn::begin(env);
            db = lmdb::dbi::open(
              txn, std::string("dupsort").c_str(), MDB_CREATE | MDB_DUPSORT);
            lmdb::dbi_set_dupsort(txn, db, compare_state_key);

            db.put(txn, "abcd", "ab,cdef");
            db.put(txn, "abcd", "a,abc");

            txn.commit();
        }

        {
            auto txn = lmdb::txn::begin(env);

            std::string_view data;
            db.get(txn, "abcd", data);
            std::cout << "Data size: " << data.size() << " expected: 5, data:
'" << data << "', expected: 'a,abc'\n";

            txn.commit();
        }

        {
            auto txn = lmdb::txn::begin(env);
            db.put(txn, "abcd", "a,12");

            txn.commit();
        }

        {
            auto txn = lmdb::txn::begin(env);

            std::string_view data;
            db.get(txn, "abcd", data);
            std::cout << "Data size: " << data.size() << " expected: 4, data:
'" << data << "', expected: 'a,12'\n";

            txn.commit();
        }

        {
            auto txn = lmdb::txn::begin(env);
            db.put(txn, "abcd", "a,x");

            txn.commit();
        }

        {
            auto txn = lmdb::txn::begin(env);

            std::string_view data;
            db.get(txn, "abcd", data);
            std::cout << "Data size: " << data.size() << " expected: 3, data:
'" << data << "', expected: 'a,x'\n";

            txn.commit();
        }

        return 0;
    }


This prints the following output:

    This is project mdb-dup-bug.
    Data size: 5 expected: 5, data: 'a,abc', expected: 'a,abc'
    Data size: 5 expected: 4, data: 'a,12c', expected: 'a,12'
    Data size: 5 expected: 3, data: 'a,x2c', expected: 'a,x'

Commenting out the first put with the different data-key resolves the issue,
but certainly you would expect that replacing a duplicate replaces the size
too. Doing explicit delete before the put works around this issue.

-- 
You are receiving this mail because:
You are on the CC list for the issue.

Reply via email to