ppad-lmdb-0.1.0: lib/Database/LMDB/Internal.hs
{-# OPTIONS_HADDOCK not-home #-}
{-# LANGUAGE CApiFFI #-}
-- |
-- Module: Database.LMDB.Internal
-- Copyright: (c) 2026 Jared Tobin
-- License: MIT
-- Maintainer: Jared Tobin <jared@ppad.tech>
--
-- Raw FFI declarations and constants for the LMDB C API. This module
-- is exposed for power users; prefer "Database.LMDB" for the safe,
-- bracketed interface.
module Database.LMDB.Internal (
-- * Opaque handles
MDB_env
, MDB_txn
, MDB_dbi
, MDB_cursor
-- * Value pair
, MDB_val(..)
-- * Environment flags
, _MDB_NOSUBDIR
, _MDB_NOSYNC
, _MDB_RDONLY
, _MDB_NOMETASYNC
, _MDB_NOTLS
-- * Database open flags
, _MDB_CREATE
-- * Put flags
, _MDB_NOOVERWRITE
, _MDB_APPEND
-- * Cursor operations
, _MDB_FIRST
, _MDB_LAST
, _MDB_NEXT
, _MDB_PREV
, _MDB_SET
, _MDB_SET_RANGE
, _MDB_GET_CURRENT
-- * Error codes
, _MDB_SUCCESS
, _MDB_KEYEXIST
, _MDB_NOTFOUND
, _MDB_MAP_FULL
, _MDB_CORRUPTED
, _MDB_PANIC
, _MDB_VERSION_MISMATCH
, _MDB_INVALID
, _MDB_BAD_TXN
, _MDB_BAD_VALSIZE
, _MDB_BAD_DBI
-- * Environment lifecycle
, mdb_env_create
, mdb_env_open
, mdb_env_close
, mdb_env_set_mapsize
, mdb_env_set_maxdbs
, mdb_env_sync
-- * Transactions
, mdb_txn_begin
, mdb_txn_commit
, mdb_txn_abort
-- * Databases
, mdb_dbi_open
, mdb_dbi_close
-- * Key-value operations
, mdb_get
, mdb_put
, mdb_del
-- * Cursors
, mdb_cursor_open
, mdb_cursor_close
, mdb_cursor_get
-- * Diagnostics
, mdb_strerror
) where
import Foreign.C.String (CString)
import Foreign.C.Types
(CInt(..), CUInt(..), CSize(..), CChar(..))
import Foreign.Ptr (Ptr)
import Foreign.Storable (Storable(..))
import System.Posix.Types (CMode(..))
-- opaque handles -------------------------------------------------------------
data MDB_env
data MDB_txn
data MDB_cursor
-- | LMDB's database identifier is a plain @unsigned int@ value type,
-- not a pointer.
type MDB_dbi = CUInt
-- value pair -----------------------------------------------------------------
-- | The key-or-value pair LMDB passes across the FFI boundary.
data MDB_val = MDB_val
{ mvSize :: !CSize
, mvData :: !(Ptr CChar)
}
instance Storable MDB_val where
sizeOf _ = 2 * sizeOf (undefined :: Ptr ())
{-# INLINE sizeOf #-}
alignment _ = alignment (undefined :: Ptr ())
{-# INLINE alignment #-}
peek p = do
sz <- peekByteOff p 0
pd <- peekByteOff p (sizeOf (undefined :: Ptr ()))
pure (MDB_val sz pd)
{-# INLINE peek #-}
poke p (MDB_val sz pd) = do
pokeByteOff p 0 sz
pokeByteOff p (sizeOf (undefined :: Ptr ())) pd
{-# INLINE poke #-}
-- environment flags ----------------------------------------------------------
_MDB_NOSUBDIR, _MDB_NOSYNC, _MDB_RDONLY, _MDB_NOMETASYNC, _MDB_NOTLS
:: CUInt
_MDB_NOSUBDIR = 0x4000
_MDB_NOSYNC = 0x10000
_MDB_RDONLY = 0x20000
_MDB_NOMETASYNC = 0x40000
_MDB_NOTLS = 0x200000
-- database open flags --------------------------------------------------------
_MDB_CREATE :: CUInt
_MDB_CREATE = 0x40000
-- put flags ------------------------------------------------------------------
_MDB_NOOVERWRITE, _MDB_APPEND :: CUInt
_MDB_NOOVERWRITE = 0x10
_MDB_APPEND = 0x20000
-- cursor ops -----------------------------------------------------------------
-- These mirror the enum MDB_cursor_op declared in lmdb.h. We only
-- bind the operations the safe wrapper currently uses; add more as
-- needed.
_MDB_FIRST, _MDB_LAST, _MDB_NEXT, _MDB_PREV
, _MDB_SET, _MDB_SET_RANGE, _MDB_GET_CURRENT :: CInt
_MDB_FIRST = 0
_MDB_LAST = 6
_MDB_NEXT = 8
_MDB_PREV = 12
_MDB_SET = 15
_MDB_SET_RANGE = 17 -- index per MDB_cursor_op enum (post-DUP entries)
_MDB_GET_CURRENT = 4
-- error codes ----------------------------------------------------------------
_MDB_SUCCESS, _MDB_KEYEXIST, _MDB_NOTFOUND, _MDB_MAP_FULL
, _MDB_CORRUPTED, _MDB_PANIC, _MDB_VERSION_MISMATCH, _MDB_INVALID
, _MDB_BAD_TXN, _MDB_BAD_VALSIZE, _MDB_BAD_DBI :: CInt
_MDB_SUCCESS = 0
_MDB_KEYEXIST = -30799
_MDB_NOTFOUND = -30798
_MDB_CORRUPTED = -30796
_MDB_PANIC = -30795
_MDB_VERSION_MISMATCH = -30794
_MDB_INVALID = -30793
_MDB_MAP_FULL = -30792
_MDB_BAD_TXN = -30782
_MDB_BAD_VALSIZE = -30781
_MDB_BAD_DBI = -30780
-- foreign imports ------------------------------------------------------------
-- environment lifecycle
foreign import capi "lmdb.h mdb_env_create"
mdb_env_create :: Ptr (Ptr MDB_env) -> IO CInt
foreign import capi "lmdb.h mdb_env_open"
mdb_env_open
:: Ptr MDB_env -> CString -> CUInt -> CMode -> IO CInt
foreign import capi "lmdb.h mdb_env_close"
mdb_env_close :: Ptr MDB_env -> IO ()
foreign import capi "lmdb.h mdb_env_set_mapsize"
mdb_env_set_mapsize :: Ptr MDB_env -> CSize -> IO CInt
foreign import capi "lmdb.h mdb_env_set_maxdbs"
mdb_env_set_maxdbs :: Ptr MDB_env -> MDB_dbi -> IO CInt
foreign import capi "lmdb.h mdb_env_sync"
mdb_env_sync :: Ptr MDB_env -> CInt -> IO CInt
-- transactions
foreign import capi "lmdb.h mdb_txn_begin"
mdb_txn_begin
:: Ptr MDB_env
-> Ptr MDB_txn -- parent (NULL for top-level)
-> CUInt -- flags
-> Ptr (Ptr MDB_txn)
-> IO CInt
foreign import capi "lmdb.h mdb_txn_commit"
mdb_txn_commit :: Ptr MDB_txn -> IO CInt
foreign import capi "lmdb.h mdb_txn_abort"
mdb_txn_abort :: Ptr MDB_txn -> IO ()
-- databases
foreign import capi "lmdb.h mdb_dbi_open"
mdb_dbi_open
:: Ptr MDB_txn
-> CString -- name; NULL for the default unnamed db
-> CUInt -- flags
-> Ptr MDB_dbi
-> IO CInt
foreign import capi "lmdb.h mdb_dbi_close"
mdb_dbi_close :: Ptr MDB_env -> MDB_dbi -> IO ()
-- key-value ops
foreign import capi "lmdb.h mdb_get"
mdb_get
:: Ptr MDB_txn -> MDB_dbi -> Ptr MDB_val -> Ptr MDB_val -> IO CInt
foreign import capi "lmdb.h mdb_put"
mdb_put
:: Ptr MDB_txn
-> MDB_dbi
-> Ptr MDB_val -- key
-> Ptr MDB_val -- data
-> CUInt -- flags
-> IO CInt
foreign import capi "lmdb.h mdb_del"
mdb_del
:: Ptr MDB_txn
-> MDB_dbi
-> Ptr MDB_val -- key
-> Ptr MDB_val -- data; NULL except for MDB_DUPSORT
-> IO CInt
-- cursors
foreign import capi "lmdb.h mdb_cursor_open"
mdb_cursor_open
:: Ptr MDB_txn -> MDB_dbi -> Ptr (Ptr MDB_cursor) -> IO CInt
foreign import capi "lmdb.h mdb_cursor_close"
mdb_cursor_close :: Ptr MDB_cursor -> IO ()
foreign import capi "lmdb.h mdb_cursor_get"
mdb_cursor_get
:: Ptr MDB_cursor
-> Ptr MDB_val -- key (in/out)
-> Ptr MDB_val -- data (out)
-> CInt -- MDB_cursor_op
-> IO CInt
-- diagnostics
foreign import capi "lmdb.h mdb_strerror"
mdb_strerror :: CInt -> IO CString