Skip to content

Commit

Permalink
Add support for Record ID ranges
Browse files Browse the repository at this point in the history
Closes #66
  • Loading branch information
tobiemh committed Aug 28, 2022
1 parent e26d86b commit c1a1eba
Show file tree
Hide file tree
Showing 9 changed files with 206 additions and 4 deletions.
60 changes: 60 additions & 0 deletions lib/src/dbs/channel.rs
Expand Up @@ -135,6 +135,66 @@ impl Iterable {
break;
}
}
Iterable::Range(v) => {
// Check that the table exists
txn.lock().await.check_ns_db_tb(opt.ns(), opt.db(), &v.tb, opt.strict).await?;
// Prepare the start and end keys
let beg = thing::new(opt.ns(), opt.db(), &v.tb, &v.beg).encode().unwrap();
let end = thing::new(opt.ns(), opt.db(), &v.tb, &v.end).encode().unwrap();
// Prepare the next holder key
let mut nxt: Option<Vec<u8>> = None;
// Loop until no more keys
loop {
// Check if the context is finished
if ctx.is_done() {
break;
}
// Get the next 1000 key-value entries
let res = match nxt {
None => {
let min = beg.clone();
let max = end.clone();
txn.clone().lock().await.scan(min..max, 1000).await?
}
Some(ref mut beg) => {
beg.push(0x00);
let min = beg.clone();
let max = end.clone();
txn.clone().lock().await.scan(min..max, 1000).await?
}
};
// If there are key-value entries then fetch them
if !res.is_empty() {
// Get total results
let n = res.len();
// Exit when settled
if n == 0 {
break;
}
// Loop over results
for (i, (k, v)) in res.into_iter().enumerate() {
// Check the context
if ctx.is_done() {
break;
}
// Ready the next
if n == i + 1 {
nxt = Some(k.clone());
}
// Parse the data from the store
let key: crate::key::thing::Thing = (&k).into();
let val: crate::sql::value::Value = (&v).into();
let rid = Thing::from((key.tb, key.id));
// Create a new operable value
let val = Operable::Value(val);
// Process the record
chn.send((Some(rid), val)).await?;
}
continue;
}
break;
}
}
Iterable::Edges(e) => {
// Pull out options
let ns = opt.ns();
Expand Down
60 changes: 60 additions & 0 deletions lib/src/dbs/iterate.rs
Expand Up @@ -135,6 +135,66 @@ impl Iterable {
break;
}
}
Iterable::Range(v) => {
// Check that the table exists
txn.lock().await.check_ns_db_tb(opt.ns(), opt.db(), &v.tb, opt.strict).await?;
// Prepare the start and end keys
let beg = thing::new(opt.ns(), opt.db(), &v.tb, &v.beg).encode().unwrap();
let end = thing::new(opt.ns(), opt.db(), &v.tb, &v.end).encode().unwrap();
// Prepare the next holder key
let mut nxt: Option<Vec<u8>> = None;
// Loop until no more keys
loop {
// Check if the context is finished
if ctx.is_done() {
break;
}
// Get the next 1000 key-value entries
let res = match nxt {
None => {
let min = beg.clone();
let max = end.clone();
txn.clone().lock().await.scan(min..max, 1000).await?
}
Some(ref mut beg) => {
beg.push(0x00);
let min = beg.clone();
let max = end.clone();
txn.clone().lock().await.scan(min..max, 1000).await?
}
};
// If there are key-value entries then fetch them
if !res.is_empty() {
// Get total results
let n = res.len();
// Exit when settled
if n == 0 {
break;
}
// Loop over results
for (i, (k, v)) in res.into_iter().enumerate() {
// Check the context
if ctx.is_done() {
break;
}
// Ready the next
if n == i + 1 {
nxt = Some(k.clone());
}
// Parse the data from the store
let key: crate::key::thing::Thing = (&k).into();
let val: crate::sql::value::Value = (&v).into();
let rid = Thing::from((key.tb, key.id));
// Create a new operable value
let val = Operable::Value(val);
// Process the record
ite.process(ctx, opt, txn, stm, Some(rid), val).await;
}
continue;
}
break;
}
}
Iterable::Edges(e) => {
// Pull out options
let ns = opt.ns();
Expand Down
2 changes: 2 additions & 0 deletions lib/src/dbs/iterator.rs
Expand Up @@ -10,6 +10,7 @@ use crate::sql::array::Array;
use crate::sql::edges::Edges;
use crate::sql::field::Field;
use crate::sql::part::Part;
use crate::sql::range::Range;
use crate::sql::table::Table;
use crate::sql::thing::Thing;
use crate::sql::value::Value;
Expand All @@ -22,6 +23,7 @@ pub enum Iterable {
Value(Value),
Table(Table),
Thing(Thing),
Range(Range),
Edges(Edges),
Mergeable(Thing, Value),
Relatable(Thing, Thing, Thing),
Expand Down
2 changes: 2 additions & 0 deletions lib/src/sql/mod.rs
Expand Up @@ -37,6 +37,7 @@ pub(crate) mod part;
pub(crate) mod paths;
pub(crate) mod permission;
pub(crate) mod query;
pub(crate) mod range;
pub(crate) mod regex;
pub(crate) mod script;
pub(crate) mod serde;
Expand Down Expand Up @@ -100,6 +101,7 @@ pub use self::part::Part;
pub use self::permission::Permission;
pub use self::permission::Permissions;
pub use self::query::Query;
pub use self::range::Range;
pub use self::regex::Regex;
pub use self::script::Script;
pub use self::split::Split;
Expand Down
62 changes: 62 additions & 0 deletions lib/src/sql/range.rs
@@ -0,0 +1,62 @@
use crate::sql::error::IResult;
use crate::sql::id::{id, Id};
use crate::sql::ident::ident_raw;
use nom::character::complete::char;
use serde::{Deserialize, Serialize};
use std::fmt;

#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize)]
pub struct Range {
pub tb: String,
pub beg: Id,
pub end: Id,
}

impl fmt::Display for Range {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}:{}..{}", self.tb, self.beg, self.end)
}
}

pub fn range(i: &str) -> IResult<&str, Range> {
let (i, tb) = ident_raw(i)?;
let (i, _) = char(':')(i)?;
let (i, beg) = id(i)?;
let (i, _) = char('.')(i)?;
let (i, _) = char('.')(i)?;
let (i, end) = id(i)?;
Ok((
i,
Range {
tb,
beg,
end,
},
))
}
#[cfg(test)]
mod tests {

use super::*;

#[test]
fn range_array() {
let sql = "person:['USA', 10]..['USA', 100]";
let res = range(sql);
assert!(res.is_ok());
let out = res.unwrap().1;
assert_eq!(r#"person:["USA", 10]..["USA", 100]"#, format!("{}", out));
}

#[test]
fn range_object() {
let sql = "person:{ country: 'USA', position: 10 }..{ country: 'USA', position: 100 }";
let res = range(sql);
assert!(res.is_ok());
let out = res.unwrap().1;
assert_eq!(
r#"person:{ country: "USA", position: 10 }..{ country: "USA", position: 100 }"#,
format!("{}", out)
);
}
}
1 change: 1 addition & 0 deletions lib/src/sql/statements/delete.rs
Expand Up @@ -55,6 +55,7 @@ impl DeleteStatement {
match v {
Value::Table(v) => i.ingest(Iterable::Table(v)),
Value::Thing(v) => i.ingest(Iterable::Thing(v)),
Value::Range(v) => i.ingest(Iterable::Range(*v)),
Value::Edges(v) => i.ingest(Iterable::Edges(*v)),
Value::Model(v) => {
for v in v {
Expand Down
1 change: 1 addition & 0 deletions lib/src/sql/statements/select.rs
Expand Up @@ -94,6 +94,7 @@ impl SelectStatement {
match v {
Value::Table(v) => i.ingest(Iterable::Table(v)),
Value::Thing(v) => i.ingest(Iterable::Thing(v)),
Value::Range(v) => i.ingest(Iterable::Range(*v)),
Value::Edges(v) => i.ingest(Iterable::Edges(*v)),
Value::Model(v) => {
for v in v {
Expand Down
1 change: 1 addition & 0 deletions lib/src/sql/statements/update.rs
Expand Up @@ -56,6 +56,7 @@ impl UpdateStatement {
match v {
Value::Table(v) => i.ingest(Iterable::Table(v)),
Value::Thing(v) => i.ingest(Iterable::Thing(v)),
Value::Range(v) => i.ingest(Iterable::Range(*v)),
Value::Edges(v) => i.ingest(Iterable::Edges(*v)),
Value::Model(v) => {
for v in v {
Expand Down
21 changes: 17 additions & 4 deletions lib/src/sql/value/value.rs
Expand Up @@ -23,6 +23,7 @@ use crate::sql::object::{object, Object};
use crate::sql::operation::Operation;
use crate::sql::param::{param, Param};
use crate::sql::part::Part;
use crate::sql::range::{range, Range};
use crate::sql::regex::{regex, Regex};
use crate::sql::serde::is_internal_serialization;
use crate::sql::strand::{strand, Strand};
Expand Down Expand Up @@ -114,6 +115,7 @@ pub enum Value {
Thing(Thing),
Model(Model),
Regex(Regex),
Range(Box<Range>),
Edges(Box<Edges>),
Function(Box<Function>),
Subquery(Box<Subquery>),
Expand Down Expand Up @@ -227,6 +229,12 @@ impl From<Duration> for Value {
}
}

impl From<Range> for Value {
fn from(v: Range) -> Self {
Value::Range(Box::new(v))
}
}

impl From<Edges> for Value {
fn from(v: Edges) -> Self {
Value::Edges(Box::new(v))
Expand Down Expand Up @@ -1071,6 +1079,7 @@ impl fmt::Display for Value {
Value::Thing(v) => write!(f, "{}", v),
Value::Model(v) => write!(f, "{}", v),
Value::Regex(v) => write!(f, "{}", v),
Value::Range(v) => write!(f, "{}", v),
Value::Edges(v) => write!(f, "{}", v),
Value::Function(v) => write!(f, "{}", v),
Value::Subquery(v) => write!(f, "{}", v),
Expand Down Expand Up @@ -1142,10 +1151,11 @@ impl Serialize for Value {
Value::Thing(v) => s.serialize_newtype_variant("Value", 15, "Thing", v),
Value::Model(v) => s.serialize_newtype_variant("Value", 16, "Model", v),
Value::Regex(v) => s.serialize_newtype_variant("Value", 17, "Regex", v),
Value::Edges(v) => s.serialize_newtype_variant("Value", 18, "Edges", v),
Value::Function(v) => s.serialize_newtype_variant("Value", 19, "Function", v),
Value::Subquery(v) => s.serialize_newtype_variant("Value", 20, "Subquery", v),
Value::Expression(v) => s.serialize_newtype_variant("Value", 21, "Expression", v),
Value::Range(v) => s.serialize_newtype_variant("Value", 18, "Range", v),
Value::Edges(v) => s.serialize_newtype_variant("Value", 19, "Edges", v),
Value::Function(v) => s.serialize_newtype_variant("Value", 20, "Function", v),
Value::Subquery(v) => s.serialize_newtype_variant("Value", 21, "Subquery", v),
Value::Expression(v) => s.serialize_newtype_variant("Value", 22, "Expression", v),
}
} else {
match self {
Expand Down Expand Up @@ -1275,6 +1285,7 @@ pub fn select(i: &str) -> IResult<&str, Value> {
map(regex, Value::from),
map(model, Value::from),
map(edges, Value::from),
map(range, Value::from),
map(thing, Value::from),
map(table, Value::from),
map(strand, Value::from),
Expand All @@ -1289,6 +1300,7 @@ pub fn what(i: &str) -> IResult<&str, Value> {
map(param, Value::from),
map(model, Value::from),
map(edges, Value::from),
map(range, Value::from),
map(thing, Value::from),
map(table, Value::from),
))(i)
Expand Down Expand Up @@ -1472,6 +1484,7 @@ mod tests {
assert_eq!(56, std::mem::size_of::<crate::sql::thing::Thing>());
assert_eq!(48, std::mem::size_of::<crate::sql::model::Model>());
assert_eq!(24, std::mem::size_of::<crate::sql::regex::Regex>());
assert_eq!(8, std::mem::size_of::<Box<crate::sql::range::Range>>());
assert_eq!(8, std::mem::size_of::<Box<crate::sql::edges::Edges>>());
assert_eq!(8, std::mem::size_of::<Box<crate::sql::function::Function>>());
assert_eq!(8, std::mem::size_of::<Box<crate::sql::subquery::Subquery>>());
Expand Down

0 comments on commit c1a1eba

Please sign in to comment.