diff --git a/mdbx.h b/mdbx.h index fb7d1400..cce6c6a5 100644 --- a/mdbx.h +++ b/mdbx.h @@ -1718,7 +1718,7 @@ typedef enum MDBX_cursor_op { /** \ref MDBX_DUPFIXED -only: Return up to a page of duplicate data items * from current cursor position. Move cursor to prepare - * for \ref MDBX_NEXT_MULTIPLE. */ + * for \ref MDBX_NEXT_MULTIPLE. \see MDBX_SEEK_AND_GET_MULTIPLE */ MDBX_GET_MULTIPLE, /** Position at last key/data item */ @@ -1734,8 +1734,8 @@ typedef enum MDBX_cursor_op { MDBX_NEXT_DUP, /** \ref MDBX_DUPFIXED -only: Return up to a page of duplicate data items - * from next cursor position. Move cursor to prepare - * for `MDBX_NEXT_MULTIPLE`. */ + * from next cursor position. Move cursor to prepare for `MDBX_NEXT_MULTIPLE`. + * \see MDBX_SEEK_AND_GET_MULTIPLE \see MDBX_GET_MULTIPLE */ MDBX_NEXT_MULTIPLE, /** Position at first data item of next key */ @@ -1760,7 +1760,8 @@ typedef enum MDBX_cursor_op { MDBX_SET_RANGE, /** \ref MDBX_DUPFIXED -only: Position at previous page and return up to - * a page of duplicate data items. */ + * a page of duplicate data items. + * \see MDBX_SEEK_AND_GET_MULTIPLE \see MDBX_GET_MULTIPLE */ MDBX_PREV_MULTIPLE, /** Positions cursor at first key-value pair greater than or equal to @@ -1812,7 +1813,12 @@ typedef enum MDBX_cursor_op { MDBX_TO_PAIR_LESSER_OR_EQUAL /** \copydoc MDBX_TO_PAIR_LESSER_THAN */, MDBX_TO_PAIR_EQUAL /** \copydoc MDBX_TO_PAIR_LESSER_THAN */, MDBX_TO_PAIR_GREATER_OR_EQUAL /** \copydoc MDBX_TO_PAIR_LESSER_THAN */, - MDBX_TO_PAIR_GREATER_THAN /** \copydoc MDBX_TO_PAIR_LESSER_THAN */ + MDBX_TO_PAIR_GREATER_THAN /** \copydoc MDBX_TO_PAIR_LESSER_THAN */, + + /** \ref MDBX_DUPFIXED -only: Seek to given key and return up to a page of + * duplicate data items from current cursor position. Move cursor to prepare + * for \ref MDBX_NEXT_MULTIPLE. \see MDBX_GET_MULTIPLE */ + MDBX_SEEK_AND_GET_MULTIPLE } MDBX_cursor_op; /** \brief Errors and return codes diff --git a/src/cursor.c b/src/cursor.c index bb6f4e61..9c1192d9 100644 --- a/src/cursor.c +++ b/src/cursor.c @@ -2047,27 +2047,24 @@ __hot int cursor_ops(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data, const MDBX_ cASSERT(mc, is_poor(mc) && !is_filled(mc)); return rc; + case MDBX_SEEK_AND_GET_MULTIPLE: + if (unlikely(!key)) + return MDBX_EINVAL; + rc = cursor_seek(mc, key, data, MDBX_SET).err; + if (unlikely(rc != MDBX_SUCCESS)) + return rc; + __fallthrough /* fall through */; case MDBX_GET_MULTIPLE: if (unlikely(!data)) return MDBX_EINVAL; if (unlikely((mc->tree->flags & MDBX_DUPFIXED) == 0)) return MDBX_INCOMPATIBLE; - if (unlikely(!is_pointed(mc))) { - if (unlikely(!key)) - return MDBX_EINVAL; - if (unlikely((mc->flags & z_fresh) == 0)) - return MDBX_ENODATA; - rc = cursor_seek(mc, key, data, MDBX_SET).err; - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - } else { - if (unlikely(!is_filled(mc))) - return MDBX_ENODATA; - if (key) { - const page_t *mp = mc->pg[mc->top]; - const node_t *node = page_node(mp, mc->ki[mc->top]); - *key = get_key(node); - } + if (unlikely(!is_filled(mc))) + return MDBX_ENODATA; + if (key) { + const page_t *mp = mc->pg[mc->top]; + const node_t *node = page_node(mp, mc->ki[mc->top]); + *key = get_key(node); } cASSERT(mc, is_filled(mc)); if (unlikely(!inner_filled(mc))) { @@ -2102,15 +2099,6 @@ __hot int cursor_ops(MDBX_cursor *mc, MDBX_val *key, MDBX_val *data, const MDBX_ return MDBX_EINVAL; if (unlikely(mc->subcur == nullptr)) return MDBX_INCOMPATIBLE; - if (unlikely(!is_pointed(mc))) { - if (unlikely((mc->flags & z_fresh) == 0)) - return MDBX_ENODATA; - rc = outer_last(mc, key, data); - if (unlikely(rc != MDBX_SUCCESS)) - return rc; - mc->subcur->cursor.ki[mc->subcur->cursor.top] = 0; - goto fetch_multiple; - } if (unlikely(!is_filled(mc) || !inner_filled(mc))) return MDBX_ENODATA; rc = cursor_sibling_left(&mc->subcur->cursor);