diff --git a/lib/src/dbs/channel.rs b/lib/src/dbs/channel.rs index 45b1cdd6..b1001bc1 100644 --- a/lib/src/dbs/channel.rs +++ b/lib/src/dbs/channel.rs @@ -1,16 +1,15 @@ -use crate::cnf::ID_CHARS; use crate::dbs::Options; use crate::dbs::Runtime; use crate::dbs::Transaction; use crate::err::Error; use crate::key::thing; use crate::sql::array::Array; +use crate::sql::id::Id; use crate::sql::model::Model; use crate::sql::table::Table; use crate::sql::thing::Thing; use crate::sql::value::Value; use async_recursion::async_recursion; -use nanoid::nanoid; use tokio::sync::mpsc::Sender; impl Value { @@ -71,7 +70,7 @@ impl Model { for _ in 0..c { Thing { tb: self.table.to_string(), - id: nanoid!(20, &ID_CHARS), + id: Id::rand(), } .process(ctx, opt, txn, chn) .await?; @@ -81,7 +80,7 @@ impl Model { for x in r.0..=r.1 { Thing { tb: self.table.to_string(), - id: x.to_string(), + id: Id::from(x), } .process(ctx, opt, txn, chn) .await?; diff --git a/lib/src/dbs/iterate.rs b/lib/src/dbs/iterate.rs index 70993fac..a4afa641 100644 --- a/lib/src/dbs/iterate.rs +++ b/lib/src/dbs/iterate.rs @@ -1,4 +1,3 @@ -use crate::cnf::ID_CHARS; use crate::dbs::Iterator; use crate::dbs::Options; use crate::dbs::Runtime; @@ -6,12 +5,12 @@ use crate::dbs::Transaction; use crate::err::Error; use crate::key::thing; use crate::sql::array::Array; +use crate::sql::id::Id; use crate::sql::model::Model; use crate::sql::table::Table; use crate::sql::thing::Thing; use crate::sql::value::Value; use async_recursion::async_recursion; -use nanoid::nanoid; impl Value { #[cfg_attr(feature = "parallel", async_recursion)] @@ -74,7 +73,7 @@ impl Model { for _ in 0..c { Thing { tb: self.table.to_string(), - id: nanoid!(20, &ID_CHARS), + id: Id::rand(), } .iterate(ctx, opt, txn, ite) .await?; @@ -84,7 +83,7 @@ impl Model { for x in r.0..=r.1 { Thing { tb: self.table.to_string(), - id: x.to_string(), + id: Id::from(x), } .iterate(ctx, opt, txn, ite) .await?; diff --git a/lib/src/dbs/iterator.rs b/lib/src/dbs/iterator.rs index f79787cb..5b04cada 100644 --- a/lib/src/dbs/iterator.rs +++ b/lib/src/dbs/iterator.rs @@ -1,4 +1,3 @@ -use crate::cnf::ID_CHARS; use crate::cnf::MAX_CONCURRENT_TASKS; use crate::ctx::Canceller; use crate::ctx::Context; @@ -8,6 +7,7 @@ use crate::dbs::Statement; use crate::dbs::Transaction; use crate::doc::Document; use crate::err::Error; +use crate::sql::id::Id; use crate::sql::statements::create::CreateStatement; use crate::sql::statements::delete::DeleteStatement; use crate::sql::statements::insert::InsertStatement; @@ -17,7 +17,6 @@ use crate::sql::statements::update::UpdateStatement; use crate::sql::table::Table; use crate::sql::thing::Thing; use crate::sql::value::Value; -use nanoid::nanoid; use std::mem; use std::sync::Arc; @@ -107,7 +106,7 @@ impl Iterator { pub fn produce(&mut self, val: Table) { self.prepare(Value::Thing(Thing { tb: val.name, - id: nanoid!(20, &ID_CHARS), + id: Id::rand(), })) } diff --git a/lib/src/fnc/type.rs b/lib/src/fnc/type.rs index f06bcebd..87f0283b 100644 --- a/lib/src/fnc/type.rs +++ b/lib/src/fnc/type.rs @@ -107,7 +107,7 @@ pub fn thing(_: &Runtime, mut args: Vec) -> Result { })), id => Ok(Value::Thing(Thing { tb: tb.as_strand().value, - id: id.as_strand().value, + id: id.as_strand().into(), })), } } diff --git a/lib/src/key/thing.rs b/lib/src/key/thing.rs index 0f76322f..fa3d44d4 100644 --- a/lib/src/key/thing.rs +++ b/lib/src/key/thing.rs @@ -1,4 +1,5 @@ use crate::err::Error; +use crate::sql::id::Id; use serde::{Deserialize, Serialize}; use storekey::{deserialize, serialize}; @@ -12,7 +13,7 @@ pub struct Thing { _c: u8, pub tb: String, _d: u8, - pub id: String, + pub id: Id, } impl From for Vec { @@ -33,8 +34,8 @@ impl From<&Vec> for Thing { } } -pub fn new(ns: &str, db: &str, tb: &str, id: &str) -> Thing { - Thing::new(ns.to_string(), db.to_string(), tb.to_string(), id.to_string()) +pub fn new(ns: &str, db: &str, tb: &str, id: &Id) -> Thing { + Thing::new(ns.to_string(), db.to_string(), tb.to_string(), id.to_owned()) } pub fn prefix(ns: &str, db: &str, tb: &str) -> Vec { @@ -50,7 +51,7 @@ pub fn suffix(ns: &str, db: &str, tb: &str) -> Vec { } impl Thing { - pub fn new(ns: String, db: String, tb: String, id: String) -> Thing { + pub fn new(ns: String, db: String, tb: String, id: Id) -> Thing { Thing { __: 0x2f, // / _a: 0x2a, // * diff --git a/lib/src/sql/id.rs b/lib/src/sql/id.rs new file mode 100644 index 00000000..fcb56870 --- /dev/null +++ b/lib/src/sql/id.rs @@ -0,0 +1,100 @@ +use crate::cnf::ID_CHARS; +use crate::sql::common::escape; +use crate::sql::common::val_char; +use crate::sql::error::IResult; +use crate::sql::ident::ident_raw; +use crate::sql::number::{number, Number}; +use crate::sql::strand::Strand; +use nanoid::nanoid; +use nom::branch::alt; +use nom::combinator::map; +use serde::{Deserialize, Serialize}; +use std::fmt; + +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize)] +pub enum Id { + Number(Number), + String(String), +} + +impl From for Id { + fn from(v: Number) -> Self { + Id::Number(v) + } +} + +impl From for Id { + fn from(v: String) -> Self { + Id::String(v) + } +} + +impl From for Id { + fn from(v: Strand) -> Self { + Id::String(v.value) + } +} + +impl From<&str> for Id { + fn from(v: &str) -> Self { + Id::String(v.to_owned()) + } +} + +impl From for Id { + fn from(v: u64) -> Self { + Id::Number(Number::from(v)) + } +} + +impl Id { + pub fn rand() -> Id { + Id::String(nanoid!(20, &ID_CHARS)) + } +} + +impl fmt::Display for Id { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self { + Id::Number(v) => write!(f, "{}", v), + Id::String(v) => write!(f, "{}", escape(&v, &val_char, "`")), + } + } +} + +pub fn id(i: &str) -> IResult<&str, Id> { + alt((map(number, Id::Number), map(ident_raw, Id::String)))(i) +} + +#[cfg(test)] +mod tests { + + use super::*; + + #[test] + fn id_number() { + let sql = "100"; + let res = id(sql); + assert!(res.is_ok()); + let out = res.unwrap().1; + assert_eq!(Id::from(100), out); + } + + #[test] + fn id_string() { + let sql = "test"; + let res = id(sql); + assert!(res.is_ok()); + let out = res.unwrap().1; + assert_eq!(Id::from("test"), out); + } + + #[test] + fn id_either() { + let sql = "100test"; + let res = id(sql); + assert!(res.is_ok()); + let out = res.unwrap().1; + assert_eq!(Id::from("100test"), out); + } +} diff --git a/lib/src/sql/mod.rs b/lib/src/sql/mod.rs index df4a74e4..4aac0024 100644 --- a/lib/src/sql/mod.rs +++ b/lib/src/sql/mod.rs @@ -15,6 +15,7 @@ pub(crate) mod function; pub(crate) mod geometry; pub(crate) mod graph; pub(crate) mod group; +pub(crate) mod id; pub(crate) mod ident; pub(crate) mod idiom; pub(crate) mod kind; @@ -70,6 +71,7 @@ pub use self::geometry::Geometry; pub use self::graph::Graph; pub use self::group::Group; pub use self::group::Groups; +pub use self::id::Id; pub use self::ident::Ident; pub use self::idiom::Idiom; pub use self::idiom::Idioms; diff --git a/lib/src/sql/thing.rs b/lib/src/sql/thing.rs index 23275f12..cf28153b 100644 --- a/lib/src/sql/thing.rs +++ b/lib/src/sql/thing.rs @@ -1,20 +1,22 @@ use crate::sql::common::escape; use crate::sql::common::val_char; use crate::sql::error::IResult; +use crate::sql::id::{id, Id}; use crate::sql::ident::ident_raw; +use crate::sql::number::Number; use nom::character::complete::char; use serde::ser::SerializeStruct; use serde::{Deserialize, Serialize}; use std::fmt; -#[derive(Clone, Debug, Default, Eq, PartialEq, PartialOrd, Deserialize)] +#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Deserialize)] pub struct Thing { pub tb: String, - pub id: String, + pub id: Id, } -impl From<(String, String)> for Thing { - fn from(v: (String, String)) -> Self { +impl From<(String, Id)> for Thing { + fn from(v: (String, Id)) -> Self { Thing { tb: v.0, id: v.1, @@ -22,11 +24,28 @@ impl From<(String, String)> for Thing { } } +impl From<(String, String)> for Thing { + fn from(v: (String, String)) -> Self { + Thing { + tb: v.0, + id: Id::from(v.1), + } + } +} + +impl From<(String, Number)> for Thing { + fn from(v: (String, Number)) -> Self { + Thing { + tb: v.0, + id: Id::from(v.1), + } + } +} + impl fmt::Display for Thing { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { let t = escape(&self.tb, &val_char, "`"); - let i = escape(&self.id, &val_char, "`"); - write!(f, "{}:{}", t, i) + write!(f, "{}:{}", t, self.id) } } @@ -50,7 +69,7 @@ impl Serialize for Thing { pub fn thing(i: &str) -> IResult<&str, Thing> { let (i, t) = ident_raw(i)?; let (i, _) = char(':')(i)?; - let (i, v) = ident_raw(i)?; + let (i, v) = id(i)?; Ok(( i, Thing { @@ -76,7 +95,7 @@ mod tests { out, Thing { tb: String::from("test"), - id: String::from("id"), + id: Id::from("id"), } ); } @@ -92,7 +111,7 @@ mod tests { out, Thing { tb: String::from("test"), - id: String::from("id"), + id: Id::from("id"), } ); } @@ -108,7 +127,7 @@ mod tests { out, Thing { tb: String::from("test"), - id: String::from("id"), + id: Id::from("id"), } ); } diff --git a/lib/src/sql/value/get.rs b/lib/src/sql/value/get.rs index 11bbc627..f6b6c3b3 100644 --- a/lib/src/sql/value/get.rs +++ b/lib/src/sql/value/get.rs @@ -100,6 +100,7 @@ mod tests { use super::*; use crate::dbs::test::mock; + use crate::sql::id::Id; use crate::sql::idiom::Idiom; use crate::sql::test::Parse; use crate::sql::thing::Thing; @@ -132,7 +133,7 @@ mod tests { res, Value::from(Thing { tb: String::from("test"), - id: String::from("tobie") + id: Id::from("tobie") }) ); } @@ -156,7 +157,7 @@ mod tests { res, Value::from(Thing { tb: String::from("test"), - id: String::from("jaime") + id: Id::from("jaime") }) ); } diff --git a/lib/src/sql/value/value.rs b/lib/src/sql/value/value.rs index 2d06086a..e589a1a0 100644 --- a/lib/src/sql/value/value.rs +++ b/lib/src/sql/value/value.rs @@ -10,6 +10,7 @@ use crate::sql::error::IResult; use crate::sql::expression::{expression, Expression}; use crate::sql::function::{function, Function}; use crate::sql::geometry::{geometry, Geometry}; +use crate::sql::id::Id; use crate::sql::idiom::{idiom, Idiom}; use crate::sql::model::{model, Model}; use crate::sql::number::{number, Number}; @@ -387,6 +388,15 @@ impl From> for Value { } } +impl From for Value { + fn from(v: Id) -> Self { + match v { + Id::String(v) => Strand::from(v).into(), + Id::Number(v) => Number::from(v).into(), + } + } +} + impl Value { // ----------------------------------- // Initial record value