MDB_PREV_NODUP, /**< Position at last data item of previous key */
MDB_SET, /**< Position at specified key */
MDB_SET_KEY, /**< Position at specified key, return key + data */
- MDB_SET_RANGE /**< Position at first key greater than or equal to specified key. */
+ MDB_SET_RANGE, /**< Position at first key greater than or equal to specified key. */
+ MDB_PREV_MULTIPLE /**< Position at previous page and return key and up to
+ a page of duplicate data items. Only for #MDB_DUPFIXED */
} MDB_cursor_op;
/** @defgroup errors Return Codes
* This flag may only be used in combination with #MDB_DUPSORT. This option
* tells the library that the data items for this database are all the same
* size, which allows further optimizations in storage and retrieval. When
- * all data items are the same size, the #MDB_GET_MULTIPLE and #MDB_NEXT_MULTIPLE
- * cursor operations may be used to retrieve multiple items at once.
+ * all data items are the same size, the #MDB_GET_MULTIPLE, #MDB_NEXT_MULTIPLE
+ * and #MDB_PREV_MULTIPLE cursor operations may be used to retrieve multiple
+ * items at once.
* <li>#MDB_INTEGERDUP
* This option specifies that duplicate data items are binary integers,
* similar to #MDB_INTEGERKEY keys.
* and the actual use of the message uses more than 4K of stack.
*/
#define MSGSIZE 1024
-#define PADSIZE 4096
+#define PADSIZE 4096
char buf[MSGSIZE+PADSIZE], *ptr = buf;
#endif
int i;
}
}
break;
+ case MDB_PREV_MULTIPLE:
+ if (data == NULL) {
+ rc = EINVAL;
+ break;
+ }
+ if (!(mc->mc_db->md_flags & MDB_DUPFIXED)) {
+ rc = MDB_INCOMPATIBLE;
+ break;
+ }
+ if (!(mc->mc_flags & C_INITIALIZED))
+ rc = mdb_cursor_last(mc, key, data);
+ else
+ rc = MDB_SUCCESS;
+ if (rc == MDB_SUCCESS) {
+ MDB_cursor *mx = &mc->mc_xcursor->mx_cursor;
+ if (mx->mc_flags & C_INITIALIZED) {
+ rc = mdb_cursor_sibling(mx, 0);
+ if (rc == MDB_SUCCESS)
+ goto fetchm;
+ } else {
+ rc = MDB_NOTFOUND;
+ }
+ }
+ break;
case MDB_NEXT:
case MDB_NEXT_DUP:
case MDB_NEXT_NODUP: