Enable support for numbers and strings in record ids

This commit is contained in:
Tobie Morgan Hitchcock 2022-03-18 07:24:36 +00:00
parent 364412b437
commit 24752a75d9
10 changed files with 158 additions and 28 deletions

View file

@ -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?;

View file

@ -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?;

View file

@ -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(),
}))
}

View file

@ -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(),
})),
}
}

View file

@ -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
View 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);
}
}

View file

@ -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;

View file

@ -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"),
}
);
}

View file

@ -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")
})
);
}

View file

@ -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