Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 21 additions & 7 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -57,12 +57,26 @@ code, message, value = db:get("my_column_family", "key")
-- Delete the key-value pair
db:delete("my_column_family", "key")

-- Create a cursor for iterating over key-value pairs
code, message, cursor = db:cursor_init("my_column_family")
assert(code == 0, message)

-- Move cursor to next key-value pair
code, message = cursor:next()
assert(code == 0, message)

-- Get current key-value pair
code, message, value = cursor:get()
assert(code == 0, message)

-- Move cursor to previous key-value pair
code, message = cursor:prev()
assert(code == 0, message)

-- Free cursor when done
code, message = cursor:free()
assert(code == 0, message)

--- Close the database
lib.close(db)
```

#### Test lua wrapper-library
```bash
cd build
lua ../test_lua.lua
```
```
77 changes: 77 additions & 0 deletions spec/tidesdb_spec.lua
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,17 @@ local value = "value"
local value_size = string.len(value)
local ttl = 10

-- Setup test directory
os.execute("rm -rf " .. directory)
os.execute("mkdir -p " .. directory)
os.execute("chmod 777 " .. directory)

describe("load", function()
it("should open tidesdb_lua", function()
assert.truthy(require("libtidesdb_lua"))
end)
end)

describe("open and close", function()
it("should open and close db", function()
assert.truthy(lib.open(directory))
Expand Down Expand Up @@ -233,3 +244,69 @@ describe("transactions put and delete", function()
assert.is_equal(0, code)
end)
end)

describe("cursor operations", function()
it("should perform cursor operations", function()
assert.truthy(lib.open(directory))

local code, message, db = lib.open(directory)
assert.is_equal(0, code)

code, message = db:create_column_family(name,
threshold,
max_skip_list,
prob_skip_list,
enable_compression,
compression_algo,
enable_bloom_filter)
assert.is_equal(0, code)

-- Insert test data
for i=1,5 do
code, message = db:put(name, "key" .. i, "value" .. i, ttl)
assert.is_equal(0, code)
end

-- Create cursor
code, message, cursor = db:cursor_init(name)
assert.is_equal(0, code)

-- Test next operations
for i=1,5 do
code, message, key, value = cursor:get()
assert.is_equal(0, code)
assert.is_equal(key, "key" .. i)
assert.is_equal(value, "value" .. i)
code, message = cursor:next()
if i ~= 5 then
assert.is_equal(0, code)
end
end

-- Position cursor at last element
code, message = cursor:prev()
assert.is_equal(0, code)

-- Test prev operations
for i=5,1,-1 do
code, message, key, value = cursor:get()
assert.is_equal(0, code)
assert.is_equal(key, "key" .. i)
assert.is_equal(value, "value" .. i)
code, message = cursor:prev()
if i ~= 1 then
assert.is_equal(0, code)
end
end

-- Free cursor
code, message = cursor:free()
assert.is_equal(0, code)

code, message = db:drop_column_family(name)
assert.is_equal(0, code)

local code, message, db = lib.close(db)
assert.is_equal(0, code)
end)
end)
97 changes: 94 additions & 3 deletions src/tidesdb-lua.c
Original file line number Diff line number Diff line change
Expand Up @@ -72,10 +72,14 @@ static int txn_commit(lua_State *L);
static int txn_rollback(lua_State *L);
static int txn_free(lua_State *L);

static int cursor_init(lua_State *L);
static int cursor_next(lua_State *L);
static int cursor_prev(lua_State *L);
static int cursor_get(lua_State *L);
static int cursor_free(lua_State *L);

static const luaL_Reg regs_tidesdb_lib_lua[] = {
{"open", db_open},
{"close", db_close},
{"txn_begin", txn_begin},
{"open", db_open}, {"close", db_close}, {"txn_begin", txn_begin}, {"cursor_init", cursor_init},
{NULL, NULL},
};

Expand All @@ -88,6 +92,7 @@ static const luaL_Reg regs_tidesdb_lua[] = {
{"compact_sstables", compact_sstables},
{"list_column_families", list_column_families},
{"txn_begin", txn_begin},
{"cursor_init", cursor_init},
{NULL, NULL},
};

Expand All @@ -96,6 +101,11 @@ static const luaL_Reg regs_tidesdb_txn_lua[] = {
{"rollback", txn_rollback}, {"free", txn_free}, {NULL, NULL},
};

static const luaL_Reg regs_tidesdb_curs_lua[] = {
{"next", cursor_next}, {"prev", cursor_prev}, {"get", cursor_get},
{"free", cursor_free}, {NULL, NULL},
};

static int db_open(lua_State *L)
{
const char *directory = luaL_checkstring(L, 1);
Expand Down Expand Up @@ -293,6 +303,87 @@ static int txn_free(lua_State *L)
LUA_RET_CODE()
}

static int cursor_init(lua_State *L)
{
lua_getfield(L, 1, "self_db");
tidesdb_t *db = lua_touserdata(L, -1);
const char *column_family = luaL_checkstring(L, 2);
tidesdb_cursor_t *curs = NULL;

tidesdb_err_t *ret = tidesdb_cursor_init(db, column_family, &curs);
if (ret)
{
lua_pushinteger(L, ret->code);
lua_pushstring(L, ret->message);
tidesdb_err_free(ret);
return 2;
}
else
{
lua_pushinteger(L, 0);
lua_pushstring(L, "OK");

lua_newtable(L);
luaL_setfuncs(L, regs_tidesdb_curs_lua, 0);
lua_pushlightuserdata(L, curs);
lua_setfield(L, -2, "self_curs");
return 3;
}
}

static int cursor_next(lua_State *L)
{
lua_getfield(L, 1, "self_curs");
tidesdb_cursor_t *curs = lua_touserdata(L, -1);
tidesdb_err_t *ret = tidesdb_cursor_next(curs);
LUA_RET_CODE()
}

static int cursor_prev(lua_State *L)
{
lua_getfield(L, 1, "self_curs");
tidesdb_cursor_t *curs = lua_touserdata(L, -1);
tidesdb_err_t *ret = tidesdb_cursor_prev(curs);
LUA_RET_CODE()
}

static int cursor_get(lua_State *L)
{
lua_getfield(L, 1, "self_curs");
tidesdb_cursor_t *curs = lua_touserdata(L, -1);
uint8_t *key = NULL;
size_t key_size = 0;
uint8_t *value = NULL;
size_t value_size = 0;

tidesdb_err_t *ret = tidesdb_cursor_get(curs, &key, &key_size, &value, &value_size);
if (ret)
{
lua_pushinteger(L, ret->code);
lua_pushstring(L, ret->message);
tidesdb_err_free(ret);
return 2;
}
else
{
lua_pushinteger(L, 0);
lua_pushstring(L, "OK");
lua_pushlstring(L, (char *)key, key_size);
lua_pushlstring(L, (char *)value, value_size);
free(key);
free(value);
return 4;
}
}

static int cursor_free(lua_State *L)
{
lua_getfield(L, 1, "self_curs");
tidesdb_cursor_t *curs = lua_touserdata(L, -1);
tidesdb_err_t *ret = tidesdb_cursor_free(curs);
LUA_RET_CODE()
}

LUALIB_API int luaopen_libtidesdb_lua(lua_State *L)
{
luaL_newlib(L, regs_tidesdb_lib_lua);
Expand Down