mirror of
https://github.com/isar/libmdbx.git
synced 2025-01-31 11:18:21 +08:00
mdbx: обещанное "doubtless" API для позиционирования курсоров.
This commit is contained in:
parent
5cf6542fa0
commit
25015c54e1
25
mdbx.h
25
mdbx.h
@ -1778,7 +1778,7 @@ enum MDBX_cursor_op {
|
|||||||
* return both key and data, and the return code depends on whether a
|
* return both key and data, and the return code depends on whether a
|
||||||
* upper-bound was found.
|
* upper-bound was found.
|
||||||
*
|
*
|
||||||
* For non DUPSORT-ed collections this work the same to \ref MDBX_SET_RANGE,
|
* For non DUPSORT-ed collections this work like \ref MDBX_SET_RANGE,
|
||||||
* but returns \ref MDBX_SUCCESS if the greater key was found or
|
* but returns \ref MDBX_SUCCESS if the greater key was found or
|
||||||
* \ref MDBX_NOTFOUND otherwise.
|
* \ref MDBX_NOTFOUND otherwise.
|
||||||
*
|
*
|
||||||
@ -1786,7 +1786,28 @@ enum MDBX_cursor_op {
|
|||||||
* i.e. for a pairs/tuples of a key and an each data value of duplicates.
|
* i.e. for a pairs/tuples of a key and an each data value of duplicates.
|
||||||
* Returns \ref MDBX_SUCCESS if the greater pair was returned or
|
* Returns \ref MDBX_SUCCESS if the greater pair was returned or
|
||||||
* \ref MDBX_NOTFOUND otherwise. */
|
* \ref MDBX_NOTFOUND otherwise. */
|
||||||
MDBX_SET_UPPERBOUND
|
MDBX_SET_UPPERBOUND,
|
||||||
|
|
||||||
|
/* Doubtless cursor positioning at a specified key. */
|
||||||
|
MDBX_TO_KEY_LESSER_THAN,
|
||||||
|
MDBX_TO_KEY_LESSER_OR_EQUAL,
|
||||||
|
MDBX_TO_KEY_EQUAL,
|
||||||
|
MDBX_TO_KEY_GREATER_OR_EQUAL,
|
||||||
|
MDBX_TO_KEY_GREATER_THAN,
|
||||||
|
|
||||||
|
/* Doubtless cursor positioning at a specified key-value pair
|
||||||
|
* for dupsort/multi-value hives. */
|
||||||
|
MDBX_TO_EXACT_KEY_VALUE_LESSER_THAN,
|
||||||
|
MDBX_TO_EXACT_KEY_VALUE_LESSER_OR_EQUAL,
|
||||||
|
MDBX_TO_EXACT_KEY_VALUE_EQUAL,
|
||||||
|
MDBX_TO_EXACT_KEY_VALUE_GREATER_OR_EQUAL,
|
||||||
|
MDBX_TO_EXACT_KEY_VALUE_GREATER_THAN,
|
||||||
|
|
||||||
|
MDBX_TO_PAIR_LESSER_THAN,
|
||||||
|
MDBX_TO_PAIR_LESSER_OR_EQUAL,
|
||||||
|
MDBX_TO_PAIR_EQUAL,
|
||||||
|
MDBX_TO_PAIR_GREATER_OR_EQUAL,
|
||||||
|
MDBX_TO_PAIR_GREATER_THAN
|
||||||
};
|
};
|
||||||
#ifndef __cplusplus
|
#ifndef __cplusplus
|
||||||
/** \ingroup c_cursors */
|
/** \ingroup c_cursors */
|
||||||
|
256
mdbx.h++
256
mdbx.h++
@ -4391,9 +4391,33 @@ public:
|
|||||||
multi_find_pair = MDBX_GET_BOTH,
|
multi_find_pair = MDBX_GET_BOTH,
|
||||||
multi_exactkey_lowerboundvalue = MDBX_GET_BOTH_RANGE,
|
multi_exactkey_lowerboundvalue = MDBX_GET_BOTH_RANGE,
|
||||||
|
|
||||||
find_key = MDBX_SET,
|
seek_key = MDBX_SET,
|
||||||
key_exact = MDBX_SET_KEY,
|
key_exact = MDBX_SET_KEY,
|
||||||
key_lowerbound = MDBX_SET_RANGE
|
key_lowerbound = MDBX_SET_RANGE,
|
||||||
|
|
||||||
|
/* Doubtless cursor positioning at a specified key. */
|
||||||
|
key_lesser_than = MDBX_TO_KEY_LESSER_THAN,
|
||||||
|
key_lesser_or_equal = MDBX_TO_KEY_LESSER_OR_EQUAL,
|
||||||
|
key_equal = MDBX_TO_KEY_EQUAL,
|
||||||
|
key_greater_or_equal = MDBX_TO_KEY_GREATER_OR_EQUAL,
|
||||||
|
key_greater_than = MDBX_TO_KEY_GREATER_THAN,
|
||||||
|
|
||||||
|
/* Doubtless cursor positioning at a specified key-value pair
|
||||||
|
* for dupsort/multi-value hives. */
|
||||||
|
multi_exactkey_value_lesser_than = MDBX_TO_EXACT_KEY_VALUE_LESSER_THAN,
|
||||||
|
multi_exactkey_value_lesser_or_equal =
|
||||||
|
MDBX_TO_EXACT_KEY_VALUE_LESSER_OR_EQUAL,
|
||||||
|
multi_exactkey_value_equal = MDBX_TO_EXACT_KEY_VALUE_EQUAL,
|
||||||
|
multi_exactkey_value_greater_or_equal =
|
||||||
|
MDBX_TO_EXACT_KEY_VALUE_GREATER_OR_EQUAL,
|
||||||
|
multi_exactkey_value_greater = MDBX_TO_EXACT_KEY_VALUE_GREATER_THAN,
|
||||||
|
|
||||||
|
pair_lesser_than = MDBX_TO_PAIR_LESSER_THAN,
|
||||||
|
pair_lesser_or_equal = MDBX_TO_PAIR_LESSER_OR_EQUAL,
|
||||||
|
pair_equal = MDBX_TO_PAIR_EQUAL,
|
||||||
|
pair_exact = pair_equal,
|
||||||
|
pair_greater_or_equal = MDBX_TO_PAIR_GREATER_OR_EQUAL,
|
||||||
|
pair_greater_than = MDBX_TO_PAIR_GREATER_THAN,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct move_result : public pair_result {
|
struct move_result : public pair_result {
|
||||||
@ -4424,45 +4448,154 @@ public:
|
|||||||
};
|
};
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
/* fake const, i.e. for some move/get operations */
|
||||||
inline bool move(move_operation operation, MDBX_val *key, MDBX_val *value,
|
inline bool move(move_operation operation, MDBX_val *key, MDBX_val *value,
|
||||||
bool throw_notfound) const
|
bool throw_notfound) const;
|
||||||
/* fake const, i.e. for some operations */;
|
|
||||||
inline ptrdiff_t estimate(move_operation operation, MDBX_val *key,
|
inline ptrdiff_t estimate(move_operation operation, MDBX_val *key,
|
||||||
MDBX_val *value) const;
|
MDBX_val *value) const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
inline move_result move(move_operation operation, bool throw_notfound);
|
move_result move(move_operation operation, bool throw_notfound) {
|
||||||
inline move_result to_first(bool throw_notfound = true);
|
return move_result(*this, operation, throw_notfound);
|
||||||
inline move_result to_previous(bool throw_notfound = true);
|
}
|
||||||
inline move_result to_previous_last_multi(bool throw_notfound = true);
|
move_result move(move_operation operation, const slice &key,
|
||||||
inline move_result to_current_first_multi(bool throw_notfound = true);
|
bool throw_notfound) {
|
||||||
inline move_result to_current_prev_multi(bool throw_notfound = true);
|
return move_result(*this, operation, key, throw_notfound);
|
||||||
inline move_result current(bool throw_notfound = true) const;
|
}
|
||||||
inline move_result to_current_next_multi(bool throw_notfound = true);
|
move_result move(move_operation operation, const slice &key,
|
||||||
inline move_result to_current_last_multi(bool throw_notfound = true);
|
const slice &value, bool throw_notfound) {
|
||||||
inline move_result to_next_first_multi(bool throw_notfound = true);
|
return move_result(*this, operation, key, value, throw_notfound);
|
||||||
inline move_result to_next(bool throw_notfound = true);
|
}
|
||||||
inline move_result to_last(bool throw_notfound = true);
|
bool move(move_operation operation, slice &key, slice &value,
|
||||||
|
bool throw_notfound) {
|
||||||
|
return move(operation, &key, &value, throw_notfound);
|
||||||
|
}
|
||||||
|
|
||||||
inline move_result move(move_operation operation, const slice &key,
|
move_result to_first(bool throw_notfound = true) {
|
||||||
bool throw_notfound);
|
return move(first, throw_notfound);
|
||||||
|
}
|
||||||
|
move_result to_previous(bool throw_notfound = true) {
|
||||||
|
return move(previous, throw_notfound);
|
||||||
|
}
|
||||||
|
move_result to_previous_last_multi(bool throw_notfound = true) {
|
||||||
|
return move(multi_prevkey_lastvalue, throw_notfound);
|
||||||
|
}
|
||||||
|
move_result to_current_first_multi(bool throw_notfound = true) {
|
||||||
|
return move(multi_currentkey_firstvalue, throw_notfound);
|
||||||
|
}
|
||||||
|
move_result to_current_prev_multi(bool throw_notfound = true) {
|
||||||
|
return move(multi_currentkey_prevvalue, throw_notfound);
|
||||||
|
}
|
||||||
|
move_result current(bool throw_notfound = true) const {
|
||||||
|
return move_result(*this, throw_notfound);
|
||||||
|
}
|
||||||
|
move_result to_current_next_multi(bool throw_notfound = true) {
|
||||||
|
return move(multi_currentkey_nextvalue, throw_notfound);
|
||||||
|
}
|
||||||
|
move_result to_current_last_multi(bool throw_notfound = true) {
|
||||||
|
return move(multi_currentkey_lastvalue, throw_notfound);
|
||||||
|
}
|
||||||
|
move_result to_next_first_multi(bool throw_notfound = true) {
|
||||||
|
return move(multi_nextkey_firstvalue, throw_notfound);
|
||||||
|
}
|
||||||
|
move_result to_next(bool throw_notfound = true) {
|
||||||
|
return move(next, throw_notfound);
|
||||||
|
}
|
||||||
|
move_result to_last(bool throw_notfound = true) {
|
||||||
|
return move(last, throw_notfound);
|
||||||
|
}
|
||||||
|
|
||||||
|
move_result to_key_lesser_than(const slice &key, bool throw_notfound = true) {
|
||||||
|
return move(key_lesser_than, key, throw_notfound);
|
||||||
|
}
|
||||||
|
move_result to_key_lesser_or_equal(const slice &key,
|
||||||
|
bool throw_notfound = true) {
|
||||||
|
return move(key_lesser_or_equal, key, throw_notfound);
|
||||||
|
}
|
||||||
|
move_result to_key_equal(const slice &key, bool throw_notfound = true) {
|
||||||
|
return move(key_equal, key, throw_notfound);
|
||||||
|
}
|
||||||
|
move_result to_key_exact(const slice &key, bool throw_notfound = true) {
|
||||||
|
return move(key_exact, key, throw_notfound);
|
||||||
|
}
|
||||||
|
move_result to_key_greater_or_equal(const slice &key,
|
||||||
|
bool throw_notfound = true) {
|
||||||
|
return move(key_greater_or_equal, key, throw_notfound);
|
||||||
|
}
|
||||||
|
move_result to_key_greater_than(const slice &key,
|
||||||
|
bool throw_notfound = true) {
|
||||||
|
return move(key_greater_than, key, throw_notfound);
|
||||||
|
}
|
||||||
|
|
||||||
|
move_result to_exact_key_value_lesser_than(const slice &key,
|
||||||
|
const slice &value,
|
||||||
|
bool throw_notfound = true) {
|
||||||
|
return move(multi_exactkey_value_lesser_than, key, value, throw_notfound);
|
||||||
|
}
|
||||||
|
move_result to_exact_key_value_lesser_or_equal(const slice &key,
|
||||||
|
const slice &value,
|
||||||
|
bool throw_notfound = true) {
|
||||||
|
return move(multi_exactkey_value_lesser_or_equal, key, value,
|
||||||
|
throw_notfound);
|
||||||
|
}
|
||||||
|
move_result to_exact_key_value_equal(const slice &key, const slice &value,
|
||||||
|
bool throw_notfound = true) {
|
||||||
|
return move(multi_exactkey_value_equal, key, value, throw_notfound);
|
||||||
|
}
|
||||||
|
move_result to_exact_key_value_greater_or_equal(const slice &key,
|
||||||
|
const slice &value,
|
||||||
|
bool throw_notfound = true) {
|
||||||
|
return move(multi_exactkey_value_greater_or_equal, key, value,
|
||||||
|
throw_notfound);
|
||||||
|
}
|
||||||
|
move_result to_exact_key_value_greater_than(const slice &key,
|
||||||
|
const slice &value,
|
||||||
|
bool throw_notfound = true) {
|
||||||
|
return move(multi_exactkey_value_greater, key, value, throw_notfound);
|
||||||
|
}
|
||||||
|
|
||||||
|
move_result to_pair_lesser_than(const slice &key, const slice &value,
|
||||||
|
bool throw_notfound = true) {
|
||||||
|
return move(pair_lesser_than, key, value, throw_notfound);
|
||||||
|
}
|
||||||
|
move_result to_pair_lesser_or_equal(const slice &key, const slice &value,
|
||||||
|
bool throw_notfound = true) {
|
||||||
|
return move(pair_lesser_or_equal, key, value, throw_notfound);
|
||||||
|
}
|
||||||
|
move_result to_pair_equal(const slice &key, const slice &value,
|
||||||
|
bool throw_notfound = true) {
|
||||||
|
return move(pair_equal, key, value, throw_notfound);
|
||||||
|
}
|
||||||
|
move_result to_pair_exact(const slice &key, const slice &value,
|
||||||
|
bool throw_notfound = true) {
|
||||||
|
return move(pair_exact, key, value, throw_notfound);
|
||||||
|
}
|
||||||
|
move_result to_pair_greater_or_equal(const slice &key, const slice &value,
|
||||||
|
bool throw_notfound = true) {
|
||||||
|
return move(pair_greater_or_equal, key, value, throw_notfound);
|
||||||
|
}
|
||||||
|
move_result to_pair_greater_than(const slice &key, const slice &value,
|
||||||
|
bool throw_notfound = true) {
|
||||||
|
return move(pair_greater_than, key, value, throw_notfound);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline bool seek(const slice &key);
|
||||||
inline move_result find(const slice &key, bool throw_notfound = true);
|
inline move_result find(const slice &key, bool throw_notfound = true);
|
||||||
inline move_result lower_bound(const slice &key, bool throw_notfound = true);
|
inline move_result lower_bound(const slice &key, bool throw_notfound = false);
|
||||||
|
inline move_result upper_bound(const slice &key, bool throw_notfound = false);
|
||||||
|
|
||||||
|
/// \brief Return count of duplicates for current key.
|
||||||
|
inline size_t count_multivalue() const;
|
||||||
|
|
||||||
inline move_result move(move_operation operation, const slice &key,
|
|
||||||
const slice &value, bool throw_notfound);
|
|
||||||
inline move_result find_multivalue(const slice &key, const slice &value,
|
inline move_result find_multivalue(const slice &key, const slice &value,
|
||||||
bool throw_notfound = true);
|
bool throw_notfound = true);
|
||||||
inline move_result lower_bound_multivalue(const slice &key,
|
inline move_result lower_bound_multivalue(const slice &key,
|
||||||
const slice &value,
|
const slice &value,
|
||||||
bool throw_notfound = false);
|
bool throw_notfound = false);
|
||||||
|
inline move_result upper_bound_multivalue(const slice &key,
|
||||||
inline bool seek(const slice &key);
|
const slice &value,
|
||||||
inline bool move(move_operation operation, slice &key, slice &value,
|
bool throw_notfound = false);
|
||||||
bool throw_notfound);
|
|
||||||
|
|
||||||
/// \brief Return count of duplicates for current key.
|
|
||||||
inline size_t count_multivalue() const;
|
|
||||||
|
|
||||||
inline bool eof() const;
|
inline bool eof() const;
|
||||||
inline bool on_first() const;
|
inline bool on_first() const;
|
||||||
@ -6290,60 +6423,6 @@ inline ptrdiff_t estimate(const cursor &from, const cursor &to) {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
inline cursor::move_result cursor::move(move_operation operation,
|
|
||||||
bool throw_notfound) {
|
|
||||||
return move_result(*this, operation, throw_notfound);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline cursor::move_result cursor::to_first(bool throw_notfound) {
|
|
||||||
return move(first, throw_notfound);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline cursor::move_result cursor::to_previous(bool throw_notfound) {
|
|
||||||
return move(previous, throw_notfound);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline cursor::move_result cursor::to_previous_last_multi(bool throw_notfound) {
|
|
||||||
return move(multi_prevkey_lastvalue, throw_notfound);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline cursor::move_result cursor::to_current_first_multi(bool throw_notfound) {
|
|
||||||
return move(multi_currentkey_firstvalue, throw_notfound);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline cursor::move_result cursor::to_current_prev_multi(bool throw_notfound) {
|
|
||||||
return move(multi_currentkey_prevvalue, throw_notfound);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline cursor::move_result cursor::current(bool throw_notfound) const {
|
|
||||||
return move_result(*this, throw_notfound);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline cursor::move_result cursor::to_current_next_multi(bool throw_notfound) {
|
|
||||||
return move(multi_currentkey_nextvalue, throw_notfound);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline cursor::move_result cursor::to_current_last_multi(bool throw_notfound) {
|
|
||||||
return move(multi_currentkey_lastvalue, throw_notfound);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline cursor::move_result cursor::to_next_first_multi(bool throw_notfound) {
|
|
||||||
return move(multi_nextkey_firstvalue, throw_notfound);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline cursor::move_result cursor::to_next(bool throw_notfound) {
|
|
||||||
return move(next, throw_notfound);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline cursor::move_result cursor::to_last(bool throw_notfound) {
|
|
||||||
return move(last, throw_notfound);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline cursor::move_result cursor::move(move_operation operation,
|
|
||||||
const slice &key, bool throw_notfound) {
|
|
||||||
return move_result(*this, operation, key, throw_notfound);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline cursor::move_result cursor::find(const slice &key, bool throw_notfound) {
|
inline cursor::move_result cursor::find(const slice &key, bool throw_notfound) {
|
||||||
return move(key_exact, key, throw_notfound);
|
return move(key_exact, key, throw_notfound);
|
||||||
}
|
}
|
||||||
@ -6353,12 +6432,6 @@ inline cursor::move_result cursor::lower_bound(const slice &key,
|
|||||||
return move(key_lowerbound, key, throw_notfound);
|
return move(key_lowerbound, key, throw_notfound);
|
||||||
}
|
}
|
||||||
|
|
||||||
inline cursor::move_result cursor::move(move_operation operation,
|
|
||||||
const slice &key, const slice &value,
|
|
||||||
bool throw_notfound) {
|
|
||||||
return move_result(*this, operation, key, value, throw_notfound);
|
|
||||||
}
|
|
||||||
|
|
||||||
inline cursor::move_result cursor::find_multivalue(const slice &key,
|
inline cursor::move_result cursor::find_multivalue(const slice &key,
|
||||||
const slice &value,
|
const slice &value,
|
||||||
bool throw_notfound) {
|
bool throw_notfound) {
|
||||||
@ -6372,12 +6445,7 @@ inline cursor::move_result cursor::lower_bound_multivalue(const slice &key,
|
|||||||
}
|
}
|
||||||
|
|
||||||
inline bool cursor::seek(const slice &key) {
|
inline bool cursor::seek(const slice &key) {
|
||||||
return move(find_key, const_cast<slice *>(&key), nullptr, false);
|
return move(seek_key, const_cast<slice *>(&key), nullptr, false);
|
||||||
}
|
|
||||||
|
|
||||||
inline bool cursor::move(move_operation operation, slice &key, slice &value,
|
|
||||||
bool throw_notfound) {
|
|
||||||
return move(operation, &key, &value, throw_notfound);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
inline size_t cursor::count_multivalue() const {
|
inline size_t cursor::count_multivalue() const {
|
||||||
|
154
src/core.c
154
src/core.c
@ -16961,7 +16961,7 @@ search_node:;
|
|||||||
node = nsr.node;
|
node = nsr.node;
|
||||||
ret.exact = nsr.exact;
|
ret.exact = nsr.exact;
|
||||||
if (!ret.exact) {
|
if (!ret.exact) {
|
||||||
if (op != MDBX_SET_RANGE) {
|
if (op < MDBX_SET_RANGE) {
|
||||||
/* MDBX_SET specified and not an exact match. */
|
/* MDBX_SET specified and not an exact match. */
|
||||||
if (unlikely(mc->mc_ki[mc->mc_top] >=
|
if (unlikely(mc->mc_ki[mc->mc_top] >=
|
||||||
page_numkeys(mc->mc_pg[mc->mc_top])))
|
page_numkeys(mc->mc_pg[mc->mc_top])))
|
||||||
@ -17010,7 +17010,7 @@ got_node:
|
|||||||
ret.err = cursor_xinit1(mc, node, mp);
|
ret.err = cursor_xinit1(mc, node, mp);
|
||||||
if (unlikely(ret.err != MDBX_SUCCESS))
|
if (unlikely(ret.err != MDBX_SUCCESS))
|
||||||
return ret;
|
return ret;
|
||||||
if (op == MDBX_SET || op == MDBX_SET_KEY || op == MDBX_SET_RANGE) {
|
if (op >= MDBX_SET) {
|
||||||
MDBX_ANALYSIS_ASSUME(mc->mc_xcursor != nullptr);
|
MDBX_ANALYSIS_ASSUME(mc->mc_xcursor != nullptr);
|
||||||
ret.err = cursor_first(&mc->mc_xcursor->mx_cursor, data, NULL);
|
ret.err = cursor_first(&mc->mc_xcursor->mx_cursor, data, NULL);
|
||||||
if (unlikely(ret.err != MDBX_SUCCESS))
|
if (unlikely(ret.err != MDBX_SUCCESS))
|
||||||
@ -17026,7 +17026,7 @@ got_node:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (likely(data)) {
|
} else if (likely(data)) {
|
||||||
if (op == MDBX_GET_BOTH || op == MDBX_GET_BOTH_RANGE) {
|
if (op <= MDBX_GET_BOTH_RANGE) {
|
||||||
if (unlikely(data->iov_len < mc->mc_dbx->md_vlen_min ||
|
if (unlikely(data->iov_len < mc->mc_dbx->md_vlen_min ||
|
||||||
data->iov_len > mc->mc_dbx->md_vlen_max)) {
|
data->iov_len > mc->mc_dbx->md_vlen_max)) {
|
||||||
cASSERT(mc, !"Invalid data-size");
|
cASSERT(mc, !"Invalid data-size");
|
||||||
@ -17365,6 +17365,7 @@ static __hot int cursor_get(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
|
|||||||
case MDBX_LAST_DUP:
|
case MDBX_LAST_DUP:
|
||||||
mfunc = cursor_last;
|
mfunc = cursor_last;
|
||||||
goto move;
|
goto move;
|
||||||
|
|
||||||
case MDBX_SET_UPPERBOUND: /* mostly same as MDBX_SET_LOWERBOUND */
|
case MDBX_SET_UPPERBOUND: /* mostly same as MDBX_SET_LOWERBOUND */
|
||||||
case MDBX_SET_LOWERBOUND: {
|
case MDBX_SET_LOWERBOUND: {
|
||||||
if (unlikely(key == NULL || data == NULL))
|
if (unlikely(key == NULL || data == NULL))
|
||||||
@ -17408,6 +17409,153 @@ static __hot int cursor_get(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Doubtless API to positioning of the cursor at a specified key. */
|
||||||
|
case MDBX_TO_KEY_LESSER_THAN:
|
||||||
|
case MDBX_TO_KEY_LESSER_OR_EQUAL:
|
||||||
|
case MDBX_TO_KEY_EQUAL:
|
||||||
|
case MDBX_TO_KEY_GREATER_OR_EQUAL:
|
||||||
|
case MDBX_TO_KEY_GREATER_THAN: {
|
||||||
|
if (unlikely(key == NULL))
|
||||||
|
return MDBX_EINVAL;
|
||||||
|
struct cursor_set_result csr = cursor_set(mc, key, data, MDBX_SET_RANGE);
|
||||||
|
rc = csr.err;
|
||||||
|
if (csr.exact) {
|
||||||
|
cASSERT(mc, csr.err == MDBX_SUCCESS);
|
||||||
|
if (op == MDBX_TO_KEY_LESSER_THAN)
|
||||||
|
rc = cursor_prev(mc, key, data, MDBX_PREV_NODUP);
|
||||||
|
else if (op == MDBX_TO_KEY_GREATER_THAN)
|
||||||
|
rc = cursor_next(mc, key, data, MDBX_NEXT_NODUP);
|
||||||
|
} else if (op < MDBX_TO_KEY_EQUAL &&
|
||||||
|
(rc == MDBX_NOTFOUND || rc == MDBX_SUCCESS))
|
||||||
|
rc = cursor_prev(mc, key, data, MDBX_PREV_NODUP);
|
||||||
|
else if (op == MDBX_TO_KEY_EQUAL && rc == MDBX_SUCCESS)
|
||||||
|
rc = MDBX_NOTFOUND;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Doubtless API to positioning of the cursor at a specified key-value pair
|
||||||
|
* for multi-value hives. */
|
||||||
|
case MDBX_TO_EXACT_KEY_VALUE_LESSER_THAN:
|
||||||
|
case MDBX_TO_EXACT_KEY_VALUE_LESSER_OR_EQUAL:
|
||||||
|
case MDBX_TO_EXACT_KEY_VALUE_EQUAL:
|
||||||
|
case MDBX_TO_EXACT_KEY_VALUE_GREATER_OR_EQUAL:
|
||||||
|
case MDBX_TO_EXACT_KEY_VALUE_GREATER_THAN: {
|
||||||
|
if (unlikely(key == NULL || data == NULL))
|
||||||
|
return MDBX_EINVAL;
|
||||||
|
MDBX_val save_data = *data;
|
||||||
|
struct cursor_set_result csr = cursor_set(mc, key, data, MDBX_SET_KEY);
|
||||||
|
rc = csr.err;
|
||||||
|
if (rc == MDBX_SUCCESS) {
|
||||||
|
cASSERT(mc, csr.exact);
|
||||||
|
MDBX_cursor *const mx =
|
||||||
|
(mc->mc_xcursor &&
|
||||||
|
(mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED))
|
||||||
|
? &mc->mc_xcursor->mx_cursor
|
||||||
|
: nullptr;
|
||||||
|
if (mx) {
|
||||||
|
csr = cursor_set(mx, &save_data, NULL, MDBX_SET_RANGE);
|
||||||
|
rc = csr.err;
|
||||||
|
if (csr.exact) {
|
||||||
|
cASSERT(mc, csr.err == MDBX_SUCCESS);
|
||||||
|
if (op == MDBX_TO_EXACT_KEY_VALUE_LESSER_THAN)
|
||||||
|
rc = cursor_prev(mx, data, NULL, MDBX_PREV);
|
||||||
|
else if (op == MDBX_TO_EXACT_KEY_VALUE_GREATER_THAN)
|
||||||
|
rc = cursor_next(mx, data, NULL, MDBX_NEXT);
|
||||||
|
} else if (op < MDBX_TO_EXACT_KEY_VALUE_EQUAL &&
|
||||||
|
(rc == MDBX_NOTFOUND || rc == MDBX_SUCCESS))
|
||||||
|
rc = cursor_prev(mx, data, NULL, MDBX_PREV);
|
||||||
|
else if (op == MDBX_TO_EXACT_KEY_VALUE_EQUAL && rc == MDBX_SUCCESS)
|
||||||
|
rc = MDBX_NOTFOUND;
|
||||||
|
} else {
|
||||||
|
int cmp = mc->mc_dbx->md_dcmp(data, &save_data);
|
||||||
|
switch (op) {
|
||||||
|
default:
|
||||||
|
__unreachable();
|
||||||
|
case MDBX_TO_EXACT_KEY_VALUE_LESSER_THAN:
|
||||||
|
rc = (cmp < 0) ? MDBX_SUCCESS : MDBX_NOTFOUND;
|
||||||
|
break;
|
||||||
|
case MDBX_TO_EXACT_KEY_VALUE_LESSER_OR_EQUAL:
|
||||||
|
rc = (cmp <= 0) ? MDBX_SUCCESS : MDBX_NOTFOUND;
|
||||||
|
break;
|
||||||
|
case MDBX_TO_EXACT_KEY_VALUE_EQUAL:
|
||||||
|
rc = (cmp == 0) ? MDBX_SUCCESS : MDBX_NOTFOUND;
|
||||||
|
break;
|
||||||
|
case MDBX_TO_EXACT_KEY_VALUE_GREATER_OR_EQUAL:
|
||||||
|
rc = (cmp >= 0) ? MDBX_SUCCESS : MDBX_NOTFOUND;
|
||||||
|
break;
|
||||||
|
case MDBX_TO_EXACT_KEY_VALUE_GREATER_THAN:
|
||||||
|
rc = (cmp > 0) ? MDBX_SUCCESS : MDBX_NOTFOUND;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case MDBX_TO_PAIR_LESSER_THAN:
|
||||||
|
case MDBX_TO_PAIR_LESSER_OR_EQUAL:
|
||||||
|
case MDBX_TO_PAIR_EQUAL:
|
||||||
|
case MDBX_TO_PAIR_GREATER_OR_EQUAL:
|
||||||
|
case MDBX_TO_PAIR_GREATER_THAN: {
|
||||||
|
if (unlikely(key == NULL || data == NULL))
|
||||||
|
return MDBX_EINVAL;
|
||||||
|
MDBX_val save_data = *data;
|
||||||
|
struct cursor_set_result csr = cursor_set(mc, key, data, MDBX_SET_RANGE);
|
||||||
|
rc = csr.err;
|
||||||
|
if (csr.exact) {
|
||||||
|
cASSERT(mc, csr.err == MDBX_SUCCESS);
|
||||||
|
MDBX_cursor *const mx =
|
||||||
|
(mc->mc_xcursor &&
|
||||||
|
(mc->mc_xcursor->mx_cursor.mc_flags & C_INITIALIZED))
|
||||||
|
? &mc->mc_xcursor->mx_cursor
|
||||||
|
: nullptr;
|
||||||
|
if (mx) {
|
||||||
|
csr = cursor_set(mx, &save_data, NULL, MDBX_SET_RANGE);
|
||||||
|
rc = csr.err;
|
||||||
|
if (csr.exact) {
|
||||||
|
cASSERT(mc, csr.err == MDBX_SUCCESS);
|
||||||
|
if (op == MDBX_TO_PAIR_LESSER_THAN)
|
||||||
|
rc = cursor_prev(mc, key, data, MDBX_PREV);
|
||||||
|
else if (op == MDBX_TO_PAIR_GREATER_THAN)
|
||||||
|
rc = cursor_next(mc, key, data, MDBX_NEXT);
|
||||||
|
} else if (op < MDBX_TO_PAIR_EQUAL &&
|
||||||
|
(rc == MDBX_NOTFOUND || rc == MDBX_SUCCESS))
|
||||||
|
rc = cursor_prev(mc, key, data, MDBX_PREV);
|
||||||
|
else if (op == MDBX_TO_PAIR_EQUAL && rc == MDBX_SUCCESS)
|
||||||
|
rc = MDBX_NOTFOUND;
|
||||||
|
else if (op > MDBX_TO_PAIR_EQUAL && rc == MDBX_NOTFOUND)
|
||||||
|
rc = cursor_next(mc, key, data, MDBX_NEXT);
|
||||||
|
} else {
|
||||||
|
int cmp = mc->mc_dbx->md_dcmp(data, &save_data);
|
||||||
|
switch (op) {
|
||||||
|
default:
|
||||||
|
__unreachable();
|
||||||
|
case MDBX_TO_PAIR_LESSER_THAN:
|
||||||
|
rc = (cmp < 0) ? MDBX_SUCCESS : cursor_prev(mc, key, data, MDBX_PREV);
|
||||||
|
break;
|
||||||
|
case MDBX_TO_PAIR_LESSER_OR_EQUAL:
|
||||||
|
rc =
|
||||||
|
(cmp <= 0) ? MDBX_SUCCESS : cursor_prev(mc, key, data, MDBX_PREV);
|
||||||
|
break;
|
||||||
|
case MDBX_TO_PAIR_EQUAL:
|
||||||
|
rc = (cmp == 0) ? MDBX_SUCCESS : MDBX_NOTFOUND;
|
||||||
|
break;
|
||||||
|
case MDBX_TO_PAIR_GREATER_OR_EQUAL:
|
||||||
|
rc =
|
||||||
|
(cmp >= 0) ? MDBX_SUCCESS : cursor_next(mc, key, data, MDBX_NEXT);
|
||||||
|
break;
|
||||||
|
case MDBX_TO_PAIR_GREATER_THAN:
|
||||||
|
rc = (cmp > 0) ? MDBX_SUCCESS : cursor_next(mc, key, data, MDBX_NEXT);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (op < MDBX_TO_PAIR_EQUAL &&
|
||||||
|
(rc == MDBX_NOTFOUND || rc == MDBX_SUCCESS))
|
||||||
|
rc = cursor_prev(mc, key, data, MDBX_PREV_NODUP);
|
||||||
|
else if (op == MDBX_TO_PAIR_EQUAL && rc == MDBX_SUCCESS)
|
||||||
|
rc = MDBX_NOTFOUND;
|
||||||
|
break;
|
||||||
|
}
|
||||||
default:
|
default:
|
||||||
DEBUG("unhandled/unimplemented cursor operation %u", op);
|
DEBUG("unhandled/unimplemented cursor operation %u", op);
|
||||||
return MDBX_EINVAL;
|
return MDBX_EINVAL;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user