Bugfix: Fix inconsistant record parsing (#3076)
This commit is contained in:
parent
aac8ec8a36
commit
42f506a916
4 changed files with 89 additions and 23 deletions
|
@ -46,3 +46,23 @@ impl fmt::Display for SleepStatement {
|
||||||
write!(f, "SLEEP {}", self.duration)
|
write!(f, "SLEEP {}", self.duration)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
mod tests {
|
||||||
|
use super::*;
|
||||||
|
use crate::dbs::test::mock;
|
||||||
|
use crate::sql::{Duration, Value};
|
||||||
|
use std::time::{self, SystemTime};
|
||||||
|
|
||||||
|
#[tokio::test]
|
||||||
|
async fn test_sleep_compute() {
|
||||||
|
let time = SystemTime::now();
|
||||||
|
let (ctx, opt, txn) = mock().await;
|
||||||
|
let stm = SleepStatement {
|
||||||
|
duration: Duration(time::Duration::from_micros(500)),
|
||||||
|
};
|
||||||
|
let value = stm.compute(&ctx, &opt, &txn, None).await.unwrap();
|
||||||
|
assert!(time.elapsed().unwrap() >= time::Duration::from_micros(500));
|
||||||
|
assert_eq!(value, Value::None);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -6,9 +6,9 @@ use super::{
|
||||||
use nom::{
|
use nom::{
|
||||||
branch::alt,
|
branch::alt,
|
||||||
bytes::complete::{tag, tag_no_case},
|
bytes::complete::{tag, tag_no_case},
|
||||||
character::complete::{char, multispace1},
|
character::complete::{char, multispace1, satisfy},
|
||||||
combinator::{eof, peek, value},
|
combinator::{eof, peek, value},
|
||||||
sequence::preceded,
|
sequence::{preceded, tuple},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn number(i: &str) -> IResult<&str, ()> {
|
pub fn number(i: &str) -> IResult<&str, ()> {
|
||||||
|
@ -20,12 +20,21 @@ pub fn number(i: &str) -> IResult<&str, ()> {
|
||||||
value((), char(')')), // (1)
|
value((), char(')')), // (1)
|
||||||
value((), char(']')), // a[1]
|
value((), char(']')), // a[1]
|
||||||
value((), char('}')), // {k: 1}
|
value((), char('}')), // {k: 1}
|
||||||
value((), char('"')),
|
value((), char('"')), // r"foo:1"
|
||||||
value((), char('\'')),
|
value((), char('\'')), // r'foo:1'
|
||||||
value((), char(';')), // SET a = 1;
|
value((), char(';')), // SET a = 1;
|
||||||
value((), char(',')), // [1, 2]
|
value((), char(',')), // [1, 2]
|
||||||
value((), tag("..")), // thing:1..2
|
value((), char('[')), // thing:1[foo]
|
||||||
value((), eof), // SET a = 1
|
value((), tag("..")), // thing:1..2
|
||||||
|
value(
|
||||||
|
(),
|
||||||
|
tuple((
|
||||||
|
char('.'),
|
||||||
|
mightbespace,
|
||||||
|
satisfy(|x| x.is_alphanumeric() || x == '$' || x == '*'),
|
||||||
|
)),
|
||||||
|
), // thing:1.foo
|
||||||
|
value((), eof), // SET a = 1
|
||||||
)))(i)
|
)))(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -276,7 +276,7 @@ pub fn bracketed_value(i: &str) -> IResult<&str, Part> {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
|
|
||||||
use crate::sql::{Dir, Expression, Number, Param, Table, Thing};
|
use crate::sql::{Dir, Expression, Id, Number, Param, Strand, Table, Thing};
|
||||||
use crate::syn::test::Parse;
|
use crate::syn::test::Parse;
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -581,4 +581,55 @@ mod tests {
|
||||||
assert_eq!("[WHERE test = true]", format!("{}", out));
|
assert_eq!("[WHERE test = true]", format!("{}", out));
|
||||||
assert_eq!(out, Part::Where(Value::from(Expression::parse("test = true"))));
|
assert_eq!(out, Part::Where(Value::from(Expression::parse("test = true"))));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn idiom_thing_number() {
|
||||||
|
let sql = "test:1.foo";
|
||||||
|
let res = idiom(sql);
|
||||||
|
let out = res.unwrap().1;
|
||||||
|
assert_eq!(
|
||||||
|
out,
|
||||||
|
Idiom(vec![
|
||||||
|
Part::Start(Value::Thing(Thing {
|
||||||
|
tb: "test".to_owned(),
|
||||||
|
id: Id::Number(1),
|
||||||
|
})),
|
||||||
|
Part::from("foo"),
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn idiom_thing_index() {
|
||||||
|
let sql = "test:1['foo']";
|
||||||
|
let res = idiom(sql);
|
||||||
|
let out = res.unwrap().1;
|
||||||
|
assert_eq!(
|
||||||
|
out,
|
||||||
|
Idiom(vec![
|
||||||
|
Part::Start(Value::Thing(Thing {
|
||||||
|
tb: "test".to_owned(),
|
||||||
|
id: Id::Number(1),
|
||||||
|
})),
|
||||||
|
Part::Value(Value::Strand(Strand("foo".to_owned()))),
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn idiom_thing_all() {
|
||||||
|
let sql = "test:1.*";
|
||||||
|
let res = idiom(sql);
|
||||||
|
let out = res.unwrap().1;
|
||||||
|
assert_eq!(
|
||||||
|
out,
|
||||||
|
Idiom(vec![
|
||||||
|
Part::Start(Value::Thing(Thing {
|
||||||
|
tb: "test".to_owned(),
|
||||||
|
id: Id::Number(1),
|
||||||
|
})),
|
||||||
|
Part::All
|
||||||
|
])
|
||||||
|
);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -17,9 +17,6 @@ pub fn sleep(i: &str) -> IResult<&str, SleepStatement> {
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::*;
|
use super::*;
|
||||||
use crate::dbs::test::mock;
|
|
||||||
use crate::sql::Value;
|
|
||||||
use std::time::SystemTime;
|
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_sleep_statement_sec() {
|
fn test_sleep_statement_sec() {
|
||||||
|
@ -36,15 +33,4 @@ mod tests {
|
||||||
let out = res.unwrap().1;
|
let out = res.unwrap().1;
|
||||||
assert_eq!("SLEEP 500ms", format!("{}", out))
|
assert_eq!("SLEEP 500ms", format!("{}", out))
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tokio::test]
|
|
||||||
async fn test_sleep_compute() {
|
|
||||||
let sql = "SLEEP 500ms";
|
|
||||||
let time = SystemTime::now();
|
|
||||||
let (ctx, opt, txn) = mock().await;
|
|
||||||
let (_, stm) = sleep(sql).unwrap();
|
|
||||||
let value = stm.compute(&ctx, &opt, &txn, None).await.unwrap();
|
|
||||||
assert!(time.elapsed().unwrap() >= time::Duration::microseconds(500));
|
|
||||||
assert_eq!(value, Value::None);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue