Enable support for numbers and strings in record ids
This commit is contained in:
parent
364412b437
commit
24752a75d9
10 changed files with 158 additions and 28 deletions
|
@ -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?;
|
||||
|
|
|
@ -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?;
|
||||
|
|
|
@ -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(),
|
||||
}))
|
||||
}
|
||||
|
||||
|
|
|
@ -107,7 +107,7 @@ pub fn thing(_: &Runtime, mut args: Vec<Value>) -> Result<Value, Error> {
|
|||
})),
|
||||
id => Ok(Value::Thing(Thing {
|
||||
tb: tb.as_strand().value,
|
||||
id: id.as_strand().value,
|
||||
id: id.as_strand().into(),
|
||||
})),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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<Thing> for Vec<u8> {
|
||||
|
@ -33,8 +34,8 @@ impl From<&Vec<u8>> 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<u8> {
|
||||
|
@ -50,7 +51,7 @@ pub fn suffix(ns: &str, db: &str, tb: &str) -> Vec<u8> {
|
|||
}
|
||||
|
||||
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, // *
|
||||
|
|
100
lib/src/sql/id.rs
Normal file
100
lib/src/sql/id.rs
Normal file
|
@ -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<Number> for Id {
|
||||
fn from(v: Number) -> Self {
|
||||
Id::Number(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<String> for Id {
|
||||
fn from(v: String) -> Self {
|
||||
Id::String(v)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Strand> 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<u64> 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);
|
||||
}
|
||||
}
|
|
@ -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;
|
||||
|
|
|
@ -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"),
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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")
|
||||
})
|
||||
);
|
||||
}
|
||||
|
|
|
@ -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<Option<String>> for Value {
|
|||
}
|
||||
}
|
||||
|
||||
impl From<Id> 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
|
||||
|
|
Loading…
Reference in a new issue