Only support strings or integers for Record IDs

This commit is contained in:
Tobie Morgan Hitchcock 2022-06-08 08:39:09 +01:00
parent 2c97d65e97
commit a8fa9ecfb7
5 changed files with 45 additions and 33 deletions

View file

@ -2,7 +2,7 @@ use crate::cnf::ID_CHARS;
use crate::sql::error::IResult; use crate::sql::error::IResult;
use crate::sql::escape::escape_ident; use crate::sql::escape::escape_ident;
use crate::sql::ident::ident_raw; use crate::sql::ident::ident_raw;
use crate::sql::number::{number, Number}; use crate::sql::number::integer;
use nanoid::nanoid; use nanoid::nanoid;
use nom::branch::alt; use nom::branch::alt;
use nom::combinator::map; use nom::combinator::map;
@ -11,16 +11,28 @@ use std::fmt;
#[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize)] #[derive(Clone, Debug, Eq, PartialEq, PartialOrd, Serialize, Deserialize)]
pub enum Id { pub enum Id {
Number(Number), Number(i64),
String(String), String(String),
} }
impl From<Number> for Id { impl From<i64> for Id {
fn from(v: Number) -> Self { fn from(v: i64) -> Self {
Id::Number(v) Id::Number(v)
} }
} }
impl From<i32> for Id {
fn from(v: i32) -> Self {
Id::Number(v as i64)
}
}
impl From<u64> for Id {
fn from(v: u64) -> Self {
Id::Number(v as i64)
}
}
impl From<String> for Id { impl From<String> for Id {
fn from(v: String) -> Self { fn from(v: String) -> Self {
Id::String(v) Id::String(v)
@ -33,12 +45,6 @@ impl From<&str> for Id {
} }
} }
impl From<u64> for Id {
fn from(v: u64) -> Self {
Id::Number(Number::from(v))
}
}
impl Id { impl Id {
pub fn rand() -> Id { pub fn rand() -> Id {
Id::String(nanoid!(20, &ID_CHARS)) Id::String(nanoid!(20, &ID_CHARS))
@ -55,7 +61,7 @@ impl fmt::Display for Id {
} }
pub fn id(i: &str) -> IResult<&str, Id> { pub fn id(i: &str) -> IResult<&str, Id> {
alt((map(number, Id::Number), map(ident_raw, Id::String)))(i) alt((map(integer, Id::Number), map(ident_raw, Id::String)))(i)
} }
#[cfg(test)] #[cfg(test)]

View file

@ -160,6 +160,18 @@ impl Number {
// Simple number detection // Simple number detection
// ----------------------------------- // -----------------------------------
pub fn is_int(&self) -> bool {
matches!(self, Number::Int(_))
}
pub fn is_float(&self) -> bool {
matches!(self, Number::Float(_))
}
pub fn is_decimal(&self) -> bool {
matches!(self, Number::Decimal(_))
}
pub fn is_truthy(&self) -> bool { pub fn is_truthy(&self) -> bool {
match self { match self {
Number::Int(v) => v != &0, Number::Int(v) => v != &0,
@ -492,10 +504,10 @@ impl<'a> Product<&'a Self> for Number {
} }
pub fn number(i: &str) -> IResult<&str, Number> { pub fn number(i: &str) -> IResult<&str, Number> {
alt((integer, decimal))(i) alt((map(integer, Number::from), map(decimal, Number::from)))(i)
} }
fn integer(i: &str) -> IResult<&str, Number> { pub fn integer(i: &str) -> IResult<&str, i64> {
let (i, v) = i64(i)?; let (i, v) = i64(i)?;
let (i, _) = peek(alt(( let (i, _) = peek(alt((
map(multispace1, |_| ()), map(multispace1, |_| ()),
@ -509,10 +521,10 @@ fn integer(i: &str) -> IResult<&str, Number> {
map(char(','), |_| ()), map(char(','), |_| ()),
map(eof, |_| ()), map(eof, |_| ()),
)))(i)?; )))(i)?;
Ok((i, Number::from(v))) Ok((i, v))
} }
fn decimal(i: &str) -> IResult<&str, Number> { pub fn decimal(i: &str) -> IResult<&str, &str> {
let (i, v) = recognize_float(i)?; let (i, v) = recognize_float(i)?;
let (i, _) = peek(alt(( let (i, _) = peek(alt((
map(multispace1, |_| ()), map(multispace1, |_| ()),
@ -526,7 +538,7 @@ fn decimal(i: &str) -> IResult<&str, Number> {
map(char(','), |_| ()), map(char(','), |_| ()),
map(eof, |_| ()), map(eof, |_| ()),
)))(i)?; )))(i)?;
Ok((i, Number::from(v))) Ok((i, v))
} }
#[cfg(test)] #[cfg(test)]

View file

@ -2,7 +2,6 @@ use crate::sql::error::IResult;
use crate::sql::escape::escape_ident; use crate::sql::escape::escape_ident;
use crate::sql::id::{id, Id}; use crate::sql::id::{id, Id};
use crate::sql::ident::ident_raw; use crate::sql::ident::ident_raw;
use crate::sql::number::Number;
use crate::sql::serde::is_internal_serialization; use crate::sql::serde::is_internal_serialization;
use derive::Store; use derive::Store;
use nom::character::complete::char; use nom::character::complete::char;
@ -34,15 +33,6 @@ impl From<(String, String)> for Thing {
} }
} }
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 { impl fmt::Display for Thing {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "{}:{}", escape_ident(&self.tb), self.id) write!(f, "{}:{}", escape_ident(&self.tb), self.id)

View file

@ -12,14 +12,18 @@ impl Value {
pub fn retable(&self, val: &Table) -> Result<Thing, Error> { pub fn retable(&self, val: &Table) -> Result<Thing, Error> {
// Fetch the id from the document // Fetch the id from the document
let id = match self.pick(&*ID) { let id = match self.pick(&*ID) {
Value::Number(id) if id.is_float() => Thing {
tb: val.to_string(),
id: Id::Number(id.as_int()),
},
Value::Number(id) if id.is_int() => Thing {
tb: val.to_string(),
id: Id::Number(id.as_int()),
},
Value::Strand(id) => Thing { Value::Strand(id) => Thing {
tb: val.to_string(), tb: val.to_string(),
id: Id::String(id.0), id: Id::String(id.0),
}, },
Value::Number(id) => Thing {
tb: val.to_string(),
id: Id::Number(id),
},
Value::Thing(id) => Thing { Value::Thing(id) => Thing {
tb: val.to_string(), tb: val.to_string(),
id: id.id, id: id.id,

View file

@ -1352,7 +1352,8 @@ mod tests {
#[test] #[test]
fn check_size() { fn check_size() {
assert_eq!(88, std::mem::size_of::<Value>()); assert_eq!(64, std::mem::size_of::<Value>());
assert_eq!(88, std::mem::size_of::<Result<Value, Error>>());
assert_eq!(48, std::mem::size_of::<crate::sql::number::Number>()); assert_eq!(48, std::mem::size_of::<crate::sql::number::Number>());
assert_eq!(24, std::mem::size_of::<crate::sql::strand::Strand>()); assert_eq!(24, std::mem::size_of::<crate::sql::strand::Strand>());
assert_eq!(16, std::mem::size_of::<crate::sql::duration::Duration>()); assert_eq!(16, std::mem::size_of::<crate::sql::duration::Duration>());
@ -1363,13 +1364,12 @@ mod tests {
assert_eq!(24, std::mem::size_of::<crate::sql::param::Param>()); assert_eq!(24, std::mem::size_of::<crate::sql::param::Param>());
assert_eq!(24, std::mem::size_of::<crate::sql::idiom::Idiom>()); assert_eq!(24, std::mem::size_of::<crate::sql::idiom::Idiom>());
assert_eq!(24, std::mem::size_of::<crate::sql::table::Table>()); assert_eq!(24, std::mem::size_of::<crate::sql::table::Table>());
assert_eq!(80, std::mem::size_of::<crate::sql::thing::Thing>()); assert_eq!(56, std::mem::size_of::<crate::sql::thing::Thing>());
assert_eq!(48, std::mem::size_of::<crate::sql::model::Model>()); assert_eq!(48, std::mem::size_of::<crate::sql::model::Model>());
assert_eq!(24, std::mem::size_of::<crate::sql::regex::Regex>()); assert_eq!(24, std::mem::size_of::<crate::sql::regex::Regex>());
assert_eq!(8, std::mem::size_of::<Box<crate::sql::function::Function>>()); assert_eq!(8, std::mem::size_of::<Box<crate::sql::function::Function>>());
assert_eq!(8, std::mem::size_of::<Box<crate::sql::subquery::Subquery>>()); assert_eq!(8, std::mem::size_of::<Box<crate::sql::subquery::Subquery>>());
assert_eq!(8, std::mem::size_of::<Box<crate::sql::expression::Expression>>()); assert_eq!(8, std::mem::size_of::<Box<crate::sql::expression::Expression>>());
assert_eq!(96, std::mem::size_of::<Result<Value, Error>>());
} }
#[test] #[test]