From 6537d42d7e66a93ab6d2b1e263e4eefbded4f809 Mon Sep 17 00:00:00 2001 From: Zachary Levy Date: Tue, 21 Apr 2026 18:34:57 -0700 Subject: [PATCH] LMDB cleanup --- vendor/lmdb/examples/examples.odin | 23 +- vendor/lmdb/lmdb.odin | 344 ++++++++++++++++------------- 2 files changed, 204 insertions(+), 163 deletions(-) diff --git a/vendor/lmdb/examples/examples.odin b/vendor/lmdb/examples/examples.odin index 846df61..1df4e87 100644 --- a/vendor/lmdb/examples/examples.odin +++ b/vendor/lmdb/examples/examples.odin @@ -15,29 +15,28 @@ main :: proc() { // Create environment for lmdb mdb.panic_on_err(mdb.env_create(&environment)) // Create directory for databases. Won't do anything if it already exists. - // 0o774 gives all permissions for owner and group, read for everyone else. - os.make_directory(DB_PATH, 0o774) + os.make_directory(DB_PATH) // Open the database files (creates them if they don't already exist) - mdb.panic_on_err(mdb.env_open(environment, DB_PATH, 0, DB_MODE)) + mdb.panic_on_err(mdb.env_open(environment, DB_PATH, {}, DB_MODE)) // Transactions txn_handle: ^mdb.Txn db_handle: mdb.Dbi // Put transaction key := 7 - key_val := mdb.autoval(&key) + key_val := mdb.blittable_val(&key) put_data := 12 - put_data_val := mdb.autoval(&put_data) - mdb.panic_on_err(mdb.txn_begin(environment, nil, 0, &txn_handle)) - mdb.panic_on_err(mdb.dbi_open(txn_handle, nil, 0, &db_handle)) - mdb.panic_on_err(mdb.put(txn_handle, db_handle, &key_val.raw, &put_data_val.raw, 0)) + put_data_val := mdb.blittable_val(&put_data) + mdb.panic_on_err(mdb.txn_begin(environment, nil, {}, &txn_handle)) + mdb.panic_on_err(mdb.dbi_open(txn_handle, nil, {}, &db_handle)) + mdb.panic_on_err(mdb.put(txn_handle, db_handle, &key_val, &put_data_val, {})) mdb.panic_on_err(mdb.txn_commit(txn_handle)) // Get transaction - get_data_val := mdb.nil_autoval(int) - mdb.panic_on_err(mdb.txn_begin(environment, nil, 0, &txn_handle)) - mdb.panic_on_err(mdb.get(txn_handle, db_handle, &key_val.raw, &get_data_val.raw)) + data_val: mdb.Val + mdb.panic_on_err(mdb.txn_begin(environment, nil, {}, &txn_handle)) + mdb.panic_on_err(mdb.get(txn_handle, db_handle, &key_val, &data_val)) + data_cpy := mdb.blittable_copy(&data_val, int) mdb.panic_on_err(mdb.txn_commit(txn_handle)) - data_cpy := mdb.autoval_get_data(&get_data_val)^ fmt.println("Get result:", data_cpy) } diff --git a/vendor/lmdb/lmdb.odin b/vendor/lmdb/lmdb.odin index 7292c5c..0315f11 100644 --- a/vendor/lmdb/lmdb.odin +++ b/vendor/lmdb/lmdb.odin @@ -168,20 +168,119 @@ foreign import lib "system:lmdb" import "core:c" import "core:fmt" +import "core:reflect" import "core:sys/posix" +// --------------------------------------------------------------------------------------------------------------------- +// ----- Added Odin Helpers ------------------------ +// --------------------------------------------------------------------------------------------------------------------- + +// Wrap a blittable value's bytes as an LMDB Val. +// T must be a contiguous type with no indirection (no pointers, slices, strings, maps, etc.). +blittable_val :: #force_inline proc(val_ptr: ^$T) -> Val { + fmt.assertf( + reflect.has_no_indirections(type_info_of(T)), + "blitval: type '%v' contains indirection and cannot be stored directly in LMDB", + typeid_of(T), + ) + return Val{size_of(T), val_ptr} +} + +// Reads a blittable T out of the LMDB memory map by copying it into caller +// storage. The returned T has no lifetime tie to the transaction. +blittable_copy :: #force_inline proc(val: ^Val, $T: typeid) -> T { + fmt.assertf( + reflect.has_no_indirections(type_info_of(T)), + "blitval_copy: type '%v' contains indirection and cannot be read directly from LMDB", + typeid_of(T), + ) + return (cast(^T)val.data)^ +} + +// Zero-copy pointer view into the LMDB memory map as a ^T. +// Useful for large blittable types where you want to read individual fields +// without copying the entire value (e.g. ptr.timestamp, ptr.flags). +// MUST NOT be written through — writes either segfault (default env mode) +// or silently corrupt the database (ENV_WRITEMAP). +// MUST NOT be retained past txn_commit, txn_abort, or any subsequent write +// operation on the same env — the pointer is invalidated. +blittable_view :: #force_inline proc(val: ^Val, $T: typeid) -> ^T { + fmt.assertf( + reflect.has_no_indirections(type_info_of(T)), + "blitval_view: type '%v' contains indirection and cannot be viewed directly from LMDB", + typeid_of(T), + ) + return cast(^T)val.data +} + +// Wrap a slice of blittable elements as an LMDB Val for use with put/get. +// T must be a contiguous type with no indirection. +// The caller's slice must remain valid (not freed, not resized) for the +// duration of the put call that consumes this Val. +slice_val :: #force_inline proc(s: []$T) -> Val { + fmt.assertf( + reflect.has_no_indirections(type_info_of(T)), + "slice_val: element type '%v' contains indirection and cannot be stored directly in LMDB", + typeid_of(T), + ) + return Val{uint(len(s) * size_of(T)), raw_data(s)} +} + +// Zero-copy slice view into the LMDB memory map. +// T must match the element type that was originally stored. +// MUST NOT be modified — writes through this slice either segfault (default +// env mode) or silently corrupt the database (ENV_WRITEMAP). +// MUST be copied (e.g. slice.clone) if it needs to outlive the current +// transaction; the view is invalidated by txn_commit, txn_abort, or any +// subsequent write operation on the same env. +slice_view :: #force_inline proc(val: ^Val, $T: typeid) -> []T { + fmt.assertf( + reflect.has_no_indirections(type_info_of(T)), + "slice_view: element type '%v' contains indirection and cannot be read directly from LMDB", + typeid_of(T), + ) + return (cast([^]T)val.data)[:val.size / size_of(T)] +} + +// Wrap a string's bytes as an LMDB Val for use with put/get. +// The caller's string must remain valid (backing memory not freed) for the +// duration of the put call that consumes this Val. +string_val :: #force_inline proc(s: string) -> Val { + return Val{uint(len(s)), raw_data(s)} +} + +// Zero-copy string view into the LMDB memory map. +// MUST NOT be modified — writes through the underlying bytes either segfault +// (default env mode) or silently corrupt the database (ENV_WRITEMAP). +// MUST be copied (e.g. strings.clone) if it needs to outlive the current +// transaction; the view is invalidated by txn_commit, txn_abort, or any +// subsequent write operation on the same env. +string_view :: #force_inline proc(val: ^Val) -> string { + return string((cast([^]u8)val.data)[:val.size]) +} + +// Panic if there is an error +panic_on_err :: #force_inline proc(error: Error, loc := #caller_location) { + if error != .NONE { + fmt.panicf("LMDB error %v: %s", error, strerror(i32(error)), loc = loc) + } +} + +// --------------------------------------------------------------------------------------------------------------------- +// ----- Bindings ------------------------ +// --------------------------------------------------------------------------------------------------------------------- + _ :: c when ODIN_OS == .Windows { mode_t :: c.int -} else { - mode_t :: posix.mode_t -} - -when ODIN_OS == .Windows { filehandle_t :: rawptr -} else { +} else when ODIN_OS == + .Linux || ODIN_OS == .Darwin || ODIN_OS == .FreeBSD || ODIN_OS == .OpenBSD || ODIN_OS == .NetBSD { + mode_t :: posix.mode_t filehandle_t :: c.int +} else { + #panic("levlib/vendor/lmdb: unsupported OS target") } Env :: struct {} @@ -189,7 +288,7 @@ Env :: struct {} Txn :: struct {} /** @brief A handle for an individual database in the DB environment. */ -Dbi :: u32 +Dbi :: c.uint Cursor :: struct {} @@ -205,33 +304,8 @@ Cursor :: struct {} * Other data items can in theory be from 0 to 0xffffffff bytes long. */ Val :: struct { - mv_size: uint, /**< size of the data item */ - mv_data: rawptr, /**< address of the data item */ -} - -// Automatic `Val` handling for a given type 'T'. -// Will not traverse pointers. If `T` stores pointers, you probably don't want to use this. -Auto_Val :: struct($T: typeid) { - raw: Val, -} - -autoval :: #force_inline proc "contextless" (val_ptr: ^$T) -> Auto_Val(T) { - return Auto_Val(T){Val{size_of(T), val_ptr}} -} - -nil_autoval :: #force_inline proc "contextless" ($T: typeid) -> Auto_Val(T) { - return Auto_Val(T){Val{size_of(T), nil}} -} - -autoval_get_data :: #force_inline proc "contextless" (val: ^Auto_Val($T)) -> ^T { - return cast(^T)val.raw.mv_data -} - -// Panic if there is an error -panic_on_err :: #force_inline proc(error: Error) { - if error != .NONE { - fmt.panicf("Irrecoverable LMDB error", strerror(i32(error))) - } + size: uint, /**< size of the data item */ + data: rawptr, /**< address of the data item */ } /** @brief A callback function used to compare two keys in a database */ @@ -253,85 +327,65 @@ Cmp_Func :: #type proc "c" (_: ^Val, _: ^Val) -> i32 */ Rel_Func :: #type proc "c" (item: ^Val, oldptr, newptr, relctx: rawptr) -/** @defgroup mdb_env Environment Flags +/** @defgroup mdb_env Environment Flags * @{ */ -/** mmap at a fixed address (experimental) */ -ENV_FIXEDMAP :: 0x01 -/** no environment directory */ -ENV_NOSUBDIR :: 0x4000 -/** don't fsync after commit */ -ENV_NOSYNC :: 0x10000 -/** read only */ -ENV_RDONLY :: 0x20000 -/** don't fsync metapage after commit */ -ENV_NOMETASYNC :: 0x40000 -/** use writable mmap */ -ENV_WRITEMAP :: 0x80000 -/** use asynchronous msync when #MDB_WRITEMAP is used */ -ENV_MAPASYNC :: 0x100000 -/** tie reader locktable slots to #MDB_txn objects instead of to threads */ -ENV_NOTLS :: 0x200000 -/** don't do any locking, caller must manage their own locks */ -ENV_NOLOCK :: 0x400000 -/** don't do readahead (no effect on Windows) */ -ENV_NORDAHEAD :: 0x800000 -/** don't initialize malloc'd memory before writing to datafile */ -ENV_NOMEMINIT :: 0x1000000 +Env_Flag :: enum u32 { + FIXEDMAP = 0, /**< mmap at a fixed address (experimental) */ + NOSUBDIR = 14, /**< no environment directory */ + NOSYNC = 16, /**< don't fsync after commit */ + RDONLY = 17, /**< read only */ + NOMETASYNC = 18, /**< don't fsync metapage after commit */ + WRITEMAP = 19, /**< use writable mmap */ + MAPASYNC = 20, /**< use asynchronous msync when WRITEMAP is used */ + NOTLS = 21, /**< tie reader locktable slots to Txn objects instead of to threads */ + NOLOCK = 22, /**< don't do any locking, caller must manage their own locks */ + NORDAHEAD = 23, /**< don't do readahead (no effect on Windows) */ + NOMEMINIT = 24, /**< don't initialize malloc'd memory before writing to datafile */ + PREVSNAPSHOT = 25, /**< use the previous snapshot rather than the latest one */ +} +Env_Flags :: distinct bit_set[Env_Flag;c.uint] /** @} */ -/** @defgroup mdb_dbi_open Database Flags +/** @defgroup mdb_dbi_open Database Flags * @{ */ -/** use reverse string keys */ -DB_REVERSEKEY :: 0x02 -/** use sorted duplicates */ -DB_DUPSORT :: 0x04 -/** numeric keys in native byte order: either unsigned int or size_t. - * The keys must all be of the same size. */ -DB_INTEGERKEY :: 0x08 -/** with #MDB_DUPSORT, sorted dup items have fixed size */ -DB_DUPFIXED :: 0x10 -/** with #MDB_DUPSORT, dups are #MDB_INTEGERKEY-style integers */ -DB_INTEGERDUP :: 0x20 -/** with #MDB_DUPSORT, use reverse string dups */ -DB_REVERSEDUP :: 0x40 -/** create DB if not already existing */ -DB_CREATE :: 0x40000 +Db_Flag :: enum u32 { + REVERSEKEY = 1, /**< use reverse string keys */ + DUPSORT = 2, /**< use sorted duplicates */ + INTEGERKEY = 3, /**< numeric keys in native byte order */ + DUPFIXED = 4, /**< with DUPSORT, sorted dup items have fixed size */ + INTEGERDUP = 5, /**< with DUPSORT, dups are INTEGERKEY-style integers */ + REVERSEDUP = 6, /**< with DUPSORT, use reverse string dups */ + CREATE = 18, /**< create DB if not already existing */ +} +Db_Flags :: distinct bit_set[Db_Flag;c.uint] /** @} */ -/** @defgroup mdb_put Write Flags +/** @defgroup mdb_put Write Flags * @{ */ -/** For put: Don't write if the key already exists. */ -WRITE_NOOVERWRITE :: 0x10 -/** Only for #MDB_DUPSORT
- * For put: don't write if the key and data pair already exist.
- * For mdb_cursor_del: remove all duplicate data items. - */ -WRITE_NODUPDATA :: 0x20 -/** For mdb_cursor_put: overwrite the current key/data pair */ -WRITE_CURRENT :: 0x40 -/** For put: Just reserve space for data, don't copy it. Return a - * pointer to the reserved space. - */ -WRITE_RESERVE :: 0x10000 -/** Data is being appended, don't split full pages. */ -WRITE_APPEND :: 0x20000 -/** Duplicate data is being appended, don't split full pages. */ -WRITE_APPENDDUP :: 0x40000 -/** Store multiple data items in one call. Only for #MDB_DUPFIXED. */ -WRITE_MULTIPLE :: 0x80000 -/* @} */ +Write_Flag :: enum u32 { + NOOVERWRITE = 4, /**< For put: Don't write if the key already exists */ + NODUPDATA = 5, /**< For DUPSORT: don't write if the key and data pair already exist. + For mdb_cursor_del: remove all duplicate data items. */ + CURRENT = 6, /**< For mdb_cursor_put: overwrite the current key/data pair */ + RESERVE = 16, /**< For put: Just reserve space for data, don't copy it */ + APPEND = 17, /**< Data is being appended, don't split full pages */ + APPENDDUP = 18, /**< Duplicate data is being appended, don't split full pages */ + MULTIPLE = 19, /**< Store multiple data items in one call. Only for DUPFIXED. */ +} +Write_Flags :: distinct bit_set[Write_Flag;c.uint] +/** @} */ -/** @defgroup mdb_copy Copy Flags +/** @defgroup mdb_copy Copy Flags * @{ */ -/** Compacting copy: Omit free space from copy, and renumber all - * pages sequentially. - */ -CP_COMPACT :: 0x01 -/* @} */ +Copy_Flag :: enum u32 { + COMPACT = 0, /**< Compacting copy: Omit free space from copy, and renumber all pages sequentially. */ +} +Copy_Flags :: distinct bit_set[Copy_Flag;c.uint] +/** @} */ /** @brief Cursor Get operations. * @@ -340,33 +394,24 @@ CP_COMPACT :: 0x01 */ Cursor_Op :: enum c.int { FIRST, /**< Position at first key/data item */ - FIRST_DUP, /**< Position at first data item of current key. - Only for #MDB_DUPSORT */ - GET_BOTH, /**< Position at key/data pair. Only for #MDB_DUPSORT */ - GET_BOTH_RANGE, /**< position at key, nearest data. Only for #MDB_DUPSORT */ + FIRST_DUP, /**< Position at first data item of current key. Only for DUPSORT */ + GET_BOTH, /**< Position at key/data pair. Only for DUPSORT */ + GET_BOTH_RANGE, /**< Position at key, nearest data. Only for DUPSORT */ GET_CURRENT, /**< Return key/data at current cursor position */ - GET_MULTIPLE, /**< Return up to a page of duplicate data items - from current cursor position. Move cursor to prepare - for #MDB_NEXT_MULTIPLE. Only for #MDB_DUPFIXED */ + GET_MULTIPLE, /**< Return up to a page of duplicate data items from current cursor position. Only for DUPFIXED */ LAST, /**< Position at last key/data item */ - LAST_DUP, /**< Position at last data item of current key. - Only for #MDB_DUPSORT */ + LAST_DUP, /**< Position at last data item of current key. Only for DUPSORT */ NEXT, /**< Position at next data item */ - NEXT_DUP, /**< Position at next data item of current key. - Only for #MDB_DUPSORT */ - NEXT_MULTIPLE, /**< Return up to a page of duplicate data items - from next cursor position. Move cursor to prepare - for #MDB_NEXT_MULTIPLE. Only for #MDB_DUPFIXED */ + NEXT_DUP, /**< Position at next data item of current key. Only for DUPSORT */ + NEXT_MULTIPLE, /**< Return up to a page of duplicate data items from next cursor position. Only for DUPFIXED */ NEXT_NODUP, /**< Position at first data item of next key */ PREV, /**< Position at previous data item */ - PREV_DUP, /**< Position at previous data item of current key. - Only for #MDB_DUPSORT */ + PREV_DUP, /**< Position at previous data item of current key. Only for DUPSORT */ PREV_NODUP, /**< Position at last data item of previous key */ SET, /**< Position at specified key */ SET_KEY, /**< Position at specified key, return key + data */ - SET_RANGE, /**< Position at first key greater than or equal to specified key. */ - PREV_MULTIPLE, /**< Position at previous page and return up to - a page of duplicate data items. Only for #MDB_DUPFIXED */ + SET_RANGE, /**< Position at first key greater than or equal to specified key */ + PREV_MULTIPLE, /**< Position at previous page and return up to a page of duplicate data items. Only for DUPFIXED */ } Error :: enum c.int { @@ -419,33 +464,28 @@ Error :: enum c.int { BAD_VALSIZE = -30781, /** The specified DBI was changed unexpectedly */ BAD_DBI = -30780, + /** Unexpected problem - txn should abort */ + PROBLEM = -30779, } /** @brief Statistics for a database in the environment */ Stat :: struct { - ms_psize: u32, - /**< Size of a database page. - This is currently the same for all databases. */ - ms_depth: u32, - /**< Depth (height) of the B-tree */ - ms_branch_pages: uint, - /**< Number of internal (non-leaf) pages */ - ms_leaf_pages: uint, - /**< Number of leaf pages */ - ms_overflow_pages: uint, - /**< Number of overflow pages */ - ms_entries: uint, - /**< Number of data items */ + psize: u32, /**< Size of a database page. This is currently the same for all databases. */ + depth: u32, /**< Depth (height) of the B-tree */ + branch_pages: uint, /**< Number of internal (non-leaf) pages */ + leaf_pages: uint, /**< Number of leaf pages */ + overflow_pages: uint, /**< Number of overflow pages */ + entries: uint, /**< Number of data items */ } /** @brief Information about the environment */ Env_Info :: struct { - me_mapaddr: rawptr, /**< Address of map, if fixed */ - me_mapsize: uint, /**< Size of the data memory map */ - me_last_pgno: uint, /**< ID of the last used page */ - me_last_txnid: uint, /**< ID of the last committed transaction */ - me_maxreaders: u32, /**< max reader slots in the environment */ - me_numreaders: u32, /**< max reader slots used in the environment */ + mapaddr: rawptr, /**< Address of map, if fixed */ + mapsize: uint, /**< Size of the data memory map */ + last_pgno: uint, /**< ID of the last used page */ + last_txnid: uint, /**< ID of the last committed transaction */ + maxreaders: u32, /**< max reader slots in the environment */ + numreaders: u32, /**< max reader slots used in the environment */ } /** @brief A callback function for most LMDB assert() failures, @@ -454,7 +494,7 @@ Env_Info :: struct { * @param[in] env An environment handle returned by #mdb_env_create(). * @param[in] msg The assertion message, not including newline. */ -Assert_Func :: proc "c" (_: ^Env, _: cstring) +Assert_Func :: #type proc "c" (_: ^Env, _: cstring) /** @brief A callback function used to print a message from the library. * @@ -462,7 +502,7 @@ Assert_Func :: proc "c" (_: ^Env, _: cstring) * @param[in] ctx An arbitrary context pointer for the callback. * @return < 0 on failure, >= 0 on success. */ -Msg_Func :: proc "c" (_: cstring, _: rawptr) -> i32 +Msg_Func :: #type proc "c" (_: cstring, _: rawptr) -> i32 @(default_calling_convention = "c", link_prefix = "mdb_") foreign lib { @@ -623,7 +663,7 @@ foreign lib { * */ @(require_results) - env_open :: proc(env: ^Env, path: cstring, flags: u32, mode: mode_t) -> Error --- + env_open :: proc(env: ^Env, path: cstring, flags: Env_Flags, mode: mode_t) -> Error --- /** @brief Copy an LMDB environment to the specified path. * @@ -682,7 +722,7 @@ foreign lib { * @return A non-zero error value on failure and 0 on success. */ @(require_results) - env_copy2 :: proc(env: ^Env, path: cstring, flags: u32) -> Error --- + env_copy2 :: proc(env: ^Env, path: cstring, flags: Copy_Flags) -> Error --- /** @brief Copy an LMDB environment to the specified file descriptor, * with options. @@ -702,7 +742,7 @@ foreign lib { * @return A non-zero error value on failure and 0 on success. */ @(require_results) - env_copyfd2 :: proc(env: ^Env, fd: filehandle_t, flags: u32) -> Error --- + env_copyfd2 :: proc(env: ^Env, fd: filehandle_t, flags: Copy_Flags) -> Error --- /** @brief Return statistics about the LMDB environment. * @@ -767,7 +807,7 @@ foreign lib { * */ @(require_results) - env_set_flags :: proc(env: ^Env, flags: u32, onoff: i32) -> Error --- + env_set_flags :: proc(env: ^Env, flags: Env_Flags, onoff: i32) -> Error --- /** @brief Get environment flags. * @@ -780,7 +820,7 @@ foreign lib { * */ @(require_results) - env_get_flags :: proc(env: ^Env, flags: ^u32) -> Error --- + env_get_flags :: proc(env: ^Env, flags: ^Env_Flags) -> Error --- /** @brief Return the path that was used in #mdb_env_open(). * @@ -973,7 +1013,7 @@ foreign lib { * */ @(require_results) - txn_begin :: proc(env: ^Env, parent: ^Txn, flags: u32, txn: ^^Txn) -> Error --- + txn_begin :: proc(env: ^Env, parent: ^Txn, flags: Env_Flags, txn: ^^Txn) -> Error --- /** @brief Returns the transaction's #MDB_env * @@ -1126,7 +1166,7 @@ foreign lib { * */ @(require_results) - dbi_open :: proc(txn: ^Txn, name: cstring, flags: u32, dbi: ^Dbi) -> Error --- + dbi_open :: proc(txn: ^Txn, name: cstring, flags: Db_Flags, dbi: ^Dbi) -> Error --- /** @brief Retrieve statistics for a database. * @@ -1151,7 +1191,7 @@ foreign lib { * @return A non-zero error value on failure and 0 on success. */ @(require_results) - dbi_flags :: proc(txn: ^Txn, dbi: Dbi, flags: ^u32) -> Error --- + dbi_flags :: proc(txn: ^Txn, dbi: Dbi, flags: ^Db_Flags) -> Error --- /** @brief Close a database handle. Normally unnecessary. Use with care: * @@ -1229,6 +1269,7 @@ foreign lib { @(require_results) set_dupsort :: proc(txn: ^Txn, dbi: Dbi, cmp: Cmp_Func) -> Error --- + // NOTE: Unimplemented in current LMDB — this function has no effect. /** @brief Set a relocation function for a #MDB_FIXEDMAP database. * * @todo The relocation function is called whenever it is necessary to move the data @@ -1250,6 +1291,7 @@ foreign lib { @(require_results) set_relfunc :: proc(txn: ^Txn, dbi: Dbi, rel: Rel_Func) -> Error --- + // NOTE: Unimplemented in current LMDB — this function has no effect. /** @brief Set a context pointer for a #MDB_FIXEDMAP database's relocation function. * * See #mdb_set_relfunc and #MDB_rel_func for more details. @@ -1344,7 +1386,7 @@ foreign lib { * */ @(require_results) - put :: proc(txn: ^Txn, dbi: Dbi, key: ^Val, data: ^Val, flags: u32) -> Error --- + put :: proc(txn: ^Txn, dbi: Dbi, key: ^Val, data: ^Val, flags: Write_Flags) -> Error --- /** @brief Delete items from a database. * @@ -1517,7 +1559,7 @@ foreign lib { * */ @(require_results) - cursor_put :: proc(cursor: ^Cursor, key: ^Val, data: ^Val, flags: u32) -> Error --- + cursor_put :: proc(cursor: ^Cursor, key: ^Val, data: ^Val, flags: Write_Flags) -> Error --- /** @brief Delete current key/data pair * @@ -1541,7 +1583,7 @@ foreign lib { * */ @(require_results) - cursor_del :: proc(cursor: ^Cursor, flags: u32) -> Error --- + cursor_del :: proc(cursor: ^Cursor, flags: Write_Flags) -> Error --- /** @brief Return count of duplicates for current key. *