aboutsummaryrefslogtreecommitdiffstats
path: root/log_db/src
diff options
context:
space:
mode:
Diffstat (limited to 'log_db/src')
-rw-r--r--log_db/src/common.rs5
-rw-r--r--log_db/src/config.rs34
-rw-r--r--log_db/src/engine.rs25
-rw-r--r--log_db/src/lib.rs59
4 files changed, 75 insertions, 48 deletions
diff --git a/log_db/src/common.rs b/log_db/src/common.rs
index 9bafdd4..ca9f451 100644
--- a/log_db/src/common.rs
+++ b/log_db/src/common.rs
@@ -289,10 +289,7 @@ impl Value {
}
}
-pub fn get_secondary_memtable_index_by_field<Field: Eq>(
- sks: &Vec<Field>,
- field: &Field,
-) -> Option<usize> {
+pub fn get_secondary_memtable_index_by_field(sks: &Vec<String>, field: &str) -> Option<usize> {
sks.iter().position(|schema_field| schema_field == field)
}
diff --git a/log_db/src/config.rs b/log_db/src/config.rs
index 5b3cf26..ec74164 100644
--- a/log_db/src/config.rs
+++ b/log_db/src/config.rs
@@ -6,23 +6,23 @@ pub struct Schema<F> {
pub secondary_keys: Vec<F>,
}
-pub struct ConfigBuilder<T, F> {
+pub struct ConfigBuilder<T> {
data_dir: Option<String>,
segment_size: Option<usize>,
write_durability: Option<WriteDurability>,
read_consistency: Option<ReadConsistency>,
- fields: Option<Vec<F>>,
- primary_key: Option<F>,
- secondary_keys: Option<Vec<F>>,
+ fields: Option<Vec<String>>,
+ primary_key: Option<String>,
+ secondary_keys: Option<Vec<String>>,
from_record: Option<fn(Vec<Value>) -> T>,
into_record: Option<fn(T) -> Vec<Value>>,
_marker: PhantomData<T>,
}
-impl<T, F: Eq + Clone> ConfigBuilder<T, F> {
- pub fn new() -> ConfigBuilder<T, F> {
+impl<T> ConfigBuilder<T> {
+ pub fn new() -> ConfigBuilder<T> {
ConfigBuilder {
data_dir: None,
segment_size: None,
@@ -71,18 +71,18 @@ impl<T, F: Eq + Clone> ConfigBuilder<T, F> {
self
}
- pub fn fields(mut self, schema: Vec<F>) -> Self {
- self.fields = Some(schema);
+ pub fn fields(mut self, schema: Vec<impl Into<String>>) -> Self {
+ self.fields = Some(schema.into_iter().map(|s| s.into()).collect());
self
}
- pub fn primary_key(mut self, primary_key: F) -> Self {
- self.primary_key = Some(primary_key);
+ pub fn primary_key(mut self, primary_key: impl Into<String>) -> Self {
+ self.primary_key = Some(primary_key.into());
self
}
- pub fn secondary_keys(mut self, secondary_keys: Vec<F>) -> Self {
- self.secondary_keys = Some(secondary_keys);
+ pub fn secondary_keys(mut self, secondary_keys: Vec<impl Into<String>>) -> Self {
+ self.secondary_keys = Some(secondary_keys.into_iter().map(|s| s.into()).collect());
self
}
@@ -96,7 +96,7 @@ impl<T, F: Eq + Clone> ConfigBuilder<T, F> {
self
}
- pub fn initialize(self) -> DBResult<DB<T, F>> {
+ pub fn initialize(self) -> DBResult<DB<T>> {
let schema = self
.fields
.ok_or_else(|| DBError::ValidationError("Schema not set".to_string()))?;
@@ -134,10 +134,10 @@ impl<T, F: Eq + Clone> ConfigBuilder<T, F> {
}
#[derive(Clone)]
-pub struct Config<T, F> {
- pub schema: Vec<F>,
- pub primary_key: F,
- pub secondary_keys: Vec<F>,
+pub struct Config<T> {
+ pub schema: Vec<String>,
+ pub primary_key: String,
+ pub secondary_keys: Vec<String>,
pub from_record: fn(Vec<Value>) -> T,
pub into_record: fn(T) -> Vec<Value>,
pub data_dir: String,
diff --git a/log_db/src/engine.rs b/log_db/src/engine.rs
index c2f9a52..b06bfd2 100644
--- a/log_db/src/engine.rs
+++ b/log_db/src/engine.rs
@@ -1,7 +1,7 @@
use super::*;
-pub struct Engine<T, F: Eq + Clone> {
- pub config: Config<T, F>,
+pub struct Engine<T> {
+ pub config: Config<T>,
pub lock_manager: LockManager,
data_dir_path: PathBuf,
@@ -19,8 +19,8 @@ pub struct Engine<T, F: Eq + Clone> {
pub secondary_memtables: Vec<SecondaryMemtable>,
}
-impl<T, F: Eq + Clone> Engine<T, F> {
- pub fn initialize(config: Config<T, F>) -> DBResult<Engine<T, F>> {
+impl<T> Engine<T> {
+ pub fn initialize(config: Config<T>) -> DBResult<Engine<T>> {
info!("Initializing DB...");
// If data_dir does not exist or is empty, create it and any necessary files.
// After creation, the directory should always be in a complete state without missing files.
@@ -104,7 +104,7 @@ impl<T, F: Eq + Clone> Engine<T, F> {
Path::new(&config.data_dir).join(active_metadata_header.uuid.to_string());
let active_data_file = APPEND_MODE.open(&active_data_path)?;
- let mut engine = Engine::<T, F> {
+ let mut engine = Engine::<T> {
config,
lock_manager,
data_dir_path,
@@ -247,7 +247,7 @@ impl<T, F: Eq + Clone> Engine<T, F> {
pub fn batch_find_by_records<'a>(
&mut self,
- field: &F,
+ field: &str,
values: impl Iterator<Item = &'a Value>,
params: &QueryParams,
) -> DBResult<Vec<(usize, Record)>> {
@@ -378,7 +378,7 @@ impl<T, F: Eq + Clone> Engine<T, F> {
pub fn range_by_records<B: RangeBounds<Value>>(
&mut self,
- field: &F,
+ field: &str,
range: B,
params: &QueryParams,
) -> DBResult<Vec<Record>> {
@@ -458,7 +458,7 @@ impl<T, F: Eq + Clone> Engine<T, F> {
}
}
- pub fn delete_by_field(&mut self, field: &F, value: &Value) -> DBResult<Vec<Record>> {
+ pub fn delete_by_field(&mut self, field: &str, value: &Value) -> DBResult<Vec<Record>> {
let recs: Vec<Record> = self
.batch_find_by_records(field, std::iter::once(value), &DEFAULT_QUERY_PARAMS)?
.into_iter()
@@ -737,6 +737,15 @@ mod tests {
Name,
}
+ impl Into<String> for Field {
+ fn into(self) -> String {
+ match self {
+ Field::Id => "id".to_owned(),
+ Field::Name => "name".to_owned(),
+ }
+ }
+ }
+
#[derive(PartialEq, Eq, Debug, Clone)]
struct TestInst2 {
id: i64,
diff --git a/log_db/src/lib.rs b/log_db/src/lib.rs
index 753e41c..fddb344 100644
--- a/log_db/src/lib.rs
+++ b/log_db/src/lib.rs
@@ -37,17 +37,17 @@ use memtable_primary::PrimaryMemtable;
use memtable_secondary::SecondaryMemtable;
use record::*;
-pub struct DB<T, F: Eq + Clone> {
- engine: Engine<T, F>,
+pub struct DB<T> {
+ engine: Engine<T>,
}
-impl<T, F: Eq + Clone> DB<T, F> {
+impl<T> DB<T> {
/// Create a new database configuration builder.
- pub fn configure() -> ConfigBuilder<T, F> {
+ pub fn configure() -> ConfigBuilder<T> {
ConfigBuilder::new()
}
- fn initialize(config: Config<T, F>) -> DBResult<DB<T, F>> {
+ fn initialize(config: Config<T>) -> DBResult<DB<T>> {
let engine = Engine::initialize(config)?;
Ok(DB { engine })
}
@@ -85,9 +85,13 @@ impl<T, F: Eq + Clone> DB<T, F> {
}
/// Get a collection of records based on an indexed field value.
- pub fn find_by(&mut self, field: &F, value: &Value) -> DBResult<Vec<T>> {
+ pub fn find_by(&mut self, field: impl AsRef<str>, value: &Value) -> DBResult<Vec<T>> {
let recs = self.engine.with_shared_lock(|engine| {
- engine.batch_find_by_records(field, std::iter::once(value), &DEFAULT_QUERY_PARAMS)
+ engine.batch_find_by_records(
+ field.as_ref(),
+ std::iter::once(value),
+ &DEFAULT_QUERY_PARAMS,
+ )
})?;
Ok(recs
@@ -99,12 +103,12 @@ impl<T, F: Eq + Clone> DB<T, F> {
/// Get a collection of records based on an indexed field value, with additional parameters.
pub fn find_by_with_params(
&mut self,
- field: &F,
+ field: impl AsRef<str>,
value: &Value,
params: &QueryParams,
) -> DBResult<Vec<T>> {
let recs = self.engine.with_shared_lock(|engine| {
- engine.batch_find_by_records(field, std::iter::once(value), params)
+ engine.batch_find_by_records(field.as_ref(), std::iter::once(value), params)
})?;
Ok(recs
@@ -116,9 +120,13 @@ impl<T, F: Eq + Clone> DB<T, F> {
/// Get a collection of records based on a sequence of indexed field values.
/// Returns a vector of pairs where the first value is an index into the given sequence of values,
/// and the second value is the record.
- pub fn batch_find_by(&mut self, field: &F, values: &[Value]) -> DBResult<Vec<(usize, T)>> {
+ pub fn batch_find_by(
+ &mut self,
+ field: impl Into<String>,
+ values: &[Value],
+ ) -> DBResult<Vec<(usize, T)>> {
let recs = self.engine.with_shared_lock(|engine| {
- engine.batch_find_by_records(field, values.iter(), &DEFAULT_QUERY_PARAMS)
+ engine.batch_find_by_records(&field.into(), values.iter(), &DEFAULT_QUERY_PARAMS)
})?;
Ok(recs
@@ -132,12 +140,12 @@ impl<T, F: Eq + Clone> DB<T, F> {
/// and the second value is the record.
pub fn batch_find_by_with_params(
&mut self,
- field: &F,
+ field: impl AsRef<str>,
values: &[Value],
params: &QueryParams,
) -> DBResult<Vec<(usize, T)>> {
let recs = self.engine.with_shared_lock(|engine| {
- engine.batch_find_by_records(field, values.iter(), params)
+ engine.batch_find_by_records(field.as_ref(), values.iter(), params)
})?;
Ok(recs
@@ -149,9 +157,13 @@ impl<T, F: Eq + Clone> DB<T, F> {
/// Get a collection of records based on a range of indexed field values.
/// This method can be used to run comparison-like queries, e.g. `field >= 10`
/// could be expressed as `db.range_by(Field::Id, 10..)`.
- pub fn range_by<B: RangeBounds<Value>>(&mut self, field: &F, range: B) -> DBResult<Vec<T>> {
+ pub fn range_by<B: RangeBounds<Value>>(
+ &mut self,
+ field: impl AsRef<str>,
+ range: B,
+ ) -> DBResult<Vec<T>> {
let recs = self.engine.with_shared_lock(|engine| {
- engine.range_by_records(field, range, &DEFAULT_QUERY_PARAMS)
+ engine.range_by_records(field.as_ref(), range, &DEFAULT_QUERY_PARAMS)
})?;
Ok(recs
@@ -165,13 +177,13 @@ impl<T, F: Eq + Clone> DB<T, F> {
/// could be expressed as `db.range_by(Field::Id, 10..)`.
pub fn range_by_with_params<B: RangeBounds<Value>>(
&mut self,
- field: &F,
+ field: impl AsRef<str>,
range: B,
params: &QueryParams,
) -> DBResult<Vec<T>> {
let recs = self
.engine
- .with_shared_lock(|engine| engine.range_by_records(field, range, params))?;
+ .with_shared_lock(|engine| engine.range_by_records(field.as_ref(), range, params))?;
Ok(recs
.into_iter()
@@ -185,10 +197,10 @@ impl<T, F: Eq + Clone> DB<T, F> {
///
/// Deletion is done by marking the record as a tombstone. The record will still be present in the log file,
/// but will be ignored by reads. Upon compaction, tombstoned records will be removed.
- pub fn delete_by(&mut self, field: &F, value: &Value) -> DBResult<Vec<T>> {
+ pub fn delete_by(&mut self, field: impl AsRef<str>, value: &Value) -> DBResult<Vec<T>> {
let recs = self
.engine
- .with_exclusive_lock(|engine| engine.delete_by_field(field, value))?;
+ .with_exclusive_lock(|engine| engine.delete_by_field(field.as_ref(), value))?;
Ok(recs
.into_iter()
@@ -295,6 +307,15 @@ mod tests {
Name,
}
+ impl Into<String> for Field {
+ fn into(self) -> String {
+ match self {
+ Field::Id => "id".to_string(),
+ Field::Name => "name".to_string(),
+ }
+ }
+ }
+
struct TestInst1 {
id: i64,
}