filtering iterator

main
Ziyang Hu 2 years ago
parent fef1d2c203
commit 79c59713fd

@ -13,96 +13,423 @@ use crate::relation::table::MegaTuple;
use crate::relation::value;
impl<'s> Session<'s> {
pub fn tuple_eval<'a>(&self, value: &'a Value<'a>, tuples: &'a MegaTuple) -> Result<Value<'a>> {
let res: Value = match value {
v @ (Value::Null |
Value::Bool(_) |
Value::Int(_) |
Value::Float(_) |
Value::Uuid(_) |
Value::Text(_)) => v.clone(),
Value::List(l) => {
let l = l.into_iter().map(|v| self.tuple_eval(v, tuples)).collect::<Result<Vec<_>>>()?;
Value::List(l)
}
Value::Dict(d) => {
let d = d.into_iter()
.map(|(k, v)|
self.tuple_eval(v, tuples).map(|v| (k.clone(), v)))
.collect::<Result<BTreeMap<_, _>>>()?;
Value::Dict(d)
}
Value::Variable(v) => {
return Err(LogicError(format!("Cannot resolve variable {}", v)));
}
Value::TupleRef(tid, cid) => {
let targets = if cid.is_key { &tuples.keys } else { &tuples.vals };
let target = targets.get(tid.id as usize).ok_or_else(|| {
LogicError("Tuple ref out of bound".to_string())
})?;
if matches!(target.data_kind(), Ok(DataKind::Empty)) {
Value::Null
} else {
target.get(cid.id as usize)
.ok_or_else(|| LogicError("Tuple ref out of bound".to_string()))?
}
pub fn tuple_eval<'a>(value: &'a Value<'a>, tuples: &'a MegaTuple) -> Result<Value<'a>> {
let res: Value = match value {
v @ (Value::Null |
Value::Bool(_) |
Value::Int(_) |
Value::Float(_) |
Value::Uuid(_) |
Value::Text(_)) => v.clone(),
Value::List(l) => {
let l = l.into_iter().map(|v| tuple_eval(v, tuples)).collect::<Result<Vec<_>>>()?;
Value::List(l)
}
Value::Dict(d) => {
let d = d.into_iter()
.map(|(k, v)|
tuple_eval(v, tuples).map(|v| (k.clone(), v)))
.collect::<Result<BTreeMap<_, _>>>()?;
Value::Dict(d)
}
Value::Variable(v) => {
return Err(LogicError(format!("Cannot resolve variable {}", v)));
}
Value::TupleRef(tid, cid) => {
let targets = if cid.is_key { &tuples.keys } else { &tuples.vals };
let target = targets.get(tid.id as usize).ok_or_else(|| {
LogicError("Tuple ref out of bound".to_string())
})?;
if matches!(target.data_kind(), Ok(DataKind::Empty)) {
Value::Null
} else {
target.get(cid.id as usize)
.ok_or_else(|| LogicError("Tuple ref out of bound".to_string()))?
}
Value::Apply(op, args) => {
match op.as_ref() {
value::OP_STR_CAT => self.str_cat_values(args, tuples)?,
value::OP_ADD => self.add_values(args, tuples)?,
value::OP_SUB => self.sub_values(args, tuples)?,
value::OP_MUL => self.mul_values(args, tuples)?,
value::OP_DIV => self.div_values(args, tuples)?,
value::OP_EQ => self.eq_values(args, tuples)?,
value::OP_NE => self.ne_values(args, tuples)?,
value::OP_OR => self.or_values(args, tuples)?,
value::OP_AND => self.and_values(args, tuples)?,
value::OP_MOD => self.mod_values(args, tuples)?,
value::OP_GT => self.gt_values(args, tuples)?,
value::OP_GE => self.ge_values(args, tuples)?,
value::OP_LT => self.lt_values(args, tuples)?,
value::OP_LE => self.le_values(args, tuples)?,
value::OP_POW => self.pow_values(args, tuples)?,
value::OP_COALESCE => self.coalesce_values(args, tuples)?,
value::OP_NEGATE => self.negate_values(args, tuples)?,
value::OP_MINUS => self.minus_values(args, tuples)?,
value::METHOD_IS_NULL => self.is_null_values(args, tuples)?,
value::METHOD_NOT_NULL => self.not_null_values(args, tuples)?,
value::METHOD_CONCAT => self.concat_values(args, tuples)?,
value::METHOD_MERGE => self.merge_values(args, tuples)?,
_ => { todo!() }
}
}
Value::Apply(op, args) => {
match op.as_ref() {
value::OP_STR_CAT => str_cat_values(args, tuples)?,
value::OP_ADD => add_values(args, tuples)?,
value::OP_SUB => sub_values(args, tuples)?,
value::OP_MUL => mul_values(args, tuples)?,
value::OP_DIV => div_values(args, tuples)?,
value::OP_EQ => eq_values(args, tuples)?,
value::OP_NE => ne_values(args, tuples)?,
value::OP_OR => or_values(args, tuples)?,
value::OP_AND => and_values(args, tuples)?,
value::OP_MOD => mod_values(args, tuples)?,
value::OP_GT => gt_values(args, tuples)?,
value::OP_GE => ge_values(args, tuples)?,
value::OP_LT => lt_values(args, tuples)?,
value::OP_LE => le_values(args, tuples)?,
value::OP_POW => pow_values(args, tuples)?,
value::OP_COALESCE => coalesce_values(args, tuples)?,
value::OP_NEGATE => negate_values(args, tuples)?,
value::OP_MINUS => minus_values(args, tuples)?,
value::METHOD_IS_NULL => is_null_values(args, tuples)?,
value::METHOD_NOT_NULL => not_null_values(args, tuples)?,
value::METHOD_CONCAT => concat_values(args, tuples)?,
value::METHOD_MERGE => merge_values(args, tuples)?,
_ => { todo!() }
}
Value::FieldAccess(field, arg) => {
let arg = self.tuple_eval(arg, tuples)?;
match arg {
Value::Dict(mut d) => {
d.remove(field.as_ref()).unwrap_or(Value::Null)
}
_ => return Err(LogicError("Field access failed".to_string()))
}
Value::FieldAccess(field, arg) => {
let arg = tuple_eval(arg, tuples)?;
match arg {
Value::Dict(mut d) => {
d.remove(field.as_ref()).unwrap_or(Value::Null)
}
_ => return Err(LogicError("Field access failed".to_string()))
}
Value::IdxAccess(idx, arg) => {
let arg = self.tuple_eval(arg, tuples)?;
match arg {
Value::List(mut l) => {
if *idx >= l.len() {
Value::Null
} else {
l.swap_remove(*idx)
}
}
Value::IdxAccess(idx, arg) => {
let arg = tuple_eval(arg, tuples)?;
match arg {
Value::List(mut l) => {
if *idx >= l.len() {
Value::Null
} else {
l.swap_remove(*idx)
}
_ => return Err(LogicError("Idx access failed".to_string()))
}
_ => return Err(LogicError("Idx access failed".to_string()))
}
Value::EndSentinel => {
return Err(LogicError("Encountered end sentinel".to_string()));
}
};
Ok(res)
}
Value::EndSentinel => {
return Err(LogicError("Encountered end sentinel".to_string()));
}
};
Ok(res)
}
fn coalesce_values<'a>(args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
for v in args {
match tuple_eval(v, tuples)? {
Value::Null => {}
v => return Ok(v)
}
}
Ok(Value::Null)
}
fn str_cat_values<'a>(args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut ret = String::new();
for v in args {
let v = tuple_eval(v, tuples)?;
match v {
Value::Null => return Ok(Value::Null),
Value::Text(s) => ret += s.as_ref(),
_ => return Err(InvalidArgument)
}
};
Ok(ret.into())
}
fn add_values<'a>(args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut args = args.into_iter();
let left = tuple_eval(args.next().unwrap(), tuples)?;
if left == Value::Null {
return Ok(Value::Null);
}
let right = tuple_eval(args.next().unwrap(), tuples)?;
if right == Value::Null {
return Ok(Value::Null);
}
Ok(match (left, right) {
(Value::Int(l), Value::Int(r)) => (l + r).into(),
(Value::Float(l), Value::Int(r)) => (l + (r as f64)).into(),
(Value::Int(l), Value::Float(r)) => ((l as f64) + r.into_inner()).into(),
(Value::Float(l), Value::Float(r)) => (l.into_inner() + r.into_inner()).into(),
(_, _) => return Err(CozoError::InvalidArgument)
})
}
fn sub_values<'a>(args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut args = args.into_iter();
let left = tuple_eval(args.next().unwrap(), tuples)?;
if left == Value::Null {
return Ok(Value::Null);
}
let right = tuple_eval(args.next().unwrap(), tuples)?;
if right == Value::Null {
return Ok(Value::Null);
}
Ok(match (left, right) {
(Value::Int(l), Value::Int(r)) => (l + r).into(),
(Value::Float(l), Value::Int(r)) => (l - (r as f64)).into(),
(Value::Int(l), Value::Float(r)) => ((l as f64) - r.into_inner()).into(),
(Value::Float(l), Value::Float(r)) => (l.into_inner() - r.into_inner()).into(),
(_, _) => return Err(CozoError::InvalidArgument)
})
}
fn minus_values<'a>(args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let left = tuple_eval(args.get(0).unwrap(), tuples)?;
Ok(match left {
Value::Int(l) => (-l).into(),
Value::Float(l) => (-l).into(),
_ => return Err(CozoError::InvalidArgument)
})
}
fn negate_values<'a>(args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let left = tuple_eval(args.get(0).unwrap(), tuples)?;
Ok(match left {
Value::Bool(l) => (!l).into(),
_ => return Err(CozoError::InvalidArgument)
})
}
fn is_null_values<'a>(args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let left = tuple_eval(args.get(0).unwrap(), tuples)?;
Ok((left == Value::Null).into())
}
fn not_null_values<'a>(args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let left = tuple_eval(args.get(0).unwrap(), tuples)?;
Ok((left != Value::Null).into())
}
fn pow_values<'a>(args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut args = args.into_iter();
let left = tuple_eval(args.next().unwrap(), tuples)?;
if left == Value::Null {
return Ok(Value::Null);
}
let right = tuple_eval(args.next().unwrap(), tuples)?;
if right == Value::Null {
return Ok(Value::Null);
}
Ok(match (left, right) {
(Value::Int(l), Value::Int(r)) => ((l as f64).powf(r as f64)).into(),
(Value::Float(l), Value::Int(r)) => ((l.into_inner()).powf(r as f64)).into(),
(Value::Int(l), Value::Float(r)) => ((l as f64).powf(r.into_inner())).into(),
(Value::Float(l), Value::Float(r)) => ((l.into_inner()).powf(r.into_inner())).into(),
(_, _) => return Err(CozoError::InvalidArgument)
})
}
fn gt_values<'a>(args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut args = args.into_iter();
let left = tuple_eval(args.next().unwrap(), tuples)?;
if left == Value::Null {
return Ok(Value::Null);
}
let right = tuple_eval(args.next().unwrap(), tuples)?;
if right == Value::Null {
return Ok(Value::Null);
}
Ok(match (left, right) {
(Value::Int(l), Value::Int(r)) => (l > r).into(),
(Value::Float(l), Value::Int(r)) => (l > (r as f64).into()).into(),
(Value::Int(l), Value::Float(r)) => ((l as f64) > r.into_inner()).into(),
(Value::Float(l), Value::Float(r)) => (l > r).into(),
(_, _) => return Err(CozoError::InvalidArgument)
})
}
fn lt_values<'a>(args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut args = args.into_iter();
let left = tuple_eval(args.next().unwrap(), tuples)?;
if left == Value::Null {
return Ok(Value::Null);
}
let right = tuple_eval(args.next().unwrap(), tuples)?;
if right == Value::Null {
return Ok(Value::Null);
}
Ok(match (left, right) {
(Value::Int(l), Value::Int(r)) => (l < r).into(),
(Value::Float(l), Value::Int(r)) => (l < (r as f64).into()).into(),
(Value::Int(l), Value::Float(r)) => ((l as f64) < r.into_inner()).into(),
(Value::Float(l), Value::Float(r)) => (l < r).into(),
(_, _) => return Err(CozoError::InvalidArgument)
})
}
fn ge_values<'a>(args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut args = args.into_iter();
let left = tuple_eval(args.next().unwrap(), tuples)?;
if left == Value::Null {
return Ok(Value::Null);
}
let right = tuple_eval(args.next().unwrap(), tuples)?;
if right == Value::Null {
return Ok(Value::Null);
}
Ok(match (left, right) {
(Value::Int(l), Value::Int(r)) => (l >= r).into(),
(Value::Float(l), Value::Int(r)) => (l >= (r as f64).into()).into(),
(Value::Int(l), Value::Float(r)) => ((l as f64) >= r.into_inner()).into(),
(Value::Float(l), Value::Float(r)) => (l >= r).into(),
(_, _) => return Err(CozoError::InvalidArgument)
})
}
fn le_values<'a>(args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut args = args.into_iter();
let left = tuple_eval(args.next().unwrap(), tuples)?;
if left == Value::Null {
return Ok(Value::Null);
}
let right = tuple_eval(args.next().unwrap(), tuples)?;
if right == Value::Null {
return Ok(Value::Null);
}
Ok(match (left, right) {
(Value::Int(l), Value::Int(r)) => (l <= r).into(),
(Value::Float(l), Value::Int(r)) => (l <= (r as f64).into()).into(),
(Value::Int(l), Value::Float(r)) => ((l as f64) <= r.into_inner()).into(),
(Value::Float(l), Value::Float(r)) => (l <= r).into(),
(_, _) => return Err(CozoError::InvalidArgument)
})
}
fn mod_values<'a>(args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut args = args.into_iter();
let left = tuple_eval(args.next().unwrap(), tuples)?;
if left == Value::Null {
return Ok(Value::Null);
}
let right = tuple_eval(args.next().unwrap(), tuples)?;
if right == Value::Null {
return Ok(Value::Null);
}
Ok(match (left, right) {
(Value::Int(l), Value::Int(r)) => (l % r).into(),
(_, _) => return Err(CozoError::InvalidArgument)
})
}
fn mul_values<'a>(args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut args = args.into_iter();
let left = tuple_eval(args.next().unwrap(), tuples)?;
if left == Value::Null {
return Ok(Value::Null);
}
let right = tuple_eval(args.next().unwrap(), tuples)?;
if right == Value::Null {
return Ok(Value::Null);
}
Ok(match (left, right) {
(Value::Int(l), Value::Int(r)) => (l * r).into(),
(Value::Float(l), Value::Int(r)) => (l * (r as f64)).into(),
(Value::Int(l), Value::Float(r)) => ((l as f64) * r.into_inner()).into(),
(Value::Float(l), Value::Float(r)) => (l.into_inner() * r.into_inner()).into(),
(_, _) => return Err(CozoError::InvalidArgument)
})
}
fn div_values<'a>(args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut args = args.into_iter();
let left = tuple_eval(args.next().unwrap(), tuples)?;
if left == Value::Null {
return Ok(Value::Null);
}
let right = tuple_eval(args.next().unwrap(), tuples)?;
if right == Value::Null {
return Ok(Value::Null);
}
Ok(match (left, right) {
(Value::Int(l), Value::Int(r)) => (l as f64 / r as f64).into(),
(Value::Float(l), Value::Int(r)) => (l / (r as f64)).into(),
(Value::Int(l), Value::Float(r)) => ((l as f64) / r.into_inner()).into(),
(Value::Float(l), Value::Float(r)) => (l.into_inner() / r.into_inner()).into(),
(_, _) => return Err(CozoError::InvalidArgument)
})
}
fn eq_values<'a>(args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut args = args.into_iter();
let left = tuple_eval(args.next().unwrap(), tuples)?;
if left == Value::Null {
return Ok(Value::Null);
}
let right = tuple_eval(args.next().unwrap(), tuples)?;
if right == Value::Null {
return Ok(Value::Null);
}
Ok((left == right).into())
}
fn ne_values<'a>(args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut args = args.into_iter();
let left = tuple_eval(args.next().unwrap(), tuples)?;
if left == Value::Null {
return Ok(Value::Null);
}
let right = tuple_eval(args.next().unwrap(), tuples)?;
if right == Value::Null {
return Ok(Value::Null);
}
Ok((left != right).into())
}
fn or_values<'a>(args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut accum = -1;
for v in args.into_iter() {
let v = tuple_eval(v, tuples)?;
match v {
Value::Null => accum = max(accum, 0),
Value::Bool(false) => {}
Value::Bool(true) => return Ok(true.into()),
_ => return Err(CozoError::InvalidArgument)
}
}
Ok(match accum {
-1 => false.into(),
0 => Value::Null,
_ => unreachable!()
})
}
fn concat_values<'a>(args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut coll = vec![];
for v in args.into_iter() {
let v = tuple_eval(v, tuples)?;
match v {
Value::Null => {}
Value::List(l) => coll.extend(l),
_ => return Err(CozoError::InvalidArgument)
}
}
Ok(coll.into())
}
fn merge_values<'a>(args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut coll = BTreeMap::new();
for v in args.into_iter() {
let v = tuple_eval(v, tuples)?;
match v {
Value::Null => {}
Value::Dict(d) => coll.extend(d),
_ => return Err(CozoError::InvalidArgument)
}
}
Ok(coll.into())
}
fn and_values<'a>(args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut accum = 1;
for v in args.into_iter() {
let v = tuple_eval(v, tuples)?;
match v {
Value::Null => accum = min(accum, 0),
Value::Bool(true) => {}
Value::Bool(false) => return Ok(false.into()),
_ => return Err(CozoError::InvalidArgument)
}
}
Ok(match accum {
1 => true.into(),
0 => Value::Null,
_ => unreachable!()
})
}
impl<'s> Session<'s> {
pub fn partial_cnf_eval<'a>(&self, mut value: Value<'a>, params: &BTreeMap<String, Value<'a>>,
table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> {
loop {
@ -274,16 +601,6 @@ impl<'s> Session<'s> {
}
impl<'s> Session<'s> {
fn coalesce_values<'a>(&self, args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
for v in args {
match self.tuple_eval(v, tuples)? {
Value::Null => {}
v => return Ok(v)
}
}
Ok(Value::Null)
}
fn coalesce_values_partial<'a>(&self, args: Vec<Value<'a>>, params: &BTreeMap<String, Value<'a>>,
table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> {
let res = args.into_iter().try_fold(vec![], |mut accum, cur| {
@ -318,19 +635,6 @@ impl<'s> Session<'s> {
}
}
fn str_cat_values<'a>(&self, args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut ret = String::new();
for v in args {
let v = self.tuple_eval(v, tuples)?;
match v {
Value::Null => return Ok(Value::Null),
Value::Text(s) => ret += s.as_ref(),
_ => return Err(InvalidArgument)
}
};
Ok(ret.into())
}
fn str_cat_values_partial<'a>(&self, args: Vec<Value<'a>>, params: &BTreeMap<String, Value<'a>>,
table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> {
let mut args = args.into_iter();
@ -348,25 +652,6 @@ impl<'s> Session<'s> {
})
}
fn add_values<'a>(&self, args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut args = args.into_iter();
let left = self.tuple_eval(args.next().unwrap(), tuples)?;
if left == Value::Null {
return Ok(Value::Null);
}
let right = self.tuple_eval(args.next().unwrap(), tuples)?;
if right == Value::Null {
return Ok(Value::Null);
}
Ok(match (left, right) {
(Value::Int(l), Value::Int(r)) => (l + r).into(),
(Value::Float(l), Value::Int(r)) => (l + (r as f64)).into(),
(Value::Int(l), Value::Float(r)) => ((l as f64) + r.into_inner()).into(),
(Value::Float(l), Value::Float(r)) => (l.into_inner() + r.into_inner()).into(),
(_, _) => return Err(CozoError::InvalidArgument)
})
}
fn add_values_partial<'a>(&self, args: Vec<Value<'a>>, params: &BTreeMap<String, Value<'a>>,
table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> {
let mut args = args.into_iter();
@ -387,25 +672,6 @@ impl<'s> Session<'s> {
})
}
fn sub_values<'a>(&self, args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut args = args.into_iter();
let left = self.tuple_eval(args.next().unwrap(), tuples)?;
if left == Value::Null {
return Ok(Value::Null);
}
let right = self.tuple_eval(args.next().unwrap(), tuples)?;
if right == Value::Null {
return Ok(Value::Null);
}
Ok(match (left, right) {
(Value::Int(l), Value::Int(r)) => (l + r).into(),
(Value::Float(l), Value::Int(r)) => (l - (r as f64)).into(),
(Value::Int(l), Value::Float(r)) => ((l as f64) - r.into_inner()).into(),
(Value::Float(l), Value::Float(r)) => (l.into_inner() - r.into_inner()).into(),
(_, _) => return Err(CozoError::InvalidArgument)
})
}
fn sub_values_partial<'a>(&self, args: Vec<Value<'a>>, params: &BTreeMap<String, Value<'a>>,
table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> {
let mut args = args.into_iter();
@ -426,15 +692,6 @@ impl<'s> Session<'s> {
})
}
fn minus_values<'a>(&self, args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let left = self.tuple_eval(args.get(0).unwrap(), tuples)?;
Ok(match left {
Value::Int(l) => (-l).into(),
Value::Float(l) => (-l).into(),
_ => return Err(CozoError::InvalidArgument)
})
}
fn minus_values_partial<'a>(&self, args: Vec<Value<'a>>, params: &BTreeMap<String, Value<'a>>,
table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> {
let mut args = args.into_iter();
@ -452,14 +709,6 @@ impl<'s> Session<'s> {
})
}
fn negate_values<'a>(&self, args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let left = self.tuple_eval(args.get(0).unwrap(), tuples)?;
Ok(match left {
Value::Bool(l) => (!l).into(),
_ => return Err(CozoError::InvalidArgument)
})
}
fn negate_values_partial<'a>(&self, args: Vec<Value<'a>>, params: &BTreeMap<String, Value<'a>>,
table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> {
let mut args = args.into_iter();
@ -476,11 +725,6 @@ impl<'s> Session<'s> {
})
}
fn is_null_values<'a>(&self, args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let left = self.tuple_eval(args.get(0).unwrap(), tuples)?;
Ok((left == Value::Null).into())
}
fn is_null_values_partial<'a>(&self, args: Vec<Value<'a>>, params: &BTreeMap<String, Value<'a>>,
table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> {
let mut args = args.into_iter();
@ -494,11 +738,6 @@ impl<'s> Session<'s> {
Ok((true, false.into()))
}
fn not_null_values<'a>(&self, args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let left = self.tuple_eval(args.get(0).unwrap(), tuples)?;
Ok((left != Value::Null).into())
}
fn not_null_values_partial<'a>(&self, args: Vec<Value<'a>>, params: &BTreeMap<String, Value<'a>>,
table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> {
let mut args = args.into_iter();
@ -512,25 +751,6 @@ impl<'s> Session<'s> {
Ok((true, true.into()))
}
fn pow_values<'a>(&self, args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut args = args.into_iter();
let left = self.tuple_eval(args.next().unwrap(), tuples)?;
if left == Value::Null {
return Ok(Value::Null);
}
let right = self.tuple_eval(args.next().unwrap(), tuples)?;
if right == Value::Null {
return Ok(Value::Null);
}
Ok(match (left, right) {
(Value::Int(l), Value::Int(r)) => ((l as f64).powf(r as f64)).into(),
(Value::Float(l), Value::Int(r)) => ((l.into_inner()).powf(r as f64)).into(),
(Value::Int(l), Value::Float(r)) => ((l as f64).powf(r.into_inner())).into(),
(Value::Float(l), Value::Float(r)) => ((l.into_inner()).powf(r.into_inner())).into(),
(_, _) => return Err(CozoError::InvalidArgument)
})
}
fn pow_values_partial<'a>(&self, args: Vec<Value<'a>>, params: &BTreeMap<String, Value<'a>>,
table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> {
let mut args = args.into_iter();
@ -551,25 +771,6 @@ impl<'s> Session<'s> {
})
}
fn gt_values<'a>(&self, args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut args = args.into_iter();
let left = self.tuple_eval(args.next().unwrap(), tuples)?;
if left == Value::Null {
return Ok(Value::Null);
}
let right = self.tuple_eval(args.next().unwrap(), tuples)?;
if right == Value::Null {
return Ok(Value::Null);
}
Ok(match (left, right) {
(Value::Int(l), Value::Int(r)) => (l > r).into(),
(Value::Float(l), Value::Int(r)) => (l > (r as f64).into()).into(),
(Value::Int(l), Value::Float(r)) => ((l as f64) > r.into_inner()).into(),
(Value::Float(l), Value::Float(r)) => (l > r).into(),
(_, _) => return Err(CozoError::InvalidArgument)
})
}
fn gt_values_partial<'a>(&self, args: Vec<Value<'a>>, params: &BTreeMap<String, Value<'a>>,
table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> {
let mut args = args.into_iter();
@ -590,25 +791,6 @@ impl<'s> Session<'s> {
})
}
fn lt_values<'a>(&self, args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut args = args.into_iter();
let left = self.tuple_eval(args.next().unwrap(), tuples)?;
if left == Value::Null {
return Ok(Value::Null);
}
let right = self.tuple_eval(args.next().unwrap(), tuples)?;
if right == Value::Null {
return Ok(Value::Null);
}
Ok(match (left, right) {
(Value::Int(l), Value::Int(r)) => (l < r).into(),
(Value::Float(l), Value::Int(r)) => (l < (r as f64).into()).into(),
(Value::Int(l), Value::Float(r)) => ((l as f64) < r.into_inner()).into(),
(Value::Float(l), Value::Float(r)) => (l < r).into(),
(_, _) => return Err(CozoError::InvalidArgument)
})
}
fn lt_values_partial<'a>(&self, args: Vec<Value<'a>>, params: &BTreeMap<String, Value<'a>>,
table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> {
let mut args = args.into_iter();
@ -629,25 +811,6 @@ impl<'s> Session<'s> {
})
}
fn ge_values<'a>(&self, args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut args = args.into_iter();
let left = self.tuple_eval(args.next().unwrap(), tuples)?;
if left == Value::Null {
return Ok(Value::Null);
}
let right = self.tuple_eval(args.next().unwrap(), tuples)?;
if right == Value::Null {
return Ok(Value::Null);
}
Ok(match (left, right) {
(Value::Int(l), Value::Int(r)) => (l >= r).into(),
(Value::Float(l), Value::Int(r)) => (l >= (r as f64).into()).into(),
(Value::Int(l), Value::Float(r)) => ((l as f64) >= r.into_inner()).into(),
(Value::Float(l), Value::Float(r)) => (l >= r).into(),
(_, _) => return Err(CozoError::InvalidArgument)
})
}
fn ge_values_partial<'a>(&self, args: Vec<Value<'a>>, params: &BTreeMap<String, Value<'a>>,
table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> {
let mut args = args.into_iter();
@ -668,25 +831,6 @@ impl<'s> Session<'s> {
})
}
fn le_values<'a>(&self, args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut args = args.into_iter();
let left = self.tuple_eval(args.next().unwrap(), tuples)?;
if left == Value::Null {
return Ok(Value::Null);
}
let right = self.tuple_eval(args.next().unwrap(), tuples)?;
if right == Value::Null {
return Ok(Value::Null);
}
Ok(match (left, right) {
(Value::Int(l), Value::Int(r)) => (l <= r).into(),
(Value::Float(l), Value::Int(r)) => (l <= (r as f64).into()).into(),
(Value::Int(l), Value::Float(r)) => ((l as f64) <= r.into_inner()).into(),
(Value::Float(l), Value::Float(r)) => (l <= r).into(),
(_, _) => return Err(CozoError::InvalidArgument)
})
}
fn le_values_partial<'a>(&self, args: Vec<Value<'a>>, params: &BTreeMap<String, Value<'a>>,
table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> {
let mut args = args.into_iter();
@ -707,22 +851,6 @@ impl<'s> Session<'s> {
})
}
fn mod_values<'a>(&self, args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut args = args.into_iter();
let left = self.tuple_eval(args.next().unwrap(), tuples)?;
if left == Value::Null {
return Ok(Value::Null);
}
let right = self.tuple_eval(args.next().unwrap(), tuples)?;
if right == Value::Null {
return Ok(Value::Null);
}
Ok(match (left, right) {
(Value::Int(l), Value::Int(r)) => (l % r).into(),
(_, _) => return Err(CozoError::InvalidArgument)
})
}
fn mod_values_partial<'a>(&self, args: Vec<Value<'a>>, params: &BTreeMap<String, Value<'a>>,
table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> {
let mut args = args.into_iter();
@ -740,25 +868,6 @@ impl<'s> Session<'s> {
})
}
fn mul_values<'a>(&self, args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut args = args.into_iter();
let left = self.tuple_eval(args.next().unwrap(), tuples)?;
if left == Value::Null {
return Ok(Value::Null);
}
let right = self.tuple_eval(args.next().unwrap(), tuples)?;
if right == Value::Null {
return Ok(Value::Null);
}
Ok(match (left, right) {
(Value::Int(l), Value::Int(r)) => (l * r).into(),
(Value::Float(l), Value::Int(r)) => (l * (r as f64)).into(),
(Value::Int(l), Value::Float(r)) => ((l as f64) * r.into_inner()).into(),
(Value::Float(l), Value::Float(r)) => (l.into_inner() * r.into_inner()).into(),
(_, _) => return Err(CozoError::InvalidArgument)
})
}
fn mul_values_partial<'a>(&self, args: Vec<Value<'a>>, params: &BTreeMap<String, Value<'a>>,
table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> {
let mut args = args.into_iter();
@ -779,25 +888,6 @@ impl<'s> Session<'s> {
})
}
fn div_values<'a>(&self, args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut args = args.into_iter();
let left = self.tuple_eval(args.next().unwrap(), tuples)?;
if left == Value::Null {
return Ok(Value::Null);
}
let right = self.tuple_eval(args.next().unwrap(), tuples)?;
if right == Value::Null {
return Ok(Value::Null);
}
Ok(match (left, right) {
(Value::Int(l), Value::Int(r)) => (l as f64 / r as f64).into(),
(Value::Float(l), Value::Int(r)) => (l / (r as f64)).into(),
(Value::Int(l), Value::Float(r)) => ((l as f64) / r.into_inner()).into(),
(Value::Float(l), Value::Float(r)) => (l.into_inner() / r.into_inner()).into(),
(_, _) => return Err(CozoError::InvalidArgument)
})
}
fn div_values_partial<'a>(&self, args: Vec<Value<'a>>, params: &BTreeMap<String, Value<'a>>,
table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> {
let mut args = args.into_iter();
@ -818,19 +908,6 @@ impl<'s> Session<'s> {
})
}
fn eq_values<'a>(&self, args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut args = args.into_iter();
let left = self.tuple_eval(args.next().unwrap(), tuples)?;
if left == Value::Null {
return Ok(Value::Null);
}
let right = self.tuple_eval(args.next().unwrap(), tuples)?;
if right == Value::Null {
return Ok(Value::Null);
}
Ok((left == right).into())
}
fn eq_values_partial<'a>(&self, args: Vec<Value<'a>>, params: &BTreeMap<String, Value<'a>>,
table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> {
let mut args = args.into_iter();
@ -845,19 +922,6 @@ impl<'s> Session<'s> {
Ok((true, (left == right).into()))
}
fn ne_values<'a>(&self, args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut args = args.into_iter();
let left = self.tuple_eval(args.next().unwrap(), tuples)?;
if left == Value::Null {
return Ok(Value::Null);
}
let right = self.tuple_eval(args.next().unwrap(), tuples)?;
if right == Value::Null {
return Ok(Value::Null);
}
Ok((left != right).into())
}
fn ne_values_partial<'a>(&self, args: Vec<Value<'a>>, params: &BTreeMap<String, Value<'a>>,
table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> {
let mut args = args.into_iter();
@ -872,24 +936,6 @@ impl<'s> Session<'s> {
Ok((true, (left != right).into()))
}
fn or_values<'a>(&self, args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut accum = -1;
for v in args.into_iter() {
let v = self.tuple_eval(v, tuples)?;
match v {
Value::Null => accum = max(accum, 0),
Value::Bool(false) => {}
Value::Bool(true) => return Ok(true.into()),
_ => return Err(CozoError::InvalidArgument)
}
}
Ok(match accum {
-1 => false.into(),
0 => Value::Null,
_ => unreachable!()
})
}
fn or_values_partial<'a>(&self, args: Vec<Value<'a>>, params: &BTreeMap<String, Value<'a>>,
table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> {
let res = args.into_iter().map(|v| self.partial_eval(v, params, table_bindings))
@ -957,19 +1003,6 @@ impl<'s> Session<'s> {
}
}
fn concat_values<'a>(&self, args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut coll = vec![];
for v in args.into_iter() {
let v = self.tuple_eval(v, tuples)?;
match v {
Value::Null => {}
Value::List(l) => coll.extend(l),
_ => return Err(CozoError::InvalidArgument)
}
}
Ok(coll.into())
}
fn concat_values_partial<'a>(&self, args: Vec<Value<'a>>, params: &BTreeMap<String, Value<'a>>,
table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> {
let mut total_ret = vec![];
@ -1012,19 +1045,6 @@ impl<'s> Session<'s> {
}
}
fn merge_values<'a>(&self, args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut coll = BTreeMap::new();
for v in args.into_iter() {
let v = self.tuple_eval(v, tuples)?;
match v {
Value::Null => {}
Value::Dict(d) => coll.extend(d),
_ => return Err(CozoError::InvalidArgument)
}
}
Ok(coll.into())
}
fn merge_values_partial<'a>(&self, args: Vec<Value<'a>>, params: &BTreeMap<String, Value<'a>>,
table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> {
let mut total_ret = vec![];
@ -1067,24 +1087,6 @@ impl<'s> Session<'s> {
}
}
fn and_values<'a>(&self, args: &'a [Value<'a>], tuples: &'a MegaTuple) -> Result<Value<'a>> {
let mut accum = 1;
for v in args.into_iter() {
let v = self.tuple_eval(v, tuples)?;
match v {
Value::Null => accum = min(accum, 0),
Value::Bool(true) => {}
Value::Bool(false) => return Ok(false.into()),
_ => return Err(CozoError::InvalidArgument)
}
}
Ok(match accum {
1 => true.into(),
0 => Value::Null,
_ => unreachable!()
})
}
fn and_values_partial<'a>(&self, args: Vec<Value<'a>>, params: &BTreeMap<String, Value<'a>>,
table_bindings: &AccessorMap) -> Result<(bool, Value<'a>)> {
let res = args.into_iter().map(|v| self.partial_eval(v, params, table_bindings))

@ -4,11 +4,13 @@ use std::cmp::Ordering;
use pest::iterators::Pair;
use cozorocks::{IteratorPtr};
use crate::db::engine::Session;
use crate::db::eval::tuple_eval;
use crate::db::query::{FromEl, Selection};
use crate::db::table::{ColId, TableId, TableInfo};
use crate::error::CozoError::LogicError;
use crate::relation::value::{StaticValue, Value};
use crate::parser::Rule;
use crate::error::Result;
use crate::error::{Result};
use crate::relation::data::{DataKind, EMPTY_DATA};
use crate::relation::table::MegaTuple;
use crate::relation::tuple::{CowSlice, CowTuple, OwnTuple, Tuple};
@ -160,6 +162,7 @@ pub enum MegaTupleIt<'a> {
KeySortedWithAssocIt { main: Box<MegaTupleIt<'a>>, associates: Vec<(u32, IteratorPtr<'a>)> },
CartesianProdIt { left: Box<MegaTupleIt<'a>>, right: Box<MegaTupleIt<'a>> },
MergeJoinIt { left: Box<MegaTupleIt<'a>>, right: Box<MegaTupleIt<'a>>, left_keys: Vec<(TableId, ColId)>, right_keys: Vec<(TableId, ColId)> },
FilterIt { it: Box<MegaTupleIt<'a>>, filter: Value<'a> },
}
impl<'a> MegaTupleIt<'a> {
@ -218,6 +221,12 @@ impl<'a> MegaTupleIt<'a> {
})
}
MegaTupleIt::MergeJoinIt { .. } => todo!(),
MegaTupleIt::FilterIt { it, filter } => {
Box::new(FilterIterator {
it: Box::new(it.iter()),
filter,
})
}
}
}
}
@ -326,7 +335,10 @@ impl<'a> Iterator for KeySortedWithAssocIterator<'a> {
Some(Err(e)) => return Some(Err(e)),
Some(Ok(MegaTuple { mut keys, mut vals })) => {
// extract key from main
let k = keys.pop().unwrap();
let k = match keys.pop() {
None => return Some(Err(LogicError("Empty keys".to_string()))),
Some(k) => k
};
let l = self.associates.len();
// initialize vector for associate values
let mut assoc_vals: Vec<Option<CowTuple>> = iter::repeat_with(|| None).take(l).collect();
@ -447,6 +459,34 @@ impl<'a> Iterator for CartesianProdIterator<'a> {
}
}
pub struct FilterIterator<'a> {
it: Box<dyn Iterator<Item=Result<MegaTuple>> + 'a>,
filter: &'a Value<'a>,
}
impl<'a> Iterator for FilterIterator<'a> {
type Item = Result<MegaTuple>;
fn next(&mut self) -> Option<Self::Item> {
for t in self.it.by_ref() {
match t {
Ok(t) => {
match tuple_eval(self.filter, &t) {
Ok(Value::Bool(true)) => {
return Some(Ok(t));
}
Ok(Value::Bool(false)) | Ok(Value::Null) => {}
Ok(_v) => return Some(Err(LogicError("Unexpected type in filter".to_string()))),
Err(e) => return Some(Err(e))
}
}
Err(e) => return Some(Err(e))
}
}
None
}
}
#[cfg(test)]
mod tests {
@ -456,6 +496,7 @@ mod tests {
use crate::db::engine::Engine;
use crate::parser::{Parser, Rule};
use pest::Parser as PestParser;
use crate::db::eval::tuple_eval;
use crate::db::plan::{MegaTupleIt};
use crate::db::query::FromEl;
use crate::relation::value::Value;
@ -528,19 +569,20 @@ mod tests {
let tbl = rel_tbls.pop().unwrap();
let it = sess.iter_node(tbl);
let it = MegaTupleIt::FilterIt { filter: where_vals, it: it.into() };
for tuple in it.iter() {
let tuple = tuple.unwrap();
match sess.tuple_eval(&where_vals, &tuple).unwrap() {
Value::Bool(true) => {
let extracted = sess.tuple_eval(&vals, &tuple).unwrap();
println!("{}", extracted);
}
Value::Null |
Value::Bool(_) => {
println!(" Ignore {:?}", &tuple);
}
_ => panic!("Bad type")
}
// match tuple_eval(&where_vals, &tuple).unwrap() {
// Value::Bool(true) => {
let extracted = tuple_eval(&vals, &tuple).unwrap();
println!("{}", extracted);
// }
// Value::Null |
// Value::Bool(_) => {
// println!(" Ignore {:?}", &tuple);
// }
// _ => panic!("Bad type")
// }
}
let duration = start.elapsed();
let duration2 = start2.elapsed();
@ -576,9 +618,9 @@ mod tests {
let mut n = 0;
for el in it.iter() {
let el = el.unwrap();
if n % 4096 == 0 {
println!("{}: {:?}", n, el)
}
// if n % 4096 == 0 {
// println!("{}: {:?}", n, el)
// }
let _x = el.keys.into_iter().map(|v| v.iter().map(|_v| ()).collect::<Vec<_>>()).collect::<Vec<_>>();
let _y = el.vals.into_iter().map(|v| v.iter().map(|_v| ()).collect::<Vec<_>>()).collect::<Vec<_>>();
n += 1;

Loading…
Cancel
Save