mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-04 17:34:14 +08:00
mdbx: add MDBX_EPSILON support for mdbx_estimate_range().
Change-Id: I2d89a9f20bfa16c8f35a4381709bc54f86f0ff67
This commit is contained in:
parent
b4002a8484
commit
e26b7501eb
1
mdbx.h
1
mdbx.h
@ -1737,6 +1737,7 @@ LIBMDBX_API int mdbx_estimate_move(const MDBX_cursor *cursor, MDBX_val *key,
|
|||||||
* [out] distance_items A pointer to store range estimation result.
|
* [out] distance_items A pointer to store range estimation result.
|
||||||
*
|
*
|
||||||
* Returns A non-zero error value on failure and 0 on success. */
|
* Returns A non-zero error value on failure and 0 on success. */
|
||||||
|
#define MDBX_EPSILON ((MDBX_val *)((ptrdiff_t)-1))
|
||||||
LIBMDBX_API int mdbx_estimate_range(MDBX_txn *txn, MDBX_dbi dbi,
|
LIBMDBX_API int mdbx_estimate_range(MDBX_txn *txn, MDBX_dbi dbi,
|
||||||
MDBX_val *begin_key, MDBX_val *begin_data,
|
MDBX_val *begin_key, MDBX_val *begin_data,
|
||||||
MDBX_val *end_key, MDBX_val *end_data,
|
MDBX_val *end_key, MDBX_val *end_data,
|
||||||
|
@ -1155,7 +1155,7 @@ typedef struct MDBX_node {
|
|||||||
#define LEAF2KEY(p, i, ks) ((char *)(p) + PAGEHDRSZ + ((i) * (ks)))
|
#define LEAF2KEY(p, i, ks) ((char *)(p) + PAGEHDRSZ + ((i) * (ks)))
|
||||||
|
|
||||||
/* Set the node's key into keyptr, if requested. */
|
/* Set the node's key into keyptr, if requested. */
|
||||||
#define MDBX_GET_KEY(node, keyptr) \
|
#define MDBX_GET_MAYNULL_KEYPTR(node, keyptr) \
|
||||||
do { \
|
do { \
|
||||||
if ((keyptr) != NULL) { \
|
if ((keyptr) != NULL) { \
|
||||||
(keyptr)->iov_len = NODEKSZ(node); \
|
(keyptr)->iov_len = NODEKSZ(node); \
|
||||||
@ -1164,7 +1164,7 @@ typedef struct MDBX_node {
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
/* Set the node's key into key. */
|
/* Set the node's key into key. */
|
||||||
#define MDBX_GET_KEY2(node, key) \
|
#define MDBX_GET_KEYVALUE(node, key) \
|
||||||
do { \
|
do { \
|
||||||
key.iov_len = NODEKSZ(node); \
|
key.iov_len = NODEKSZ(node); \
|
||||||
key.iov_base = NODEKEY(node); \
|
key.iov_base = NODEKEY(node); \
|
||||||
|
143
src/mdbx.c
143
src/mdbx.c
@ -5097,7 +5097,7 @@ static int __cold mdbx_read_header(MDBX_env *env, MDBX_meta *meta,
|
|||||||
/* LY: check mapsize limits */
|
/* LY: check mapsize limits */
|
||||||
const uint64_t mapsize_min =
|
const uint64_t mapsize_min =
|
||||||
page.mp_meta.mm_geo.lower * (uint64_t)page.mp_meta.mm_psize;
|
page.mp_meta.mm_geo.lower * (uint64_t)page.mp_meta.mm_psize;
|
||||||
STATIC_ASSERT(MAX_MAPSIZE < SSIZE_MAX - MAX_PAGESIZE);
|
STATIC_ASSERT(MAX_MAPSIZE < PTRDIFF_MAX - MAX_PAGESIZE);
|
||||||
STATIC_ASSERT(MIN_MAPSIZE < MAX_MAPSIZE);
|
STATIC_ASSERT(MIN_MAPSIZE < MAX_MAPSIZE);
|
||||||
if (mapsize_min < MIN_MAPSIZE || mapsize_min > MAX_MAPSIZE) {
|
if (mapsize_min < MIN_MAPSIZE || mapsize_min > MAX_MAPSIZE) {
|
||||||
mdbx_notice("meta[%u] has invalid min-mapsize (%" PRIu64 "), skip it",
|
mdbx_notice("meta[%u] has invalid min-mapsize (%" PRIu64 "), skip it",
|
||||||
@ -5511,7 +5511,7 @@ int __cold mdbx_env_get_maxkeysize(MDBX_env *env) {
|
|||||||
(((pagesize)-PAGEHDRSZ) / sizeof(pgno_t) - 1)
|
(((pagesize)-PAGEHDRSZ) / sizeof(pgno_t) - 1)
|
||||||
|
|
||||||
static void __cold mdbx_setup_pagesize(MDBX_env *env, const size_t pagesize) {
|
static void __cold mdbx_setup_pagesize(MDBX_env *env, const size_t pagesize) {
|
||||||
STATIC_ASSERT(SSIZE_MAX > MAX_MAPSIZE);
|
STATIC_ASSERT(PTRDIFF_MAX > MAX_MAPSIZE);
|
||||||
STATIC_ASSERT(MIN_PAGESIZE > sizeof(MDBX_page));
|
STATIC_ASSERT(MIN_PAGESIZE > sizeof(MDBX_page));
|
||||||
mdbx_ensure(env, mdbx_is_power2(pagesize));
|
mdbx_ensure(env, mdbx_is_power2(pagesize));
|
||||||
mdbx_ensure(env, pagesize >= MIN_PAGESIZE);
|
mdbx_ensure(env, pagesize >= MIN_PAGESIZE);
|
||||||
@ -6345,7 +6345,7 @@ static int __cold mdbx_setup_lck(MDBX_env *env, char *lck_pathname,
|
|||||||
} else {
|
} else {
|
||||||
if (env->me_flags & MDBX_EXCLUSIVE)
|
if (env->me_flags & MDBX_EXCLUSIVE)
|
||||||
return MDBX_BUSY;
|
return MDBX_BUSY;
|
||||||
if (size > SSIZE_MAX || (size & (env->me_os_psize - 1)) ||
|
if (size > PTRDIFF_MAX || (size & (env->me_os_psize - 1)) ||
|
||||||
size < env->me_os_psize) {
|
size < env->me_os_psize) {
|
||||||
mdbx_notice("lck-file has invalid size %" PRIu64 " bytes", size);
|
mdbx_notice("lck-file has invalid size %" PRIu64 " bytes", size);
|
||||||
return MDBX_PROBLEM;
|
return MDBX_PROBLEM;
|
||||||
@ -7547,7 +7547,7 @@ static int mdbx_cursor_next(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
|
|||||||
mdbx_cursor_next(&mc->mc_xcursor->mx_cursor, data, NULL, MDBX_NEXT);
|
mdbx_cursor_next(&mc->mc_xcursor->mx_cursor, data, NULL, MDBX_NEXT);
|
||||||
if (op != MDBX_NEXT || rc != MDBX_NOTFOUND) {
|
if (op != MDBX_NEXT || rc != MDBX_NOTFOUND) {
|
||||||
if (likely(rc == MDBX_SUCCESS))
|
if (likely(rc == MDBX_SUCCESS))
|
||||||
MDBX_GET_KEY(leaf, key);
|
MDBX_GET_MAYNULL_KEYPTR(leaf, key);
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7583,8 +7583,10 @@ skip:
|
|||||||
mp->mp_pgno, NUMKEYS(mp), mc->mc_ki[mc->mc_top]);
|
mp->mp_pgno, NUMKEYS(mp), mc->mc_ki[mc->mc_top]);
|
||||||
|
|
||||||
if (IS_LEAF2(mp)) {
|
if (IS_LEAF2(mp)) {
|
||||||
key->iov_len = mc->mc_db->md_xsize;
|
if (likely(key)) {
|
||||||
key->iov_base = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], key->iov_len);
|
key->iov_len = mc->mc_db->md_xsize;
|
||||||
|
key->iov_base = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], key->iov_len);
|
||||||
|
}
|
||||||
return MDBX_SUCCESS;
|
return MDBX_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7607,7 +7609,7 @@ skip:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MDBX_GET_KEY(leaf, key);
|
MDBX_GET_MAYNULL_KEYPTR(leaf, key);
|
||||||
return MDBX_SUCCESS;
|
return MDBX_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7638,7 +7640,7 @@ static int mdbx_cursor_prev(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
|
|||||||
mdbx_cursor_prev(&mc->mc_xcursor->mx_cursor, data, NULL, MDBX_PREV);
|
mdbx_cursor_prev(&mc->mc_xcursor->mx_cursor, data, NULL, MDBX_PREV);
|
||||||
if (op != MDBX_PREV || rc != MDBX_NOTFOUND) {
|
if (op != MDBX_PREV || rc != MDBX_NOTFOUND) {
|
||||||
if (likely(rc == MDBX_SUCCESS)) {
|
if (likely(rc == MDBX_SUCCESS)) {
|
||||||
MDBX_GET_KEY(leaf, key);
|
MDBX_GET_MAYNULL_KEYPTR(leaf, key);
|
||||||
mc->mc_flags &= ~C_EOF;
|
mc->mc_flags &= ~C_EOF;
|
||||||
}
|
}
|
||||||
return rc;
|
return rc;
|
||||||
@ -7673,8 +7675,10 @@ static int mdbx_cursor_prev(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
|
|||||||
mp->mp_pgno, NUMKEYS(mp), mc->mc_ki[mc->mc_top]);
|
mp->mp_pgno, NUMKEYS(mp), mc->mc_ki[mc->mc_top]);
|
||||||
|
|
||||||
if (IS_LEAF2(mp)) {
|
if (IS_LEAF2(mp)) {
|
||||||
key->iov_len = mc->mc_db->md_xsize;
|
if (likely(key)) {
|
||||||
key->iov_base = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], key->iov_len);
|
key->iov_len = mc->mc_db->md_xsize;
|
||||||
|
key->iov_base = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], key->iov_len);
|
||||||
|
}
|
||||||
return MDBX_SUCCESS;
|
return MDBX_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7697,7 +7701,7 @@ static int mdbx_cursor_prev(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MDBX_GET_KEY(leaf, key);
|
MDBX_GET_MAYNULL_KEYPTR(leaf, key);
|
||||||
return MDBX_SUCCESS;
|
return MDBX_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7734,7 +7738,7 @@ __hot static int mdbx_cursor_set(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
|
|||||||
nodekey.iov_base = LEAF2KEY(mp, 0, nodekey.iov_len);
|
nodekey.iov_base = LEAF2KEY(mp, 0, nodekey.iov_len);
|
||||||
} else {
|
} else {
|
||||||
leaf = NODEPTR(mp, 0);
|
leaf = NODEPTR(mp, 0);
|
||||||
MDBX_GET_KEY2(leaf, nodekey);
|
MDBX_GET_KEYVALUE(leaf, nodekey);
|
||||||
}
|
}
|
||||||
rc = mc->mc_dbx->md_cmp(key, &nodekey);
|
rc = mc->mc_dbx->md_cmp(key, &nodekey);
|
||||||
if (unlikely(rc == 0)) {
|
if (unlikely(rc == 0)) {
|
||||||
@ -7753,7 +7757,7 @@ __hot static int mdbx_cursor_set(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
|
|||||||
nodekey.iov_base = LEAF2KEY(mp, nkeys - 1, nodekey.iov_len);
|
nodekey.iov_base = LEAF2KEY(mp, nkeys - 1, nodekey.iov_len);
|
||||||
} else {
|
} else {
|
||||||
leaf = NODEPTR(mp, nkeys - 1);
|
leaf = NODEPTR(mp, nkeys - 1);
|
||||||
MDBX_GET_KEY2(leaf, nodekey);
|
MDBX_GET_KEYVALUE(leaf, nodekey);
|
||||||
}
|
}
|
||||||
rc = mc->mc_dbx->md_cmp(key, &nodekey);
|
rc = mc->mc_dbx->md_cmp(key, &nodekey);
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
@ -7772,7 +7776,7 @@ __hot static int mdbx_cursor_set(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
|
|||||||
LEAF2KEY(mp, mc->mc_ki[mc->mc_top], nodekey.iov_len);
|
LEAF2KEY(mp, mc->mc_ki[mc->mc_top], nodekey.iov_len);
|
||||||
} else {
|
} else {
|
||||||
leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]);
|
leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]);
|
||||||
MDBX_GET_KEY2(leaf, nodekey);
|
MDBX_GET_KEYVALUE(leaf, nodekey);
|
||||||
}
|
}
|
||||||
rc = mc->mc_dbx->md_cmp(key, &nodekey);
|
rc = mc->mc_dbx->md_cmp(key, &nodekey);
|
||||||
if (rc == 0) {
|
if (rc == 0) {
|
||||||
@ -7894,7 +7898,7 @@ set1:
|
|||||||
|
|
||||||
/* The key already matches in all other cases */
|
/* The key already matches in all other cases */
|
||||||
if (op == MDBX_SET_RANGE || op == MDBX_SET_KEY)
|
if (op == MDBX_SET_RANGE || op == MDBX_SET_KEY)
|
||||||
MDBX_GET_KEY(leaf, key);
|
MDBX_GET_MAYNULL_KEYPTR(leaf, key);
|
||||||
|
|
||||||
mdbx_debug("==> cursor placed on key [%s], data [%s]", DKEY(key), DVAL(data));
|
mdbx_debug("==> cursor placed on key [%s], data [%s]", DKEY(key), DVAL(data));
|
||||||
return rc;
|
return rc;
|
||||||
@ -7940,7 +7944,7 @@ static int mdbx_cursor_first(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data) {
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
MDBX_GET_KEY(leaf, key);
|
MDBX_GET_MAYNULL_KEYPTR(leaf, key);
|
||||||
return MDBX_SUCCESS;
|
return MDBX_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -7986,7 +7990,7 @@ static int mdbx_cursor_last(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
MDBX_GET_KEY(leaf, key);
|
MDBX_GET_MAYNULL_KEYPTR(leaf, key);
|
||||||
return MDBX_SUCCESS;
|
return MDBX_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -8024,7 +8028,7 @@ int mdbx_cursor_get(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
|
|||||||
key->iov_base = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], key->iov_len);
|
key->iov_base = LEAF2KEY(mp, mc->mc_ki[mc->mc_top], key->iov_len);
|
||||||
} else {
|
} else {
|
||||||
MDBX_node *leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]);
|
MDBX_node *leaf = NODEPTR(mp, mc->mc_ki[mc->mc_top]);
|
||||||
MDBX_GET_KEY(leaf, key);
|
MDBX_GET_MAYNULL_KEYPTR(leaf, key);
|
||||||
if (data) {
|
if (data) {
|
||||||
if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
|
if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
|
||||||
if (unlikely(!(mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED))) {
|
if (unlikely(!(mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED))) {
|
||||||
@ -8136,7 +8140,7 @@ int mdbx_cursor_get(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
|
|||||||
{
|
{
|
||||||
MDBX_node *leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
|
MDBX_node *leaf = NODEPTR(mc->mc_pg[mc->mc_top], mc->mc_ki[mc->mc_top]);
|
||||||
if (!F_ISSET(leaf->mn_flags, F_DUPDATA)) {
|
if (!F_ISSET(leaf->mn_flags, F_DUPDATA)) {
|
||||||
MDBX_GET_KEY(leaf, key);
|
MDBX_GET_MAYNULL_KEYPTR(leaf, key);
|
||||||
rc = mdbx_node_read(mc, leaf, data);
|
rc = mdbx_node_read(mc, leaf, data);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -8770,7 +8774,7 @@ new_sub:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
mdbx_cassert(mc, mc->mc_xcursor->mx_db.md_entries < SIZE_MAX);
|
mdbx_cassert(mc, mc->mc_xcursor->mx_db.md_entries < PTRDIFF_MAX);
|
||||||
ecount = (size_t)mc->mc_xcursor->mx_db.md_entries;
|
ecount = (size_t)mc->mc_xcursor->mx_db.md_entries;
|
||||||
if (flags & MDBX_APPENDDUP)
|
if (flags & MDBX_APPENDDUP)
|
||||||
xflags |= MDBX_APPEND;
|
xflags |= MDBX_APPEND;
|
||||||
@ -9615,8 +9619,8 @@ int mdbx_cursor_count(MDBX_cursor *mc, size_t *countp) {
|
|||||||
if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
|
if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
|
||||||
mdbx_cassert(mc, mc->mc_xcursor && (mc->mc_xcursor->mx_cursor.mc_flags &
|
mdbx_cassert(mc, mc->mc_xcursor && (mc->mc_xcursor->mx_cursor.mc_flags &
|
||||||
C_INITIALIZED));
|
C_INITIALIZED));
|
||||||
*countp = unlikely(mc->mc_xcursor->mx_db.md_entries > SIZE_MAX)
|
*countp = unlikely(mc->mc_xcursor->mx_db.md_entries > PTRDIFF_MAX)
|
||||||
? SIZE_MAX
|
? PTRDIFF_MAX
|
||||||
: (size_t)mc->mc_xcursor->mx_db.md_entries;
|
: (size_t)mc->mc_xcursor->mx_db.md_entries;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -13405,10 +13409,13 @@ int mdbx_estimate_range(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *begin_key,
|
|||||||
if (unlikely(!txn || !size_items))
|
if (unlikely(!txn || !size_items))
|
||||||
return MDBX_EINVAL;
|
return MDBX_EINVAL;
|
||||||
|
|
||||||
if (unlikely(!begin_key && begin_data))
|
if (unlikely(begin_data && (begin_key == NULL || begin_key == MDBX_EPSILON)))
|
||||||
return MDBX_EINVAL;
|
return MDBX_EINVAL;
|
||||||
|
|
||||||
if (unlikely(!end_key && end_data))
|
if (unlikely(end_data && (end_key == NULL || end_key == MDBX_EPSILON)))
|
||||||
|
return MDBX_EINVAL;
|
||||||
|
|
||||||
|
if (unlikely(begin_key == MDBX_EPSILON && end_key == MDBX_EPSILON))
|
||||||
return MDBX_EINVAL;
|
return MDBX_EINVAL;
|
||||||
|
|
||||||
if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
|
if (unlikely(txn->mt_signature != MDBX_MT_SIGNATURE))
|
||||||
@ -13442,35 +13449,65 @@ int mdbx_estimate_range(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *begin_key,
|
|||||||
}
|
}
|
||||||
MDBX_val stub = {0, 0};
|
MDBX_val stub = {0, 0};
|
||||||
rc = mdbx_cursor_first(&begin.outer, &stub, &stub);
|
rc = mdbx_cursor_first(&begin.outer, &stub, &stub);
|
||||||
} else if (end_key && !begin_data && !end_data &&
|
if (unlikely(end_key == MDBX_EPSILON)) {
|
||||||
(begin_key == end_key || mdbx_is_samedata(begin_key, end_key))) {
|
/* LY: FIRST..+epsilon case */
|
||||||
/* LY: single key case */
|
return (rc == MDBX_SUCCESS)
|
||||||
int exact = 0;
|
? mdbx_cursor_count(&begin.outer, (size_t *)size_items)
|
||||||
rc = mdbx_cursor_set(&begin.outer, begin_key, NULL, MDBX_SET, &exact);
|
: rc;
|
||||||
if (unlikely(rc != MDBX_SUCCESS)) {
|
|
||||||
*size_items = 0;
|
|
||||||
return (rc == MDBX_NOTFOUND) ? MDBX_SUCCESS : rc;
|
|
||||||
}
|
}
|
||||||
*size_items = 1;
|
|
||||||
if (begin.outer.mc_xcursor != NULL) {
|
|
||||||
MDBX_node *leaf = NODEPTR(begin.outer.mc_pg[begin.outer.mc_top],
|
|
||||||
begin.outer.mc_ki[begin.outer.mc_top]);
|
|
||||||
if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
|
|
||||||
/* LY: return the number of duplicates for given key */
|
|
||||||
mdbx_tassert(txn, begin.outer.mc_xcursor == &begin.inner &&
|
|
||||||
(begin.inner.mx_cursor.mc_flags & C_INITIALIZED));
|
|
||||||
*size_items =
|
|
||||||
(sizeof(*size_items) >= sizeof(begin.inner.mx_db.md_entries) ||
|
|
||||||
begin.inner.mx_db.md_entries <= SIZE_MAX)
|
|
||||||
? (size_t)begin.inner.mx_db.md_entries
|
|
||||||
: SIZE_MAX;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return MDBX_SUCCESS;
|
|
||||||
} else {
|
} else {
|
||||||
rc = mdbx_cursor_set(&begin.outer, begin_key, begin_data,
|
bool step_backward = false;
|
||||||
begin_data ? MDBX_GET_BOTH_RANGE : MDBX_SET_RANGE,
|
if (unlikely(begin_key == MDBX_EPSILON)) {
|
||||||
NULL);
|
if (end_key == NULL) {
|
||||||
|
/* LY: -epsilon..LAST case */
|
||||||
|
MDBX_val stub = {0, 0};
|
||||||
|
rc = mdbx_cursor_last(&begin.outer, &stub, &stub);
|
||||||
|
return (rc == MDBX_SUCCESS)
|
||||||
|
? mdbx_cursor_count(&begin.outer, (size_t *)size_items)
|
||||||
|
: rc;
|
||||||
|
}
|
||||||
|
/* LY: -epsilon..value case */
|
||||||
|
assert(end_key != MDBX_EPSILON);
|
||||||
|
begin_key = end_key;
|
||||||
|
step_backward = true;
|
||||||
|
} else if (unlikely(end_key == MDBX_EPSILON)) {
|
||||||
|
/* LY: value..+epsilon case */
|
||||||
|
assert(begin_key != MDBX_EPSILON);
|
||||||
|
end_key = begin_key;
|
||||||
|
}
|
||||||
|
if (end_key && !begin_data && !end_data &&
|
||||||
|
(begin_key == end_key || mdbx_is_samedata(begin_key, end_key))) {
|
||||||
|
/* LY: single key case */
|
||||||
|
int exact = 0;
|
||||||
|
rc = mdbx_cursor_set(&begin.outer, begin_key, NULL, MDBX_SET, &exact);
|
||||||
|
if (unlikely(step_backward) && rc == MDBX_SUCCESS)
|
||||||
|
rc = mdbx_cursor_prev(&begin.outer, NULL, NULL, MDBX_PREV_NODUP);
|
||||||
|
if (unlikely(rc != MDBX_SUCCESS)) {
|
||||||
|
*size_items = 0;
|
||||||
|
return (rc == MDBX_NOTFOUND) ? MDBX_SUCCESS : rc;
|
||||||
|
}
|
||||||
|
*size_items = 1;
|
||||||
|
if (begin.outer.mc_xcursor != NULL) {
|
||||||
|
MDBX_node *leaf = NODEPTR(begin.outer.mc_pg[begin.outer.mc_top],
|
||||||
|
begin.outer.mc_ki[begin.outer.mc_top]);
|
||||||
|
if (F_ISSET(leaf->mn_flags, F_DUPDATA)) {
|
||||||
|
/* LY: return the number of duplicates for given key */
|
||||||
|
mdbx_tassert(txn,
|
||||||
|
begin.outer.mc_xcursor == &begin.inner &&
|
||||||
|
(begin.inner.mx_cursor.mc_flags & C_INITIALIZED));
|
||||||
|
*size_items =
|
||||||
|
(sizeof(*size_items) >= sizeof(begin.inner.mx_db.md_entries) ||
|
||||||
|
begin.inner.mx_db.md_entries <= PTRDIFF_MAX)
|
||||||
|
? (size_t)begin.inner.mx_db.md_entries
|
||||||
|
: PTRDIFF_MAX;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return MDBX_SUCCESS;
|
||||||
|
} else {
|
||||||
|
rc = mdbx_cursor_set(&begin.outer, begin_key, begin_data,
|
||||||
|
begin_data ? MDBX_GET_BOTH_RANGE : MDBX_SET_RANGE,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (unlikely(rc != MDBX_SUCCESS)) {
|
if (unlikely(rc != MDBX_SUCCESS)) {
|
||||||
@ -13728,9 +13765,9 @@ int mdbx_get_ex(MDBX_txn *txn, MDBX_dbi dbi, MDBX_val *key, MDBX_val *data,
|
|||||||
(cx.inner.mx_cursor.mc_flags & C_INITIALIZED));
|
(cx.inner.mx_cursor.mc_flags & C_INITIALIZED));
|
||||||
*values_count =
|
*values_count =
|
||||||
(sizeof(*values_count) >= sizeof(cx.inner.mx_db.md_entries) ||
|
(sizeof(*values_count) >= sizeof(cx.inner.mx_db.md_entries) ||
|
||||||
cx.inner.mx_db.md_entries <= SIZE_MAX)
|
cx.inner.mx_db.md_entries <= PTRDIFF_MAX)
|
||||||
? (size_t)cx.inner.mx_db.md_entries
|
? (size_t)cx.inner.mx_db.md_entries
|
||||||
: SIZE_MAX;
|
: PTRDIFF_MAX;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user