Skip to content

closedOpen KeyRange not stopping before end key #169

@at055612

Description

@at055612

There seems to be a problem with the byte buffer comparator that occurs when the buffers are larger than the value they hold and it is comparing values of different lengths. The test below illustrates the problem. When comparing key301 to key30 it is getting the wrong result so is incorrectly carrying on past it. When run it finds 6 entries not 3.

I will raise a PR in a minute with the fix to the comparator.

package org.lmdbjava;

import org.junit.Assert;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TemporaryFolder;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.List;

public class ClosedOpenTest {

    @Rule
    public final TemporaryFolder tmp = new TemporaryFolder();

    @Test
    public void testClosedOpen() throws IOException {

        final File path = tmp.newFile();

        final Env<ByteBuffer> env = Env.create()
                .setMapSize(1024 * 100)
                .setMaxReaders(1)
                .setMaxDbs(1)
                .open(path, TestUtils.POSIX_MODE, EnvFlags.MDB_NOSUBDIR);
        final Dbi<ByteBuffer> db = env.openDbi(TestUtils.DB_1, DbiFlags.MDB_CREATE);

        try (Txn<ByteBuffer> txn = env.txnWrite()) {
            final Cursor<ByteBuffer> c = db.openCursor(txn);
            c.put(bb("key101"), bb("val101"));
            c.put(bb("key102"), bb("val102"));
            c.put(bb("key103"), bb("val103"));
            c.put(bb("key201"), bb("val201"));
            c.put(bb("key202"), bb("val202"));
            c.put(bb("key203"), bb("val203"));
            c.put(bb("key301"), bb("val301"));
            c.put(bb("key302"), bb("val302"));
            c.put(bb("key303"), bb("val303"));
            txn.commit();
        }

        // Should find keys 201, 202 and 203 only
        final KeyRange<ByteBuffer> range = KeyRange.closedOpen(
                bb("key20"),
                bb("key30"));

        final List<String> keysFound = new ArrayList<>();
        try (final Txn<ByteBuffer> txn = env.txnRead();
            final CursorIterable<ByteBuffer> c = db.iterate(txn, range)) {

            for (final CursorIterable.KeyVal<ByteBuffer> kv : c) {
                final String key = StandardCharsets.UTF_8.decode(kv.key()).toString();
                System.out.println(key);
                keysFound.add(key);
            }
        }

        Assert.assertEquals(3, keysFound.size());

        env.close();
    }

    private static ByteBuffer bb(final String value) {
        // Buffer larger than the value
        final ByteBuffer bb = ByteBuffer.allocateDirect(10);
        bb.put(value.getBytes(StandardCharsets.UTF_8));
        bb.flip();
        return bb;
    }
}

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions