mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-02 00:34:13 +08:00
mdbx: avoid upsertion (early exit) the same key-value data.
Resolve https://github.com/erthink/libmdbx/issues/99 Change-Id: I6aac66d6cb6818951e29bc8a3626c342d6137151
This commit is contained in:
parent
86dad2d727
commit
9428efd2ae
32
src/core.c
32
src/core.c
@ -3164,7 +3164,7 @@ static int __must_check_result mdbx_drop0(MDBX_cursor *mc, int subs);
|
||||
static int __must_check_result mdbx_fetch_sdb(MDBX_txn *txn, MDBX_dbi dbi);
|
||||
|
||||
static MDBX_cmp_func mdbx_cmp_memn, mdbx_cmp_memnr, mdbx_cmp_int_align4,
|
||||
mdbx_cmp_int_align2, mdbx_cmp_int_unaligned;
|
||||
mdbx_cmp_int_align2, mdbx_cmp_int_unaligned, mdbx_cmp_lenfast;
|
||||
|
||||
static const char *__mdbx_strerr(int errnum) {
|
||||
/* Table of descriptions for MDBX errors */
|
||||
@ -10088,6 +10088,7 @@ int __cold mdbx_env_open(MDBX_env *env, const char *pathname, unsigned flags,
|
||||
}
|
||||
env->me_dbxs[FREE_DBI].md_cmp =
|
||||
mdbx_cmp_int_align4; /* aligned MDBX_INTEGERKEY */
|
||||
env->me_dbxs[FREE_DBI].md_dcmp = mdbx_cmp_lenfast;
|
||||
|
||||
rc = mdbx_openfile(F_ISSET(flags, MDBX_RDONLY) ? MDBX_OPEN_DXB_READ
|
||||
: MDBX_OPEN_DXB_LAZY,
|
||||
@ -10481,6 +10482,12 @@ static int __hot mdbx_cmp_memnr(const MDBX_val *a, const MDBX_val *b) {
|
||||
return CMP2INT(a->iov_len, b->iov_len);
|
||||
}
|
||||
|
||||
/* Fast non-lexically comparator */
|
||||
static int __hot mdbx_cmp_lenfast(const MDBX_val *a, const MDBX_val *b) {
|
||||
int diff = CMP2INT(a->iov_len, b->iov_len);
|
||||
return likely(diff) ? diff : memcmp(a->iov_base, b->iov_base, a->iov_len);
|
||||
}
|
||||
|
||||
/* Search for key within a page, using binary search.
|
||||
* Returns the smallest entry larger or equal to the key.
|
||||
* If exactp is non-null, stores whether the found entry was an exact match
|
||||
@ -11909,12 +11916,10 @@ int mdbx_cursor_put(MDBX_cursor *mc, const MDBX_val *key, MDBX_val *data,
|
||||
rc = MDBX_NO_ROOT;
|
||||
} else if ((flags & MDBX_CURRENT) == 0) {
|
||||
int exact = 0;
|
||||
MDBX_val d2;
|
||||
if ((flags & MDBX_APPEND) != 0 && mc->mc_db->md_entries > 0) {
|
||||
MDBX_val k2;
|
||||
rc = mdbx_cursor_last(mc, &k2, &d2);
|
||||
rc = mdbx_cursor_last(mc, &dkey, &olddata);
|
||||
if (rc == 0) {
|
||||
rc = mc->mc_dbx->md_cmp(key, &k2);
|
||||
rc = mc->mc_dbx->md_cmp(key, &dkey);
|
||||
if (rc > 0) {
|
||||
rc = MDBX_NOTFOUND;
|
||||
mc->mc_ki[mc->mc_top]++;
|
||||
@ -11924,15 +11929,24 @@ int mdbx_cursor_put(MDBX_cursor *mc, const MDBX_val *key, MDBX_val *data,
|
||||
}
|
||||
}
|
||||
} else {
|
||||
rc = mdbx_cursor_set(mc, (MDBX_val *)key, &d2, MDBX_SET, &exact);
|
||||
rc = mdbx_cursor_set(mc, (MDBX_val *)key, &olddata, MDBX_SET, &exact);
|
||||
}
|
||||
if ((flags & MDBX_NOOVERWRITE) &&
|
||||
(rc == MDBX_SUCCESS || rc == MDBX_EKEYMISMATCH)) {
|
||||
mdbx_debug("duplicate key [%s]", DKEY(key));
|
||||
*data = d2;
|
||||
*data = olddata;
|
||||
return MDBX_KEYEXIST;
|
||||
}
|
||||
if (rc && unlikely(rc != MDBX_NOTFOUND))
|
||||
if (rc == MDBX_SUCCESS) {
|
||||
if (exact) {
|
||||
if (mc->mc_flags & C_SUB) {
|
||||
mdbx_assert(env, data->iov_len == 0 && olddata.iov_len == 0);
|
||||
return rc;
|
||||
}
|
||||
if (!(flags & MDBX_RESERVE) && mc->mc_dbx->md_dcmp(data, &olddata) == 0)
|
||||
return rc;
|
||||
}
|
||||
} else if (unlikely(rc != MDBX_NOTFOUND))
|
||||
return rc;
|
||||
}
|
||||
|
||||
@ -15919,7 +15933,7 @@ static MDBX_cmp_func *mdbx_default_keycmp(unsigned flags) {
|
||||
|
||||
static MDBX_cmp_func *mdbx_default_datacmp(unsigned flags) {
|
||||
return !(flags & MDBX_DUPSORT)
|
||||
? mdbx_cmp_memn
|
||||
? mdbx_cmp_lenfast
|
||||
: ((flags & MDBX_INTEGERDUP)
|
||||
? mdbx_cmp_int_unaligned
|
||||
: ((flags & MDBX_REVERSEDUP) ? mdbx_cmp_memnr
|
||||
|
Loading…
x
Reference in New Issue
Block a user