Issue 7875 - lmdb MDB_GET_BOTH unexpected success
Summary: lmdb MDB_GET_BOTH unexpected success
Status: VERIFIED FIXED
Alias: None
Product: LMDB
Classification: Unclassified
Component: liblmdb (show other issues)
Version: unspecified
Hardware: All All
: --- normal
Target Milestone: ---
Assignee: OpenLDAP project
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2014-06-11 08:34 UTC by mail@arnedebruijn.nl
Modified: 2020-03-12 15:54 UTC (History)
0 users

See Also:


Attachments

Note You need to log in before you can comment on or make changes to this issue.
Description Howard Chu 2014-06-11 02:29:29 UTC
changed notes
changed state Open to Test
moved from Incoming to Software Bugs
Comment 1 mail@arnedebruijn.nl 2014-06-11 08:34:39 UTC
Full_Name: Arne de Bruijn
Version: mdb.master a93810c
OS: Linux
URL: ftp://ftp.openldap.org/incoming/
Submission from: (NULL) (94.210.130.16)


MDB_GET_BOTH seems to unexpectedly return success if a data-value before the
first data-value for a key is requested.

The example program sets 1:b and 1:c and requests 1:a. It prints:
get_both: key=1 val=b

While I would expect:
get_both: err=MDB_NOTFOUND: No matching key/data pair found

(curiously it works when it only sets 1:b)

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include "lmdb.h"

void set_val(MDB_val *v, char *s) {
	v->mv_size = strlen(s);
	v->mv_data = s;
}

int main() {
	int rc;
	MDB_env *menv = NULL;
	MDB_dbi mdbi;
	MDB_txn *mtxn = NULL;
	MDB_val key, val;
	MDB_cursor *mc;
	
	if ((rc = mdb_env_create(&menv)))
		goto err;
	if ((rc = unlink("testdb")))
		goto err;
	if ((rc = mdb_env_open(menv, "testdb", MDB_NOSUBDIR, 0666)))
		goto err;
	if ((rc = mdb_txn_begin(menv, NULL, 0, &mtxn)))
		goto err;
	if ((rc = mdb_dbi_open(mtxn, NULL, MDB_DUPSORT | MDB_CREATE, &mdbi)))
		goto err;
	set_val(&key, "1");
	set_val(&val, "b");
	if ((rc = mdb_put(mtxn, mdbi, &key, &val, 0)))
		goto err;
	set_val(&key, "1");
	set_val(&val, "c");
	if ((rc = mdb_put(mtxn, mdbi, &key, &val, 0)))
		goto err;
	
	if ((rc = mdb_cursor_open(mtxn, mdbi, &mc)))
		goto err;
	
	set_val(&key, "1");
	set_val(&val, "a");
	rc = mdb_cursor_get(mc, &key, &val, MDB_GET_BOTH);
	if (rc)
		printf("get_both: err=%s\n", mdb_strerror(rc));
	else
		printf("get_both: key=%.*s val=%.*s\n", key.mv_size, (char *)key.mv_data,
val.mv_size, (char *)val.mv_data);

	mdb_cursor_close(mc);
	
	if ((rc = mdb_txn_commit(mtxn))) {
		mdb_dbi_close(menv, mdbi);
		goto err;
	}
	mdb_env_close(menv);
	return 0;
err:
	if (mtxn)
		mdb_txn_abort(mtxn);
	if (menv)
		mdb_env_close(menv);
	fprintf(stderr, "Error: %s\n", mdb_strerror(rc));
	return 1;
}
Comment 2 Howard Chu 2014-06-11 09:28:35 UTC
mail@arnedebruijn.nl wrote:
> Full_Name: Arne de Bruijn
> Version: mdb.master a93810c
> OS: Linux
> URL: ftp://ftp.openldap.org/incoming/
> Submission from: (NULL) (94.210.130.16)
>
>
> MDB_GET_BOTH seems to unexpectedly return success if a data-value before the
> first data-value for a key is requested.

Thanks for the report. This appears to have been broken due to commit 
18a07eb7c2dc33372455a6040984cd6b699b41a5 for ITS#7681. Fixed now in mdb.master
>
> The example program sets 1:b and 1:c and requests 1:a. It prints:
> get_both: key=1 val=b
>
> While I would expect:
> get_both: err=MDB_NOTFOUND: No matching key/data pair found
>
> (curiously it works when it only sets 1:b)
>
> #include <stdlib.h>
> #include <stdio.h>
> #include <string.h>
> #include <unistd.h>
> #include "lmdb.h"
>
> void set_val(MDB_val *v, char *s) {
> 	v->mv_size = strlen(s);
> 	v->mv_data = s;
> }
>
> int main() {
> 	int rc;
> 	MDB_env *menv = NULL;
> 	MDB_dbi mdbi;
> 	MDB_txn *mtxn = NULL;
> 	MDB_val key, val;
> 	MDB_cursor *mc;
> 	
> 	if ((rc = mdb_env_create(&menv)))
> 		goto err;
> 	if ((rc = unlink("testdb")))
> 		goto err;
> 	if ((rc = mdb_env_open(menv, "testdb", MDB_NOSUBDIR, 0666)))
> 		goto err;
> 	if ((rc = mdb_txn_begin(menv, NULL, 0, &mtxn)))
> 		goto err;
> 	if ((rc = mdb_dbi_open(mtxn, NULL, MDB_DUPSORT | MDB_CREATE, &mdbi)))
> 		goto err;
> 	set_val(&key, "1");
> 	set_val(&val, "b");
> 	if ((rc = mdb_put(mtxn, mdbi, &key, &val, 0)))
> 		goto err;
> 	set_val(&key, "1");
> 	set_val(&val, "c");
> 	if ((rc = mdb_put(mtxn, mdbi, &key, &val, 0)))
> 		goto err;
> 	
> 	if ((rc = mdb_cursor_open(mtxn, mdbi, &mc)))
> 		goto err;
> 	
> 	set_val(&key, "1");
> 	set_val(&val, "a");
> 	rc = mdb_cursor_get(mc, &key, &val, MDB_GET_BOTH);
> 	if (rc)
> 		printf("get_both: err=%s\n", mdb_strerror(rc));
> 	else
> 		printf("get_both: key=%.*s val=%.*s\n", key.mv_size, (char *)key.mv_data,
> val.mv_size, (char *)val.mv_data);
>
> 	mdb_cursor_close(mc);
> 	
> 	if ((rc = mdb_txn_commit(mtxn))) {
> 		mdb_dbi_close(menv, mdbi);
> 		goto err;
> 	}
> 	mdb_env_close(menv);
> 	return 0;
> err:
> 	if (mtxn)
> 		mdb_txn_abort(mtxn);
> 	if (menv)
> 		mdb_env_close(menv);
> 	fprintf(stderr, "Error: %s\n", mdb_strerror(rc));
> 	return 1;
> }
>
>


-- 
   -- Howard Chu
   CTO, Symas Corp.           http://www.symas.com
   Director, Highland Sun     http://highlandsun.com/hyc/
   Chief Architect, OpenLDAP  http://www.openldap.org/project/

Comment 3 OpenLDAP project 2014-08-01 21:04:51 UTC
Fixed in mdb.master
Comment 4 Quanah Gibson-Mount 2014-12-11 01:02:37 UTC
changed state Test to Closed