is_null and not_null values

main
Ziyang Hu 2 years ago
parent 35c250d410
commit 5581f23e51

@ -354,6 +354,8 @@ impl<'s> Session<'s> {
value::OP_COALESCE => self.coalesce_values(args)?,
value::OP_NEGATE => self.negate_values(args)?,
value::OP_MINUS => self.minus_values(args)?,
value::METHOD_IS_NULL => self.is_null_values(args)?,
value::METHOD_NOT_NULL => self.not_null_values(args)?,
_ => { todo!() }
})
}
@ -457,6 +459,28 @@ impl<'s> Session<'s> {
_ => return Err(CozoError::InvalidArgument)
})
}
fn is_null_values<'a>(&self, args: Vec<Value<'a>>) -> Result<(bool, Value<'a>)> {
let mut args = args.into_iter();
let (le, left) = self.partial_eval(args.next().unwrap(), &Default::default(), &Default::default())?;
if left == Value::Null {
return Ok((true, true.into()));
}
if !le {
return Ok((false, Value::Apply(value::METHOD_IS_NULL.into(), vec![left])));
}
Ok((true, false.into()))
}
fn not_null_values<'a>(&self, args: Vec<Value<'a>>) -> Result<(bool, Value<'a>)> {
let mut args = args.into_iter();
let (le, left) = self.partial_eval(args.next().unwrap(), &Default::default(), &Default::default())?;
if left == Value::Null {
return Ok((true, false.into()));
}
if !le {
return Ok((false, Value::Apply(value::METHOD_NOT_NULL.into(), vec![left])));
}
Ok((true, true.into()))
}
fn pow_values<'a>(&self, args: Vec<Value<'a>>) -> Result<(bool, Value<'a>)> {
let mut args = args.into_iter();
let (le, left) = self.partial_eval(args.next().unwrap(), &Default::default(), &Default::default())?;

@ -234,7 +234,7 @@ mod tests {
assert_eq!(parsed.as_rule(), Rule::from_pattern);
sess.parse_from_pattern(parsed).unwrap();
let s = "where b.id > c.id, a.id == 5, x.name == 'Joe', x.name.len() == 3";
let s = "where b.id > c.id || x.name.is_null(), a.id == 5, x.name == 'Joe', x.name.len() == 3";
let parsed = Parser::parse(Rule::where_pattern, s).unwrap().next().unwrap();
let first = parsed.into_inner().next().unwrap();
println!("{:#?}", first);

@ -110,7 +110,7 @@ negate = { "!" }
term = { (grouping | literal | ident | param | list | dict) ~ (call | accessor | index_accessor)* }
call = {"." ~ ident ~ "(" ~ argument* ~ ")"}
accessor = {"." ~ ident}
index_accessor = {"[" ~ expr ~ "]"}
index_accessor = {"[" ~ int ~ "]"}
argument = _{(kw_arg | pos_arg)}
kw_arg = {ident ~ "=" ~ expr}
pos_arg = { expr }

@ -126,10 +126,10 @@ impl<'a> Value<'a> {
.collect::<BTreeMap<Cow<'static, str>, StaticValue>>().into(),
Value::EndSentinel => panic!("Cannot process sentinel value"),
Value::FieldAccess(field, value) => {
Value::FieldAccess(Cow::from(field.into_owned()),value.to_static().into())
Value::FieldAccess(Cow::from(field.into_owned()), value.to_static().into())
}
Value::IdxAccess(idx, value) => {
Value::IdxAccess(idx,value.to_static().into())
Value::IdxAccess(idx, value.to_static().into())
}
}
}
@ -350,6 +350,8 @@ pub const OP_POW: &str = "**";
pub const OP_COALESCE: &str = "~~";
pub const OP_NEGATE: &str = "!";
pub const OP_MINUS: &str = "--";
pub const METHOD_IS_NULL: &str = "is_null";
pub const METHOD_NOT_NULL: &str = "not_null";
fn build_expr_infix<'a>(lhs: Result<Value<'a>>, op: Pair<Rule>, rhs: Result<Value<'a>>) -> Result<Value<'a>> {
@ -387,7 +389,19 @@ fn build_expr_primary(pair: Pair<Rule>) -> Result<Value> {
match p.as_rule() {
Rule::accessor => {
let accessor_key = p.into_inner().next().unwrap().as_str();
head = Value::Apply(".".into(), vec![accessor_key.into()])
head = Value::FieldAccess(accessor_key.into(), head.into());
}
Rule::index_accessor => {
let accessor_key = p.into_inner().next().unwrap();
let accessor_idx = parse_int(accessor_key.as_str(), 10);
head = Value::IdxAccess(accessor_idx as usize, head.into());
}
Rule::call => {
let mut pairs = p.into_inner();
let method_name = pairs.next().unwrap().as_str();
let mut args = vec![head];
args.extend(pairs.map(build_expr_primary).collect::<Result<Vec<_>>>()?);
head = Value::Apply(method_name.into(), args);
}
_ => todo!()
}

Loading…
Cancel
Save