mirror of
https://github.com/tursodatabase/limbo.git
synced 2025-08-04 18:18:03 +00:00
migrate to using limbo_core::Value
inside Simulator
This commit is contained in:
parent
2424b1b1c9
commit
6b58c4a33f
20 changed files with 201 additions and 286 deletions
|
@ -15,7 +15,7 @@ name = "limbo_sim"
|
|||
path = "main.rs"
|
||||
|
||||
[dependencies]
|
||||
limbo_core = { path = "../core", features = ["fuzz"]}
|
||||
limbo_core = { path = "../core", features = ["simulator"]}
|
||||
rand = "0.8.5"
|
||||
rand_chacha = "0.3.1"
|
||||
log = "0.4.20"
|
||||
|
|
|
@ -4,7 +4,7 @@ use limbo_sqlite3_parser::ast::{
|
|||
|
||||
use crate::{
|
||||
generation::{gen_random_text, pick, pick_index, Arbitrary, ArbitraryFrom},
|
||||
model::table::Value,
|
||||
model::table::SimValue,
|
||||
SimulatorEnv,
|
||||
};
|
||||
|
||||
|
@ -251,8 +251,8 @@ impl ArbitraryFrom<&SimulatorEnv> for ast::Literal {
|
|||
}
|
||||
|
||||
// Creates a litreal value
|
||||
impl ArbitraryFrom<&Vec<&Value>> for ast::Expr {
|
||||
fn arbitrary_from<R: rand::Rng>(rng: &mut R, values: &Vec<&Value>) -> Self {
|
||||
impl ArbitraryFrom<&Vec<&SimValue>> for ast::Expr {
|
||||
fn arbitrary_from<R: rand::Rng>(rng: &mut R, values: &Vec<&SimValue>) -> Self {
|
||||
if values.is_empty() {
|
||||
return Self::Literal(ast::Literal::Null);
|
||||
}
|
||||
|
|
|
@ -11,7 +11,7 @@ use crate::{
|
|||
update::Update,
|
||||
Create, CreateIndex, Delete, Drop, Insert, Query, Select,
|
||||
},
|
||||
table::Value,
|
||||
table::SimValue,
|
||||
},
|
||||
runner::{env::SimConnection, io::SimulatorIO},
|
||||
SimulatorEnv,
|
||||
|
@ -21,7 +21,7 @@ use crate::generation::{frequency, Arbitrary, ArbitraryFrom};
|
|||
|
||||
use super::property::{remaining, Property};
|
||||
|
||||
pub(crate) type ResultSet = Result<Vec<Vec<Value>>>;
|
||||
pub(crate) type ResultSet = Result<Vec<Vec<SimValue>>>;
|
||||
|
||||
#[derive(Clone, Serialize, Deserialize)]
|
||||
pub(crate) struct InteractionPlan {
|
||||
|
@ -483,7 +483,7 @@ impl ArbitraryFrom<&mut SimulatorEnv> for InteractionPlan {
|
|||
}
|
||||
|
||||
impl Interaction {
|
||||
pub(crate) fn shadow(&self, env: &mut SimulatorEnv) -> Vec<Vec<Value>> {
|
||||
pub(crate) fn shadow(&self, env: &mut SimulatorEnv) -> Vec<Vec<SimValue>> {
|
||||
match self {
|
||||
Self::Query(query) => query.shadow(env),
|
||||
Self::Assumption(_) | Self::Assertion(_) | Self::Fault(_) => vec![],
|
||||
|
@ -512,13 +512,7 @@ impl Interaction {
|
|||
let row = rows.row().unwrap();
|
||||
let mut r = Vec::new();
|
||||
for v in row.get_values() {
|
||||
let v = match v {
|
||||
limbo_core::Value::Null => Value::Null,
|
||||
limbo_core::Value::Integer(i) => Value::Integer(*i),
|
||||
limbo_core::Value::Float(f) => Value::Float(*f),
|
||||
limbo_core::Value::Text(t) => Value::Text(t.as_str().to_string()),
|
||||
limbo_core::Value::Blob(b) => Value::Blob(b.to_vec()),
|
||||
};
|
||||
let v = v.into();
|
||||
r.push(v);
|
||||
}
|
||||
out.push(r);
|
||||
|
|
|
@ -11,7 +11,7 @@ use crate::{
|
|||
},
|
||||
model::{
|
||||
query::predicate::Predicate,
|
||||
table::{Table, Value},
|
||||
table::{SimValue, Table},
|
||||
},
|
||||
};
|
||||
|
||||
|
@ -20,7 +20,7 @@ impl Predicate {
|
|||
pub fn from_column_binary<R: rand::Rng>(
|
||||
rng: &mut R,
|
||||
column_name: &str,
|
||||
value: &Value,
|
||||
value: &SimValue,
|
||||
) -> Predicate {
|
||||
let expr = one_of(
|
||||
vec![
|
||||
|
@ -54,7 +54,7 @@ impl Predicate {
|
|||
}
|
||||
|
||||
/// Produces a true [ast::Expr::Binary] [Predicate] that is true for the provided row in the given table
|
||||
pub fn true_binary<R: rand::Rng>(rng: &mut R, t: &Table, row: &Vec<Value>) -> Predicate {
|
||||
pub fn true_binary<R: rand::Rng>(rng: &mut R, t: &Table, row: &Vec<SimValue>) -> Predicate {
|
||||
// Pick a column
|
||||
let column_index = rng.gen_range(0..t.columns.len());
|
||||
let column = &t.columns[column_index];
|
||||
|
@ -77,7 +77,7 @@ impl Predicate {
|
|||
(
|
||||
1,
|
||||
Box::new(|rng| {
|
||||
let v = Value::arbitrary_from(rng, &column.column_type);
|
||||
let v = SimValue::arbitrary_from(rng, &column.column_type);
|
||||
if &v == value {
|
||||
None
|
||||
} else {
|
||||
|
@ -145,7 +145,7 @@ impl Predicate {
|
|||
}
|
||||
|
||||
/// Produces an [ast::Expr::Binary] [Predicate] that is false for the provided row in the given table
|
||||
pub fn false_binary<R: rand::Rng>(rng: &mut R, t: &Table, row: &Vec<Value>) -> Predicate {
|
||||
pub fn false_binary<R: rand::Rng>(rng: &mut R, t: &Table, row: &Vec<SimValue>) -> Predicate {
|
||||
// Pick a column
|
||||
let column_index = rng.gen_range(0..t.columns.len());
|
||||
let column = &t.columns[column_index];
|
||||
|
@ -164,7 +164,7 @@ impl Predicate {
|
|||
}),
|
||||
Box::new(|rng| {
|
||||
let v = loop {
|
||||
let v = Value::arbitrary_from(rng, &column.column_type);
|
||||
let v = SimValue::arbitrary_from(rng, &column.column_type);
|
||||
if &v != value {
|
||||
break v;
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use rand::{seq::SliceRandom as _, Rng};
|
|||
|
||||
use crate::model::{
|
||||
query::predicate::Predicate,
|
||||
table::{Table, Value},
|
||||
table::{SimValue, Table},
|
||||
};
|
||||
|
||||
use super::{one_of, ArbitraryFrom};
|
||||
|
@ -48,14 +48,14 @@ impl ArbitraryFrom<&Table> for Predicate {
|
|||
}
|
||||
}
|
||||
|
||||
impl ArbitraryFrom<(&str, &Value)> for Predicate {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, (column_name, value): (&str, &Value)) -> Self {
|
||||
impl ArbitraryFrom<(&str, &SimValue)> for Predicate {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, (column_name, value): (&str, &SimValue)) -> Self {
|
||||
Predicate::from_column_binary(rng, column_name, value)
|
||||
}
|
||||
}
|
||||
|
||||
impl ArbitraryFrom<(&Table, &Vec<Value>)> for Predicate {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, (t, row): (&Table, &Vec<Value>)) -> Self {
|
||||
impl ArbitraryFrom<(&Table, &Vec<SimValue>)> for Predicate {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, (t, row): (&Table, &Vec<SimValue>)) -> Self {
|
||||
// We want to produce a predicate that is true for the row
|
||||
// We can do this by creating several predicates that
|
||||
// are true, some that are false, combiend them in ways that correspond to the creation of a true predicate
|
||||
|
|
|
@ -8,14 +8,14 @@ use crate::{
|
|||
generation::{backtrack, pick, predicate::SimplePredicate, ArbitraryFromMaybe},
|
||||
model::{
|
||||
query::predicate::Predicate,
|
||||
table::{Table, Value},
|
||||
table::{SimValue, Table},
|
||||
},
|
||||
};
|
||||
|
||||
pub struct TrueValue(pub Value);
|
||||
pub struct TrueValue(pub SimValue);
|
||||
|
||||
impl ArbitraryFromMaybe<&Value> for TrueValue {
|
||||
fn arbitrary_from_maybe<R: rand::Rng>(_rng: &mut R, value: &Value) -> Option<Self>
|
||||
impl ArbitraryFromMaybe<&SimValue> for TrueValue {
|
||||
fn arbitrary_from_maybe<R: rand::Rng>(_rng: &mut R, value: &SimValue) -> Option<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
|
@ -24,13 +24,13 @@ impl ArbitraryFromMaybe<&Value> for TrueValue {
|
|||
}
|
||||
}
|
||||
|
||||
impl ArbitraryFromMaybe<&Vec<&Value>> for TrueValue {
|
||||
fn arbitrary_from_maybe<R: rand::Rng>(rng: &mut R, values: &Vec<&Value>) -> Option<Self>
|
||||
impl ArbitraryFromMaybe<&Vec<&SimValue>> for TrueValue {
|
||||
fn arbitrary_from_maybe<R: rand::Rng>(rng: &mut R, values: &Vec<&SimValue>) -> Option<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
if values.is_empty() {
|
||||
return Some(Self(Value::TRUE));
|
||||
return Some(Self(SimValue::TRUE));
|
||||
}
|
||||
|
||||
let value = pick(values, rng);
|
||||
|
@ -38,10 +38,10 @@ impl ArbitraryFromMaybe<&Vec<&Value>> for TrueValue {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct FalseValue(pub Value);
|
||||
pub struct FalseValue(pub SimValue);
|
||||
|
||||
impl ArbitraryFromMaybe<&Value> for FalseValue {
|
||||
fn arbitrary_from_maybe<R: rand::Rng>(_rng: &mut R, value: &Value) -> Option<Self>
|
||||
impl ArbitraryFromMaybe<&SimValue> for FalseValue {
|
||||
fn arbitrary_from_maybe<R: rand::Rng>(_rng: &mut R, value: &SimValue) -> Option<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
|
@ -50,13 +50,13 @@ impl ArbitraryFromMaybe<&Value> for FalseValue {
|
|||
}
|
||||
}
|
||||
|
||||
impl ArbitraryFromMaybe<&Vec<&Value>> for FalseValue {
|
||||
fn arbitrary_from_maybe<R: rand::Rng>(rng: &mut R, values: &Vec<&Value>) -> Option<Self>
|
||||
impl ArbitraryFromMaybe<&Vec<&SimValue>> for FalseValue {
|
||||
fn arbitrary_from_maybe<R: rand::Rng>(rng: &mut R, values: &Vec<&SimValue>) -> Option<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
{
|
||||
if values.is_empty() {
|
||||
return Some(Self(Value::FALSE));
|
||||
return Some(Self(SimValue::FALSE));
|
||||
}
|
||||
|
||||
let value = pick(values, rng);
|
||||
|
@ -64,12 +64,12 @@ impl ArbitraryFromMaybe<&Vec<&Value>> for FalseValue {
|
|||
}
|
||||
}
|
||||
|
||||
pub struct BitNotValue(pub Value);
|
||||
pub struct BitNotValue(pub SimValue);
|
||||
|
||||
impl ArbitraryFromMaybe<(&Value, bool)> for BitNotValue {
|
||||
impl ArbitraryFromMaybe<(&SimValue, bool)> for BitNotValue {
|
||||
fn arbitrary_from_maybe<R: rand::Rng>(
|
||||
_rng: &mut R,
|
||||
(value, predicate): (&Value, bool),
|
||||
(value, predicate): (&SimValue, bool),
|
||||
) -> Option<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
|
@ -80,10 +80,10 @@ impl ArbitraryFromMaybe<(&Value, bool)> for BitNotValue {
|
|||
}
|
||||
}
|
||||
|
||||
impl ArbitraryFromMaybe<(&Vec<&Value>, bool)> for BitNotValue {
|
||||
impl ArbitraryFromMaybe<(&Vec<&SimValue>, bool)> for BitNotValue {
|
||||
fn arbitrary_from_maybe<R: rand::Rng>(
|
||||
rng: &mut R,
|
||||
(values, predicate): (&Vec<&Value>, bool),
|
||||
(values, predicate): (&Vec<&SimValue>, bool),
|
||||
) -> Option<Self>
|
||||
where
|
||||
Self: Sized,
|
||||
|
@ -151,7 +151,9 @@ impl SimplePredicate {
|
|||
rng,
|
||||
);
|
||||
// If cannot generate a value
|
||||
SimplePredicate(Predicate(expr.unwrap_or(Expr::Literal(Value::TRUE.into()))))
|
||||
SimplePredicate(Predicate(
|
||||
expr.unwrap_or(Expr::Literal(SimValue::TRUE.into())),
|
||||
))
|
||||
}
|
||||
|
||||
/// Generates a false [ast::Expr::Unary] [SimplePredicate] from a [Table]
|
||||
|
@ -207,6 +209,8 @@ impl SimplePredicate {
|
|||
rng,
|
||||
);
|
||||
// If cannot generate a value
|
||||
SimplePredicate(Predicate(expr.unwrap_or(Expr::Literal(Value::TRUE.into()))))
|
||||
SimplePredicate(Predicate(
|
||||
expr.unwrap_or(Expr::Literal(SimValue::TRUE.into())),
|
||||
))
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
use limbo_core::LimboError;
|
||||
use limbo_core::{LimboError, Value};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
|
@ -8,7 +8,7 @@ use crate::{
|
|||
select::{Distinctness, ResultColumn},
|
||||
Create, Delete, Drop, Insert, Query, Select,
|
||||
},
|
||||
table::Value,
|
||||
table::SimValue,
|
||||
},
|
||||
runner::env::SimulatorEnv,
|
||||
};
|
||||
|
@ -418,7 +418,7 @@ impl Property {
|
|||
.iter()
|
||||
.filter(|vs| {
|
||||
let v = vs.first().unwrap();
|
||||
if let Value::Integer(i) = v {
|
||||
if let Value::Integer(i) = &v.0 {
|
||||
*i == 1
|
||||
} else {
|
||||
false
|
||||
|
@ -496,7 +496,7 @@ fn property_insert_values_select<R: rand::Rng>(
|
|||
let table = pick(&env.tables, rng);
|
||||
// Generate rows to insert
|
||||
let rows = (0..rng.gen_range(1..=5))
|
||||
.map(|_| Vec::<Value>::arbitrary_from(rng, table))
|
||||
.map(|_| Vec::<SimValue>::arbitrary_from(rng, table))
|
||||
.collect::<Vec<_>>();
|
||||
|
||||
// Pick a random row to select
|
||||
|
|
|
@ -5,7 +5,7 @@ use crate::model::query::predicate::Predicate;
|
|||
use crate::model::query::select::{Distinctness, ResultColumn};
|
||||
use crate::model::query::update::Update;
|
||||
use crate::model::query::{Create, Delete, Drop, Insert, Query, Select};
|
||||
use crate::model::table::{Table, Value};
|
||||
use crate::model::table::{SimValue, Table};
|
||||
use crate::SimulatorEnv;
|
||||
use rand::Rng;
|
||||
|
||||
|
@ -38,12 +38,12 @@ impl ArbitraryFrom<&SimulatorEnv> for Insert {
|
|||
let gen_values = |rng: &mut R| {
|
||||
let table = pick(&env.tables, rng);
|
||||
let num_rows = rng.gen_range(1..10);
|
||||
let values: Vec<Vec<Value>> = (0..num_rows)
|
||||
let values: Vec<Vec<SimValue>> = (0..num_rows)
|
||||
.map(|_| {
|
||||
table
|
||||
.columns
|
||||
.iter()
|
||||
.map(|c| Value::arbitrary_from(rng, &c.column_type))
|
||||
.map(|c| SimValue::arbitrary_from(rng, &c.column_type))
|
||||
.collect()
|
||||
})
|
||||
.collect();
|
||||
|
@ -141,7 +141,7 @@ impl ArbitraryFrom<&SimulatorEnv> for Update {
|
|||
let table = pick(&env.tables, rng);
|
||||
let mut seen = HashSet::new();
|
||||
let num_cols = rng.gen_range(1..=table.columns.len());
|
||||
let set_values: Vec<(String, Value)> = (0..num_cols)
|
||||
let set_values: Vec<(String, SimValue)> = (0..num_cols)
|
||||
.map(|_| {
|
||||
let column = loop {
|
||||
let column = pick(&table.columns, rng);
|
||||
|
@ -153,7 +153,7 @@ impl ArbitraryFrom<&SimulatorEnv> for Update {
|
|||
seen.insert(column.name.clone());
|
||||
(
|
||||
column.name.clone(),
|
||||
Value::arbitrary_from(rng, &column.column_type),
|
||||
SimValue::arbitrary_from(rng, &column.column_type),
|
||||
)
|
||||
})
|
||||
.collect();
|
||||
|
|
|
@ -1,7 +1,8 @@
|
|||
use limbo_core::Value;
|
||||
use rand::Rng;
|
||||
|
||||
use crate::generation::{gen_random_text, pick, readable_name_custom, Arbitrary, ArbitraryFrom};
|
||||
use crate::model::table::{Column, ColumnType, Name, Table, Value};
|
||||
use crate::model::table::{Column, ColumnType, Name, SimValue, Table};
|
||||
|
||||
use super::ArbitraryFromMaybe;
|
||||
|
||||
|
@ -45,44 +46,45 @@ impl Arbitrary for ColumnType {
|
|||
}
|
||||
}
|
||||
|
||||
impl ArbitraryFrom<&Table> for Vec<Value> {
|
||||
impl ArbitraryFrom<&Table> for Vec<SimValue> {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, table: &Table) -> Self {
|
||||
let mut row = Vec::new();
|
||||
for column in table.columns.iter() {
|
||||
let value = Value::arbitrary_from(rng, &column.column_type);
|
||||
let value = SimValue::arbitrary_from(rng, &column.column_type);
|
||||
row.push(value);
|
||||
}
|
||||
row
|
||||
}
|
||||
}
|
||||
|
||||
impl ArbitraryFrom<&Vec<&Value>> for Value {
|
||||
impl ArbitraryFrom<&Vec<&SimValue>> for SimValue {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, values: &Vec<&Self>) -> Self {
|
||||
if values.is_empty() {
|
||||
return Self::Null;
|
||||
return Self(Value::Null);
|
||||
}
|
||||
|
||||
pick(values, rng).to_owned().clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl ArbitraryFrom<&ColumnType> for Value {
|
||||
impl ArbitraryFrom<&ColumnType> for SimValue {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, column_type: &ColumnType) -> Self {
|
||||
match column_type {
|
||||
ColumnType::Integer => Self::Integer(rng.gen_range(i64::MIN..i64::MAX)),
|
||||
ColumnType::Float => Self::Float(rng.gen_range(-1e10..1e10)),
|
||||
ColumnType::Text => Self::Text(gen_random_text(rng)),
|
||||
ColumnType::Blob => Self::Blob(gen_random_text(rng).as_bytes().to_vec()),
|
||||
}
|
||||
let value = match column_type {
|
||||
ColumnType::Integer => Value::Integer(rng.gen_range(i64::MIN..i64::MAX)),
|
||||
ColumnType::Float => Value::Float(rng.gen_range(-1e10..1e10)),
|
||||
ColumnType::Text => Value::build_text(gen_random_text(rng)),
|
||||
ColumnType::Blob => Value::Blob(gen_random_text(rng).as_bytes().to_vec()),
|
||||
};
|
||||
SimValue(value)
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct LTValue(pub(crate) Value);
|
||||
pub(crate) struct LTValue(pub(crate) SimValue);
|
||||
|
||||
impl ArbitraryFrom<&Vec<&Value>> for LTValue {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, values: &Vec<&Value>) -> Self {
|
||||
impl ArbitraryFrom<&Vec<&SimValue>> for LTValue {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, values: &Vec<&SimValue>) -> Self {
|
||||
if values.is_empty() {
|
||||
return Self(Value::Null);
|
||||
return Self(SimValue(Value::Null));
|
||||
}
|
||||
|
||||
let value = pick(values, rng);
|
||||
|
@ -90,17 +92,17 @@ impl ArbitraryFrom<&Vec<&Value>> for LTValue {
|
|||
}
|
||||
}
|
||||
|
||||
impl ArbitraryFrom<&Value> for LTValue {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, value: &Value) -> Self {
|
||||
match value {
|
||||
Value::Integer(i) => Self(Value::Integer(rng.gen_range(i64::MIN..*i - 1))),
|
||||
Value::Float(f) => Self(Value::Float(f - rng.gen_range(0.0..1e10))),
|
||||
Value::Text(t) => {
|
||||
impl ArbitraryFrom<&SimValue> for LTValue {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, value: &SimValue) -> Self {
|
||||
let new_value = match &value.0 {
|
||||
Value::Integer(i) => Value::Integer(rng.gen_range(i64::MIN..*i - 1)),
|
||||
Value::Float(f) => Value::Float(f - rng.gen_range(0.0..1e10)),
|
||||
value @ Value::Text(..) => {
|
||||
// Either shorten the string, or make at least one character smaller and mutate the rest
|
||||
let mut t = t.clone();
|
||||
let mut t = value.to_string();
|
||||
if rng.gen_bool(0.01) {
|
||||
t.pop();
|
||||
Self(Value::Text(t))
|
||||
Value::build_text(t)
|
||||
} else {
|
||||
let mut t = t.chars().map(|c| c as u32).collect::<Vec<_>>();
|
||||
let index = rng.gen_range(0..t.len());
|
||||
|
@ -113,7 +115,7 @@ impl ArbitraryFrom<&Value> for LTValue {
|
|||
.into_iter()
|
||||
.map(|c| char::from_u32(c).unwrap_or('z'))
|
||||
.collect::<String>();
|
||||
Self(Value::Text(t))
|
||||
Value::build_text(t)
|
||||
}
|
||||
}
|
||||
Value::Blob(b) => {
|
||||
|
@ -121,7 +123,7 @@ impl ArbitraryFrom<&Value> for LTValue {
|
|||
let mut b = b.clone();
|
||||
if rng.gen_bool(0.01) {
|
||||
b.pop();
|
||||
Self(Value::Blob(b))
|
||||
Value::Blob(b)
|
||||
} else {
|
||||
let index = rng.gen_range(0..b.len());
|
||||
b[index] -= 1;
|
||||
|
@ -129,20 +131,21 @@ impl ArbitraryFrom<&Value> for LTValue {
|
|||
for i in (index + 1)..b.len() {
|
||||
b[i] = rng.gen_range(0..=255);
|
||||
}
|
||||
Self(Value::Blob(b))
|
||||
Value::Blob(b)
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
};
|
||||
Self(SimValue(new_value))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct GTValue(pub(crate) Value);
|
||||
pub(crate) struct GTValue(pub(crate) SimValue);
|
||||
|
||||
impl ArbitraryFrom<&Vec<&Value>> for GTValue {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, values: &Vec<&Value>) -> Self {
|
||||
impl ArbitraryFrom<&Vec<&SimValue>> for GTValue {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, values: &Vec<&SimValue>) -> Self {
|
||||
if values.is_empty() {
|
||||
return Self(Value::Null);
|
||||
return Self(SimValue(Value::Null));
|
||||
}
|
||||
|
||||
let value = pick(values, rng);
|
||||
|
@ -150,17 +153,17 @@ impl ArbitraryFrom<&Vec<&Value>> for GTValue {
|
|||
}
|
||||
}
|
||||
|
||||
impl ArbitraryFrom<&Value> for GTValue {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, value: &Value) -> Self {
|
||||
match value {
|
||||
Value::Integer(i) => Self(Value::Integer(rng.gen_range(*i..i64::MAX))),
|
||||
Value::Float(f) => Self(Value::Float(rng.gen_range(*f..1e10))),
|
||||
Value::Text(t) => {
|
||||
impl ArbitraryFrom<&SimValue> for GTValue {
|
||||
fn arbitrary_from<R: Rng>(rng: &mut R, value: &SimValue) -> Self {
|
||||
let new_value = match &value.0 {
|
||||
Value::Integer(i) => Value::Integer(rng.gen_range(*i..i64::MAX)),
|
||||
Value::Float(f) => Value::Float(rng.gen_range(*f..1e10)),
|
||||
value @ Value::Text(..) => {
|
||||
// Either lengthen the string, or make at least one character smaller and mutate the rest
|
||||
let mut t = t.clone();
|
||||
let mut t = value.to_string();
|
||||
if rng.gen_bool(0.01) {
|
||||
t.push(rng.gen_range(0..=255) as u8 as char);
|
||||
Self(Value::Text(t))
|
||||
Value::build_text(t)
|
||||
} else {
|
||||
let mut t = t.chars().map(|c| c as u32).collect::<Vec<_>>();
|
||||
let index = rng.gen_range(0..t.len());
|
||||
|
@ -173,7 +176,7 @@ impl ArbitraryFrom<&Value> for GTValue {
|
|||
.into_iter()
|
||||
.map(|c| char::from_u32(c).unwrap_or('a'))
|
||||
.collect::<String>();
|
||||
Self(Value::Text(t))
|
||||
Value::build_text(t)
|
||||
}
|
||||
}
|
||||
Value::Blob(b) => {
|
||||
|
@ -181,7 +184,7 @@ impl ArbitraryFrom<&Value> for GTValue {
|
|||
let mut b = b.clone();
|
||||
if rng.gen_bool(0.01) {
|
||||
b.push(rng.gen_range(0..=255));
|
||||
Self(Value::Blob(b))
|
||||
Value::Blob(b)
|
||||
} else {
|
||||
let index = rng.gen_range(0..b.len());
|
||||
b[index] += 1;
|
||||
|
@ -189,20 +192,22 @@ impl ArbitraryFrom<&Value> for GTValue {
|
|||
for i in (index + 1)..b.len() {
|
||||
b[i] = rng.gen_range(0..=255);
|
||||
}
|
||||
Self(Value::Blob(b))
|
||||
Value::Blob(b)
|
||||
}
|
||||
}
|
||||
_ => unreachable!(),
|
||||
}
|
||||
};
|
||||
Self(SimValue(new_value))
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) struct LikeValue(pub(crate) Value);
|
||||
pub(crate) struct LikeValue(pub(crate) SimValue);
|
||||
|
||||
impl ArbitraryFromMaybe<&Value> for LikeValue {
|
||||
fn arbitrary_from_maybe<R: Rng>(rng: &mut R, value: &Value) -> Option<Self> {
|
||||
match value {
|
||||
Value::Text(t) => {
|
||||
impl ArbitraryFromMaybe<&SimValue> for LikeValue {
|
||||
fn arbitrary_from_maybe<R: Rng>(rng: &mut R, value: &SimValue) -> Option<Self> {
|
||||
match &value.0 {
|
||||
value @ Value::Text(..) => {
|
||||
let t = value.to_string();
|
||||
let mut t = t.chars().collect::<Vec<_>>();
|
||||
// Remove a number of characters, either insert `_` for each character removed, or
|
||||
// insert one `%` for the whole substring
|
||||
|
@ -221,7 +226,9 @@ impl ArbitraryFromMaybe<&Value> for LikeValue {
|
|||
}
|
||||
let index = rng.gen_range(0..t.len());
|
||||
t.insert(index, '%');
|
||||
Some(Self(Value::Text(t.into_iter().collect())))
|
||||
Some(Self(SimValue(Value::build_text(
|
||||
t.into_iter().collect::<String>(),
|
||||
))))
|
||||
}
|
||||
_ => None,
|
||||
}
|
||||
|
|
|
@ -3,7 +3,7 @@ use std::fmt::Display;
|
|||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
model::table::{Table, Value},
|
||||
model::table::{SimValue, Table},
|
||||
SimulatorEnv,
|
||||
};
|
||||
|
||||
|
@ -13,7 +13,7 @@ pub(crate) struct Create {
|
|||
}
|
||||
|
||||
impl Create {
|
||||
pub(crate) fn shadow(&self, env: &mut SimulatorEnv) -> Vec<Vec<Value>> {
|
||||
pub(crate) fn shadow(&self, env: &mut SimulatorEnv) -> Vec<Vec<SimValue>> {
|
||||
if !env.tables.iter().any(|t| t.name == self.table.name) {
|
||||
env.tables.push(self.table.clone());
|
||||
}
|
||||
|
|
|
@ -31,7 +31,7 @@ impl CreateIndex {
|
|||
pub(crate) fn shadow(
|
||||
&self,
|
||||
_env: &mut crate::runner::env::SimulatorEnv,
|
||||
) -> Vec<Vec<crate::model::table::Value>> {
|
||||
) -> Vec<Vec<crate::model::table::SimValue>> {
|
||||
// CREATE INDEX doesn't require any shadowing; we don't need to keep track
|
||||
// in the simulator what indexes exist.
|
||||
vec![]
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::fmt::Display;
|
|||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{model::table::Value, SimulatorEnv};
|
||||
use crate::{model::table::SimValue, SimulatorEnv};
|
||||
|
||||
use super::predicate::Predicate;
|
||||
|
||||
|
@ -13,7 +13,7 @@ pub(crate) struct Delete {
|
|||
}
|
||||
|
||||
impl Delete {
|
||||
pub(crate) fn shadow(&self, env: &mut SimulatorEnv) -> Vec<Vec<Value>> {
|
||||
pub(crate) fn shadow(&self, env: &mut SimulatorEnv) -> Vec<Vec<SimValue>> {
|
||||
let table = env
|
||||
.tables
|
||||
.iter_mut()
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::fmt::Display;
|
|||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{model::table::Value, SimulatorEnv};
|
||||
use crate::{model::table::SimValue, SimulatorEnv};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub(crate) struct Drop {
|
||||
|
@ -10,7 +10,7 @@ pub(crate) struct Drop {
|
|||
}
|
||||
|
||||
impl Drop {
|
||||
pub(crate) fn shadow(&self, env: &mut SimulatorEnv) -> Vec<Vec<Value>> {
|
||||
pub(crate) fn shadow(&self, env: &mut SimulatorEnv) -> Vec<Vec<SimValue>> {
|
||||
env.tables.retain(|t| t.name != self.table);
|
||||
vec![]
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::fmt::Display;
|
|||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{model::table::Value, SimulatorEnv};
|
||||
use crate::{model::table::SimValue, SimulatorEnv};
|
||||
|
||||
use super::select::Select;
|
||||
|
||||
|
@ -10,7 +10,7 @@ use super::select::Select;
|
|||
pub(crate) enum Insert {
|
||||
Values {
|
||||
table: String,
|
||||
values: Vec<Vec<Value>>,
|
||||
values: Vec<Vec<SimValue>>,
|
||||
},
|
||||
Select {
|
||||
table: String,
|
||||
|
@ -19,7 +19,7 @@ pub(crate) enum Insert {
|
|||
}
|
||||
|
||||
impl Insert {
|
||||
pub(crate) fn shadow(&self, env: &mut SimulatorEnv) -> Vec<Vec<Value>> {
|
||||
pub(crate) fn shadow(&self, env: &mut SimulatorEnv) -> Vec<Vec<SimValue>> {
|
||||
match self {
|
||||
Insert::Values { table, values } => {
|
||||
if let Some(t) = env.tables.iter_mut().find(|t| &t.name == table) {
|
||||
|
|
|
@ -10,7 +10,7 @@ pub(crate) use select::Select;
|
|||
use serde::{Deserialize, Serialize};
|
||||
use update::Update;
|
||||
|
||||
use crate::{model::table::Value, runner::env::SimulatorEnv};
|
||||
use crate::{model::table::SimValue, runner::env::SimulatorEnv};
|
||||
|
||||
pub mod create;
|
||||
pub mod create_index;
|
||||
|
@ -61,7 +61,7 @@ impl Query {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn shadow(&self, env: &mut SimulatorEnv) -> Vec<Vec<Value>> {
|
||||
pub(crate) fn shadow(&self, env: &mut SimulatorEnv) -> Vec<Vec<SimValue>> {
|
||||
match self {
|
||||
Query::Create(create) => create.shadow(env),
|
||||
Query::Insert(insert) => insert.shadow(env),
|
||||
|
|
|
@ -5,7 +5,7 @@ use serde::{Deserialize, Serialize};
|
|||
|
||||
use crate::model::{
|
||||
query::EmptyContext,
|
||||
table::{Table, Value},
|
||||
table::{SimValue, Table},
|
||||
};
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
|
@ -20,7 +20,7 @@ impl Predicate {
|
|||
Self(ast::Expr::Literal(ast::Literal::Numeric("0".to_string())))
|
||||
}
|
||||
|
||||
pub(crate) fn test(&self, row: &[Value], table: &Table) -> bool {
|
||||
pub(crate) fn test(&self, row: &[SimValue], table: &Table) -> bool {
|
||||
let value = expr_to_value(&self.0, row, table);
|
||||
value.map_or(false, |value| value.into_bool())
|
||||
}
|
||||
|
@ -30,7 +30,7 @@ impl Predicate {
|
|||
// This function attempts to convert an simpler easily computable expression into values
|
||||
// TODO: In the future, we can try to expand this computation if we want to support harder properties that require us
|
||||
// to already know more values before hand
|
||||
fn expr_to_value(expr: &ast::Expr, row: &[Value], table: &Table) -> Option<Value> {
|
||||
fn expr_to_value(expr: &ast::Expr, row: &[SimValue], table: &Table) -> Option<SimValue> {
|
||||
match expr {
|
||||
ast::Expr::DoublyQualified(_, _, ast::Name(col_name))
|
||||
| ast::Expr::Qualified(_, ast::Name(col_name))
|
||||
|
@ -57,7 +57,7 @@ fn expr_to_value(expr: &ast::Expr, row: &[Value], table: &Table) -> Option<Value
|
|||
let lhs = expr_to_value(lhs, row, table)?;
|
||||
let rhs = expr_to_value(rhs, row, table)?;
|
||||
let res = lhs.like_compare(&rhs, *op);
|
||||
let value: Value = if *not { !res } else { res }.into();
|
||||
let value: SimValue = if *not { !res } else { res }.into();
|
||||
Some(value)
|
||||
}
|
||||
ast::Expr::Unary(op, expr) => {
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::fmt::Display;
|
|||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{model::table::Value, SimulatorEnv};
|
||||
use crate::{model::table::SimValue, SimulatorEnv};
|
||||
|
||||
use super::predicate::Predicate;
|
||||
|
||||
|
@ -46,7 +46,7 @@ pub(crate) struct Select {
|
|||
}
|
||||
|
||||
impl Select {
|
||||
pub(crate) fn shadow(&self, env: &mut SimulatorEnv) -> Vec<Vec<Value>> {
|
||||
pub(crate) fn shadow(&self, env: &mut SimulatorEnv) -> Vec<Vec<SimValue>> {
|
||||
let table = env.tables.iter().find(|t| t.name == self.table.as_str());
|
||||
if let Some(table) = table {
|
||||
table
|
||||
|
|
|
@ -2,19 +2,19 @@ use std::fmt::Display;
|
|||
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{model::table::Value, SimulatorEnv};
|
||||
use crate::{model::table::SimValue, SimulatorEnv};
|
||||
|
||||
use super::predicate::Predicate;
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub(crate) struct Update {
|
||||
pub(crate) table: String,
|
||||
pub(crate) set_values: Vec<(String, Value)>, // Pair of value for set expressions => SET name=value
|
||||
pub(crate) set_values: Vec<(String, SimValue)>, // Pair of value for set expressions => SET name=value
|
||||
pub(crate) predicate: Predicate,
|
||||
}
|
||||
|
||||
impl Update {
|
||||
pub(crate) fn shadow(&self, env: &mut SimulatorEnv) -> Vec<Vec<Value>> {
|
||||
pub(crate) fn shadow(&self, env: &mut SimulatorEnv) -> Vec<Vec<SimValue>> {
|
||||
let table = env
|
||||
.tables
|
||||
.iter_mut()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::{fmt::Display, ops::Deref};
|
||||
|
||||
use limbo_core::numeric::{nonnan::NonNan, NullableInteger, Numeric};
|
||||
use limbo_core::{numeric::Numeric, types};
|
||||
use limbo_sqlite3_parser::ast;
|
||||
use regex::{Regex, RegexBuilder};
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
@ -17,7 +17,7 @@ impl Deref for Name {
|
|||
|
||||
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||
pub(crate) struct Table {
|
||||
pub(crate) rows: Vec<Vec<Value>>,
|
||||
pub(crate) rows: Vec<Vec<SimValue>>,
|
||||
pub(crate) name: String,
|
||||
pub(crate) columns: Vec<Column>,
|
||||
}
|
||||
|
@ -64,35 +64,8 @@ where
|
|||
s.parse().map_err(serde::de::Error::custom)
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug, PartialEq, Serialize, Deserialize)]
|
||||
pub(crate) enum Value {
|
||||
Null,
|
||||
Integer(i64),
|
||||
// we use custom serialization to preserve float precision
|
||||
#[serde(
|
||||
serialize_with = "float_to_string",
|
||||
deserialize_with = "string_to_float"
|
||||
)]
|
||||
Float(f64),
|
||||
Text(String),
|
||||
Blob(Vec<u8>),
|
||||
}
|
||||
|
||||
impl PartialOrd for Value {
|
||||
fn partial_cmp(&self, other: &Self) -> Option<std::cmp::Ordering> {
|
||||
match (self, other) {
|
||||
(Self::Null, Self::Null) => Some(std::cmp::Ordering::Equal),
|
||||
(Self::Null, _) => Some(std::cmp::Ordering::Less),
|
||||
(_, Self::Null) => Some(std::cmp::Ordering::Greater),
|
||||
(Self::Integer(i1), Self::Integer(i2)) => i1.partial_cmp(i2),
|
||||
(Self::Float(f1), Self::Float(f2)) => f1.partial_cmp(f2),
|
||||
(Self::Text(t1), Self::Text(t2)) => t1.partial_cmp(t2),
|
||||
(Self::Blob(b1), Self::Blob(b2)) => b1.partial_cmp(b2),
|
||||
// todo: add type coercions here
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
}
|
||||
#[derive(Clone, Debug, PartialEq, PartialOrd, Serialize, Deserialize)]
|
||||
pub(crate) struct SimValue(pub limbo_core::Value);
|
||||
|
||||
fn to_sqlite_blob(bytes: &[u8]) -> String {
|
||||
format!(
|
||||
|
@ -103,29 +76,29 @@ fn to_sqlite_blob(bytes: &[u8]) -> String {
|
|||
)
|
||||
}
|
||||
|
||||
impl Display for Value {
|
||||
impl Display for SimValue {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
match self {
|
||||
Self::Null => write!(f, "NULL"),
|
||||
Self::Integer(i) => write!(f, "{}", i),
|
||||
Self::Float(fl) => write!(f, "{}", fl),
|
||||
Self::Text(t) => write!(f, "'{}'", t),
|
||||
Self::Blob(b) => write!(f, "{}", to_sqlite_blob(b)),
|
||||
match &self.0 {
|
||||
types::Value::Null => write!(f, "NULL"),
|
||||
types::Value::Integer(i) => write!(f, "{}", i),
|
||||
types::Value::Float(fl) => write!(f, "{}", fl),
|
||||
value @ types::Value::Text(..) => write!(f, "'{}'", value.to_string()),
|
||||
types::Value::Blob(b) => write!(f, "{}", to_sqlite_blob(b)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Value {
|
||||
pub const FALSE: Self = Value::Integer(0);
|
||||
pub const TRUE: Self = Value::Integer(1);
|
||||
impl SimValue {
|
||||
pub const FALSE: Self = SimValue(types::Value::Integer(0));
|
||||
pub const TRUE: Self = SimValue(types::Value::Integer(1));
|
||||
|
||||
pub fn into_bool(&self) -> bool {
|
||||
Numeric::from(self).try_into_bool().unwrap_or_default()
|
||||
Numeric::from(&self.0).try_into_bool().unwrap_or_default()
|
||||
}
|
||||
|
||||
// TODO: support more predicates
|
||||
/// Returns a Value::TRUE or VALUE::FALSE
|
||||
pub fn binary_compare(&self, other: &Self, operator: ast::Operator) -> Value {
|
||||
pub fn binary_compare(&self, other: &Self, operator: ast::Operator) -> SimValue {
|
||||
match operator {
|
||||
ast::Operator::Add => todo!(),
|
||||
ast::Operator::And => self.into_bool() && other.into_bool(),
|
||||
|
@ -167,13 +140,14 @@ impl Value {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn unary_exec(&self, operator: ast::UnaryOperator) -> Value {
|
||||
match operator {
|
||||
ast::UnaryOperator::BitwiseNot => exec_bit_not(self),
|
||||
pub fn unary_exec(&self, operator: ast::UnaryOperator) -> SimValue {
|
||||
let new_value = match operator {
|
||||
ast::UnaryOperator::BitwiseNot => self.0.exec_bit_not(),
|
||||
ast::UnaryOperator::Negative => todo!(),
|
||||
ast::UnaryOperator::Not => todo!(),
|
||||
ast::UnaryOperator::Positive => todo!(),
|
||||
}
|
||||
};
|
||||
Self(new_value)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -212,35 +186,19 @@ fn exec_like(pattern: &str, text: &str) -> bool {
|
|||
re.is_match(text)
|
||||
}
|
||||
|
||||
impl From<&ast::Literal> for Value {
|
||||
fn from(value: &ast::Literal) -> Self {
|
||||
match value {
|
||||
ast::Literal::Null => Self::Null,
|
||||
ast::Literal::Numeric(number) => Numeric::from(number).into(),
|
||||
ast::Literal::String(string) => Self::Text(string.clone()),
|
||||
ast::Literal::Blob(blob) => Self::Blob(
|
||||
blob.as_bytes()
|
||||
.chunks_exact(2)
|
||||
.map(|pair| {
|
||||
// We assume that sqlite3-parser has already validated that
|
||||
// the input is valid hex string, thus unwrap is safe.
|
||||
let hex_byte = std::str::from_utf8(pair).unwrap();
|
||||
u8::from_str_radix(hex_byte, 16).unwrap()
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
lit => unimplemented!("{:?}", lit),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<ast::Literal> for Value {
|
||||
impl From<ast::Literal> for SimValue {
|
||||
fn from(value: ast::Literal) -> Self {
|
||||
match value {
|
||||
ast::Literal::Null => Self::Null,
|
||||
Self::from(&value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&ast::Literal> for SimValue {
|
||||
fn from(value: &ast::Literal) -> Self {
|
||||
let new_value = match value {
|
||||
ast::Literal::Null => types::Value::Null,
|
||||
ast::Literal::Numeric(number) => Numeric::from(number).into(),
|
||||
ast::Literal::String(string) => Self::Text(string),
|
||||
ast::Literal::Blob(blob) => Self::Blob(
|
||||
ast::Literal::String(string) => types::Value::build_text(string),
|
||||
ast::Literal::Blob(blob) => types::Value::Blob(
|
||||
blob.as_bytes()
|
||||
.chunks_exact(2)
|
||||
.map(|pair| {
|
||||
|
@ -252,106 +210,55 @@ impl From<ast::Literal> for Value {
|
|||
.collect(),
|
||||
),
|
||||
lit => unimplemented!("{:?}", lit),
|
||||
}
|
||||
};
|
||||
Self(new_value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Value> for ast::Literal {
|
||||
fn from(value: Value) -> Self {
|
||||
match value {
|
||||
Value::Null => Self::Null,
|
||||
Value::Integer(i) => Self::Numeric(i.to_string()),
|
||||
Value::Float(f) => Self::Numeric(f.to_string()),
|
||||
Value::Text(string) => Self::String(format!("'{}'", string)),
|
||||
Value::Blob(blob) => Self::Blob(hex::encode(blob)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Value> for ast::Literal {
|
||||
fn from(value: &Value) -> Self {
|
||||
match value {
|
||||
Value::Null => Self::Null,
|
||||
Value::Integer(i) => Self::Numeric(i.to_string()),
|
||||
Value::Float(f) => Self::Numeric(f.to_string()),
|
||||
Value::Text(string) => Self::String(format!("'{}'", string)),
|
||||
Value::Blob(blob) => Self::Blob(hex::encode(blob)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Numeric> for Value {
|
||||
fn from(value: Numeric) -> Self {
|
||||
match value {
|
||||
Numeric::Null => Value::Null,
|
||||
Numeric::Integer(i) => Value::Integer(i),
|
||||
Numeric::Float(f) => Value::Float(f.into()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Copied from numeric in Core
|
||||
impl From<Value> for Numeric {
|
||||
fn from(value: Value) -> Self {
|
||||
impl From<SimValue> for ast::Literal {
|
||||
fn from(value: SimValue) -> Self {
|
||||
Self::from(&value)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Value> for Numeric {
|
||||
fn from(value: &Value) -> Self {
|
||||
match value {
|
||||
Value::Null => Self::Null,
|
||||
Value::Integer(v) => Self::Integer(*v),
|
||||
Value::Float(v) => match NonNan::new(*v) {
|
||||
Some(v) => Self::Float(v),
|
||||
None => Self::Null,
|
||||
},
|
||||
Value::Text(text) => Numeric::from(text.as_str()),
|
||||
Value::Blob(blob) => {
|
||||
let text = String::from_utf8_lossy(blob.as_slice());
|
||||
Numeric::from(&text)
|
||||
}
|
||||
impl From<&SimValue> for ast::Literal {
|
||||
fn from(value: &SimValue) -> Self {
|
||||
match &value.0 {
|
||||
types::Value::Null => Self::Null,
|
||||
types::Value::Integer(i) => Self::Numeric(i.to_string()),
|
||||
types::Value::Float(f) => Self::Numeric(f.to_string()),
|
||||
text @ types::Value::Text(..) => Self::String(format!("'{}'", text)),
|
||||
types::Value::Blob(blob) => Self::Blob(hex::encode(blob)),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl From<bool> for Value {
|
||||
impl From<bool> for SimValue {
|
||||
fn from(value: bool) -> Self {
|
||||
value.then_some(Value::TRUE).unwrap_or(Value::FALSE)
|
||||
value.then_some(SimValue::TRUE).unwrap_or(SimValue::FALSE)
|
||||
}
|
||||
}
|
||||
|
||||
// NullableInteger Code copied from Core. Ideally we should use Limbo's Core Value for everything to avoid code repetition
|
||||
impl From<NullableInteger> for Value {
|
||||
fn from(value: NullableInteger) -> Self {
|
||||
match value {
|
||||
NullableInteger::Null => Value::Null,
|
||||
NullableInteger::Integer(v) => Value::Integer(v),
|
||||
}
|
||||
impl From<SimValue> for limbo_core::types::Value {
|
||||
fn from(value: SimValue) -> Self {
|
||||
value.0
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Value> for NullableInteger {
|
||||
fn from(value: Value) -> Self {
|
||||
Self::from(&value)
|
||||
impl From<&SimValue> for limbo_core::types::Value {
|
||||
fn from(value: &SimValue) -> Self {
|
||||
value.0.clone()
|
||||
}
|
||||
}
|
||||
|
||||
impl From<&Value> for NullableInteger {
|
||||
fn from(value: &Value) -> Self {
|
||||
match value {
|
||||
Value::Null => Self::Null,
|
||||
Value::Integer(v) => Self::Integer(*v),
|
||||
Value::Float(v) => Self::Integer(*v as i64),
|
||||
Value::Text(text) => Self::from(text.as_str()),
|
||||
Value::Blob(blob) => {
|
||||
let text = String::from_utf8_lossy(blob.as_slice());
|
||||
Self::from(text)
|
||||
}
|
||||
}
|
||||
impl From<limbo_core::types::Value> for SimValue {
|
||||
fn from(value: limbo_core::types::Value) -> Self {
|
||||
Self(value)
|
||||
}
|
||||
}
|
||||
|
||||
fn exec_bit_not(reg: &Value) -> Value {
|
||||
(!NullableInteger::from(reg)).into()
|
||||
impl From<&limbo_core::types::Value> for SimValue {
|
||||
fn from(value: &limbo_core::types::Value) -> Self {
|
||||
Self(value.clone())
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,11 +1,13 @@
|
|||
use std::sync::{Arc, Mutex};
|
||||
|
||||
use limbo_core::Value;
|
||||
|
||||
use crate::{
|
||||
generation::{
|
||||
pick_index,
|
||||
plan::{Interaction, InteractionPlanState, ResultSet},
|
||||
},
|
||||
model::{query::Query, table::Value},
|
||||
model::{query::Query, table::SimValue},
|
||||
runner::execution::ExecutionContinuation,
|
||||
InteractionPlan,
|
||||
};
|
||||
|
@ -60,7 +62,7 @@ pub(crate) fn run_simulation(
|
|||
fn execute_query_rusqlite(
|
||||
connection: &rusqlite::Connection,
|
||||
query: &Query,
|
||||
) -> rusqlite::Result<Vec<Vec<Value>>> {
|
||||
) -> rusqlite::Result<Vec<Vec<SimValue>>> {
|
||||
match query {
|
||||
Query::Create(create) => {
|
||||
connection.execute(create.to_string().as_str(), ())?;
|
||||
|
@ -73,13 +75,14 @@ fn execute_query_rusqlite(
|
|||
let mut values = vec![];
|
||||
for i in 0..columns {
|
||||
let value = row.get_unwrap(i);
|
||||
match value {
|
||||
rusqlite::types::Value::Null => values.push(Value::Null),
|
||||
rusqlite::types::Value::Integer(i) => values.push(Value::Integer(i)),
|
||||
rusqlite::types::Value::Real(f) => values.push(Value::Float(f)),
|
||||
rusqlite::types::Value::Text(s) => values.push(Value::Text(s)),
|
||||
rusqlite::types::Value::Blob(b) => values.push(Value::Blob(b)),
|
||||
}
|
||||
let value = match value {
|
||||
rusqlite::types::Value::Null => Value::Null,
|
||||
rusqlite::types::Value::Integer(i) => Value::Integer(i),
|
||||
rusqlite::types::Value::Real(f) => Value::Float(f),
|
||||
rusqlite::types::Value::Text(s) => Value::build_text(s),
|
||||
rusqlite::types::Value::Blob(b) => Value::Blob(b),
|
||||
};
|
||||
values.push(SimValue(value));
|
||||
}
|
||||
Ok(values)
|
||||
})?;
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue