mirror of https://github.com/poanetwork/rox.git
feat(): add delete, restore basic testing
This commit is contained in:
parent
aab14d167e
commit
f8dbe6a0db
21
lib/rox.ex
21
lib/rox.ex
|
@ -211,6 +211,11 @@ defmodule Rox do
|
|||
The default arguments of this function is used for the `Enumerable` implementation
|
||||
for `DB` and `ColumnFamily` structs.
|
||||
|
||||
Note: The result of stream is a cursor which is *not* meant to be shared across processes.
|
||||
Iterating over the cursor will result in an internal state in RocksDB being modified.
|
||||
If two processes try and use the same cursor, they will consume
|
||||
each others results. This may or may not be desired.
|
||||
|
||||
"""
|
||||
@spec stream(DB.t | ColumnFamily.t, Iterator.mode) :: Cursor.t | {:error, any}
|
||||
def stream(db_or_cf, mode \\ :start)
|
||||
|
@ -240,6 +245,22 @@ defmodule Rox do
|
|||
Native.count_cf(db, cf)
|
||||
end
|
||||
|
||||
|
||||
@doc """
|
||||
Deletes the specified `key` from the provided database or column family.
|
||||
|
||||
Optionally takes a list of `write_opts`.
|
||||
|
||||
"""
|
||||
@spec delete(DB.t | ColumnFamily.t, key, write_options) :: :ok | {:error, any}
|
||||
def delete(db_or_cf, key, write_opts \\ [])
|
||||
def delete(%DB{resource: db}, key, write_opts) do
|
||||
Native.delete(db, key, to_map(write_opts))
|
||||
end
|
||||
def delete(%ColumnFamily{db_resource: db, cf_resource: cf}, key, write_opts) do
|
||||
Native.delete_cf(db, cf, key, to_map(write_opts))
|
||||
end
|
||||
|
||||
defp to_map(map) when is_map(map), do: map
|
||||
defp to_map([]), do: %{}
|
||||
defp to_map(enum), do: Enum.into(enum, %{})
|
||||
|
|
|
@ -10,6 +10,8 @@ defmodule Rox.Native do
|
|||
def put_cf(_, _, _, _, _), do: raise "Nif not loaded"
|
||||
def get(_, _, _), do: raise "Nif not loaded"
|
||||
def get_cf(_, _, _, _), do: raise "Nif not loaded"
|
||||
def delete(_, _, _), do: raise "Nif not loaded"
|
||||
def delete_cf(_, _, _, _), do: raise "Nif not loaded"
|
||||
def iterate(_, _), do: raise "Nif not loaded"
|
||||
def iterate_cf(_, _, _), do: raise "Nif not loaded"
|
||||
def iterator_next(_), do: raise "Nif not loaded"
|
||||
|
|
|
@ -533,6 +533,51 @@ fn put_cf<'a>(env: NifEnv<'a>, args: &[NifTerm<'a>]) -> NifResult<NifTerm<'a>> {
|
|||
Ok(atoms::ok().encode(env))
|
||||
}
|
||||
|
||||
fn delete<'a>(env: NifEnv<'a>, args: &[NifTerm<'a>]) -> NifResult<NifTerm<'a>> {
|
||||
let db_arc: ResourceArc<DBHandle> = args[0].decode()?;
|
||||
let db = db_arc.deref().db.write().unwrap();
|
||||
|
||||
let key: &str = args[1].decode()?;
|
||||
|
||||
let resp =
|
||||
if args[2].map_size()? > 0 {
|
||||
let write_opts = decode_write_options(env, args[2])?;
|
||||
db.delete_opt(key.as_bytes(), &write_opts)
|
||||
} else {
|
||||
db.delete(key.as_bytes())
|
||||
};
|
||||
|
||||
|
||||
handle_error!(env, resp);
|
||||
|
||||
|
||||
Ok(atoms::ok().encode(env))
|
||||
}
|
||||
|
||||
fn delete_cf<'a>(env: NifEnv<'a>, args: &[NifTerm<'a>]) -> NifResult<NifTerm<'a>> {
|
||||
let db_arc: ResourceArc<DBHandle> = args[0].decode()?;
|
||||
let db = db_arc.deref().db.write().unwrap();
|
||||
|
||||
let cf_arc: ResourceArc<CFHandle> = args[1].decode()?;
|
||||
let cf = cf_arc.deref().cf;
|
||||
|
||||
let key: &str = args[2].decode()?;
|
||||
|
||||
let resp =
|
||||
if args[3].map_size()? > 0 {
|
||||
let write_opts = decode_write_options(env, args[3])?;
|
||||
db.delete_cf_opt(cf, key.as_bytes(), &write_opts)
|
||||
} else {
|
||||
db.delete_cf(cf, key.as_bytes() )
|
||||
};
|
||||
|
||||
|
||||
handle_error!(env, resp);
|
||||
|
||||
|
||||
Ok(atoms::ok().encode(env))
|
||||
}
|
||||
|
||||
fn get<'a>(env: NifEnv<'a>, args: &[NifTerm<'a>]) -> NifResult<NifTerm<'a>> {
|
||||
let db_arc: ResourceArc<DBHandle> = args[0].decode()?;
|
||||
let db = db_arc.deref().db.read().unwrap();
|
||||
|
@ -652,6 +697,8 @@ rustler_export_nifs!(
|
|||
("cf_handle", 2, cf_handle),
|
||||
("put", 4, put),
|
||||
("put_cf", 5, put_cf),
|
||||
("delete", 3, delete),
|
||||
("delete_cf", 4, delete_cf),
|
||||
("count", 1, count),
|
||||
("count_cf", 2, count_cf),
|
||||
("iterate", 2, iterate),
|
||||
|
|
|
@ -2,65 +2,76 @@ defmodule RoxTest do
|
|||
use ExUnit.Case, async: false
|
||||
doctest Rox
|
||||
|
||||
setup do
|
||||
setup_all do
|
||||
path =
|
||||
Path.join(__DIR__, "test.rocksdb")
|
||||
|
||||
cf_path =
|
||||
Path.join(__DIR__, "cf_test.rocksdb")
|
||||
|
||||
{:ok, db} =
|
||||
Rox.open(path, create_if_missing: true)
|
||||
|
||||
{:ok, db} =
|
||||
Rox.open(path, create_if_missing: true)
|
||||
{:ok, db, %{"people" => people}} =
|
||||
Rox.open(path, [create_if_missing: true, auto_create_column_families: true], ["people"])
|
||||
|
||||
on_exit fn ->
|
||||
Rox.close(db)
|
||||
File.rm_rf(path)
|
||||
:ok
|
||||
end
|
||||
|
||||
{:ok, %{db: db}}
|
||||
{:ok, %{db: db, people: people}}
|
||||
end
|
||||
|
||||
describe "Working with default column family" do
|
||||
test "simple put and get", %{db: db} do
|
||||
assert :not_found = Rox.get(db, "key")
|
||||
:ok = Rox.put(db, "key", "val")
|
||||
assert :not_found = Rox.get(db, "put_test")
|
||||
|
||||
assert {:ok, "val"} = Rox.get(db, "key")
|
||||
end
|
||||
assert :ok = Rox.put(db, "put_test", "val")
|
||||
|
||||
test "stream_keys", %{db: db} do
|
||||
:ok = Rox.put(db, "key", "val")
|
||||
|
||||
count = Rox.stream_keys(db)
|
||||
|> Enum.count
|
||||
|
||||
assert count == 1
|
||||
assert {:ok, "val"} = Rox.get(db, "put_test")
|
||||
end
|
||||
|
||||
test "stream", %{db: db} do
|
||||
:ok = Rox.put(db, "key", "val")
|
||||
assert :ok = Rox.put(db, "stream_test", "val")
|
||||
|
||||
count = Rox.stream(db)
|
||||
count =
|
||||
Rox.stream(db)
|
||||
|> Enum.count
|
||||
|
||||
assert count == 1
|
||||
assert count > 0
|
||||
end
|
||||
|
||||
test "partial exhaustion of a stream", %{db: db} do
|
||||
:ok = Rox.put(db, "key", "val")
|
||||
:ok = Rox.put(db, "alt-key", "val")
|
||||
test "delete", %{db: db} do
|
||||
assert :not_found = Rox.get(db, "delete_test")
|
||||
assert :ok = Rox.put(db, "delete_test", "some_val")
|
||||
assert {:ok, _val} = Rox.get(db, "delete_test")
|
||||
assert :ok = Rox.delete(db, "delete_test")
|
||||
|
||||
Rox.stream_keys(db) |> Enum.take(1)
|
||||
assert :not_found = Rox.get(db, "delete_test")
|
||||
end
|
||||
end
|
||||
|
||||
test "count", %{db: db} do
|
||||
describe "Working with non-default column family" do
|
||||
test "simple put and get", %{people: people} do
|
||||
assert :not_found = Rox.get(people, "put_test")
|
||||
|
||||
assert :ok = Rox.put(people, "put_test", "val")
|
||||
|
||||
assert {:ok, "val"} = Rox.get(people, "put_test")
|
||||
end
|
||||
|
||||
test "stream", %{people: people} do
|
||||
assert :ok = Rox.put(people, "stream_test", "val")
|
||||
|
||||
count =
|
||||
Rox.count(db)
|
||||
Rox.stream(people)
|
||||
|> Enum.count
|
||||
|
||||
assert is_number(count)
|
||||
assert count >= 0
|
||||
assert count > 0
|
||||
end
|
||||
|
||||
test "delete", %{people: people} do
|
||||
assert :not_found = Rox.get(people, "delete_test")
|
||||
assert :ok = Rox.put(people, "delete_test", "some_val")
|
||||
assert {:ok, _val} = Rox.get(people, "delete_test")
|
||||
assert :ok = Rox.delete(people, "delete_test")
|
||||
|
||||
assert :not_found = Rox.get(people, "delete_test")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
Loading…
Reference in New Issue