From 1dd351d18223577c1ba83550f1b0dbeae0a9cdbb Mon Sep 17 00:00:00 2001 From: Kris Zyp Date: Wed, 7 Jul 2021 16:24:02 -0600 Subject: [PATCH] Fix for doing reverse range query, #69 --- src/cursor.cpp | 35 ++++++++++++++--------------------- test/index.test.js | 26 ++++++++++++++++++++++++++ 2 files changed, 40 insertions(+), 21 deletions(-) diff --git a/src/cursor.cpp b/src/cursor.cpp index 7534bcbf94..5b8de5a43c 100644 --- a/src/cursor.cpp +++ b/src/cursor.cpp @@ -389,7 +389,7 @@ int CursorWrap::returnEntry(int lastRC, MDB_val &key, MDB_val &data) { comparison = mdb_dcmp(tw->txn, dw->dbi, &endKey, &data); else comparison = mdb_cmp(tw->txn, dw->dbi, &endKey, &key); - if ((flags & 0x400) ? comparison >= 0 : (comparison <=0)) { + if ((flags & 0x400) ? comparison >= 0 : (comparison <= 0)) { return 0; } } @@ -438,34 +438,27 @@ uint32_t CursorWrap::doPosition(uint32_t offset, uint32_t keySize, uint64_t endK data.mv_size = endKeyAddress ? *((uint32_t*)startValueBuffer) : 0; data.mv_data = startValueBuffer + 1; rc = mdb_cursor_get(cursor, &key, &data, data.mv_size ? MDB_GET_BOTH_RANGE : MDB_SET_KEY); + if (rc == MDB_NOTFOUND) + return 0; if (flags & 0x1000 && !endKeyAddress) { - if (rc == MDB_NOTFOUND) - return 0; size_t count; rc = mdb_cursor_count(cursor, &count); if (rc) throwLmdbError(rc); return count; } - } else - rc = mdb_cursor_get(cursor, &key, &data, MDB_SET_RANGE); - if (flags & 0x400) {// reverse - MDB_val firstKey = key; // save it for comparison - if (rc) { // not found - if (flags & 0x800) {// only values for this key - // nothing to do, not found - } else if (true) {// MDB_SET_RANGE, not found, go to end + if (flags & 0x400) // reverse, get last dup + rc = mdb_cursor_get(cursor, &key, &data, MDB_LAST_DUP); + } else { + if (flags & 0x400) {// reverse + MDB_val firstKey = key; // save it for comparison + rc = mdb_cursor_get(cursor, &key, &data, MDB_SET_RANGE); + if (rc) rc = mdb_cursor_get(cursor, &key, &data, MDB_LAST); - } - } else { - if (flags & 0x800) {// only values for this key - // compare data - rc = mdb_cursor_get(cursor, &key, &data, MDB_LAST_DUP); - } else {// MDB_SET_RANGE - if (mdb_cmp(tw->txn, dw->dbi, &firstKey, &key)) - rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV); - } - } + if (mdb_cmp(tw->txn, dw->dbi, &firstKey, &key) && !rc) + rc = mdb_cursor_get(cursor, &key, &data, MDB_PREV); + } else // forward, just do a get by range + rc = mdb_cursor_get(cursor, &key, &data, MDB_SET_RANGE); } } while (offset-- > 0 && !rc) { diff --git a/test/index.test.js b/test/index.test.js index a17084ff31..78b6edb9aa 100644 --- a/test/index.test.js +++ b/test/index.test.js @@ -115,6 +115,32 @@ describe('lmdb-store', function() { value.should.equal(db.get(key)) } keys.should.deep.equal(returnedKeys) + + returnedKeys = [] + for (let { key, value } of db.getRange({ + reverse: true, + })) { + returnedKeys.unshift(key) + value.should.equal(db.get(key)) + } + keys.should.deep.equal(returnedKeys) + }); + it('reverse query range', async function() { + const keys = [ + [ 'Test', 100, 1 ], + [ 'Test', 10010, 2 ], + [ 'Test', 10010, 3 ], + ] + for (let key of keys) + await db.put(key, 3); + let returnedKeys = [] + for (let { key, value } of db.getRange({ + start: ['Test', null], + end: ['Test', null], + reverse: true + })) { + throw new Error('Should not return any results') + } }); it('string', async function() { await db.put('key1', 'Hello world!');