mdbx: add MDBX_SET_UPPERBOUND for cursors.

Resolves https://github.com/erthink/libmdbx/issues/250.
This commit is contained in:
Leonid Yuriev 2021-12-13 03:40:12 +03:00
parent bee5df20fd
commit 4e44dc69f9
2 changed files with 32 additions and 7 deletions

25
mdbx.h
View File

@ -1572,18 +1572,33 @@ enum MDBX_cursor_op {
* a page of duplicate data items. */ * a page of duplicate data items. */
MDBX_PREV_MULTIPLE, MDBX_PREV_MULTIPLE,
/** Position at first key-value pair greater than or equal to specified, /** Positions cursor at first key-value pair greater than or equal to
* return both key and data, and the return code depends on a exact match. * specified, return both key and data, and the return code depends on whether
* a exact match.
* *
* For non DUPSORT-ed collections this work the same to \ref MDBX_SET_RANGE, * For non DUPSORT-ed collections this work the same to \ref MDBX_SET_RANGE,
* but returns \ref MDBX_SUCCESS if key found exactly and * but returns \ref MDBX_SUCCESS if key found exactly or
* \ref MDBX_RESULT_TRUE if greater key was found. * \ref MDBX_RESULT_TRUE if greater key was found.
* *
* For DUPSORT-ed a data value is taken into account for duplicates, * For DUPSORT-ed a data value is taken into account for duplicates,
* 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 key-value pair found exactly and * Returns \ref MDBX_SUCCESS if key-value pair found exactly or
* \ref MDBX_RESULT_TRUE if the next pair was returned. */ * \ref MDBX_RESULT_TRUE if the next pair was returned. */
MDBX_SET_LOWERBOUND MDBX_SET_LOWERBOUND,
/** Positions cursor at first key-value pair greater than specified,
* return both key and data, and the return code depends on whether a
* upper-bound was found.
*
* For non DUPSORT-ed collections this work the same to \ref MDBX_SET_RANGE,
* but returns \ref MDBX_SUCCESS if the greater key was found or
* \ref MDBX_NOTFOUND otherwise.
*
* For DUPSORT-ed a data value is taken into account for 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
* \ref MDBX_NOTFOUND otherwise. */
MDBX_SET_UPPERBOUND
}; };
#ifndef __cplusplus #ifndef __cplusplus
/** \ingroup c_cursors */ /** \ingroup c_cursors */

View File

@ -14487,7 +14487,7 @@ int mdbx_cursor_get(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
break; break;
case MDBX_FIRST_DUP: case MDBX_FIRST_DUP:
mfunc = mdbx_cursor_first; mfunc = mdbx_cursor_first;
mmove: move:
if (unlikely(data == NULL || !(mc->mc_flags & C_INITIALIZED))) if (unlikely(data == NULL || !(mc->mc_flags & C_INITIALIZED)))
return MDBX_EINVAL; return MDBX_EINVAL;
if (unlikely(mc->mc_xcursor == NULL)) if (unlikely(mc->mc_xcursor == NULL))
@ -14515,7 +14515,8 @@ int mdbx_cursor_get(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
break; break;
case MDBX_LAST_DUP: case MDBX_LAST_DUP:
mfunc = mdbx_cursor_last; mfunc = mdbx_cursor_last;
goto mmove; goto move;
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))
return MDBX_EINVAL; return MDBX_EINVAL;
@ -14548,6 +14549,15 @@ int mdbx_cursor_get(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data,
} }
if (rc == MDBX_SUCCESS && !csr.exact) if (rc == MDBX_SUCCESS && !csr.exact)
rc = MDBX_RESULT_TRUE; rc = MDBX_RESULT_TRUE;
if (unlikely(op == MDBX_SET_UPPERBOUND)) {
/* minor fixups for MDBX_SET_UPPERBOUND */
if (rc == MDBX_RESULT_TRUE)
/* already at great-than by MDBX_SET_LOWERBOUND */
rc = MDBX_SUCCESS;
else if (rc == MDBX_SUCCESS)
/* exactly match, going next */
rc = mdbx_cursor_next(mc, key, data, MDBX_NEXT);
}
break; break;
} }
default: default: