Feature #2720 - add remainder aka modulo operator. (#2868)

This commit is contained in:
Finn Bear 2023-10-23 06:37:21 -07:00 committed by GitHub
parent f185c595f4
commit 4c1ceac6eb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
6 changed files with 35 additions and 9 deletions

View file

@ -547,6 +547,10 @@ pub enum Error {
#[error("Cannot perform division with '{0}' and '{1}'")] #[error("Cannot perform division with '{0}' and '{1}'")]
TryDiv(String, String), TryDiv(String, String),
/// Cannot perform remainder
#[error("Cannot perform remainder with '{0}' and '{1}'")]
TryRem(String, String),
/// Cannot perform power /// Cannot perform power
#[error("Cannot raise the value '{0}' with '{1}'")] #[error("Cannot raise the value '{0}' with '{1}'")]
TryPow(String, String), TryPow(String, String),

View file

@ -3,13 +3,7 @@ use crate::dbs::Transaction;
use crate::doc::CursorDoc; use crate::doc::CursorDoc;
use crate::err::Error; use crate::err::Error;
use crate::idx::planner::executor::QueryExecutor; use crate::idx::planner::executor::QueryExecutor;
use crate::sql::value::TryAdd; use crate::sql::value::{TryAdd, TryDiv, TryMul, TryNeg, TryPow, TryRem, TrySub, Value};
use crate::sql::value::TryDiv;
use crate::sql::value::TryMul;
use crate::sql::value::TryNeg;
use crate::sql::value::TryPow;
use crate::sql::value::TrySub;
use crate::sql::value::Value;
use crate::sql::{Expression, Thing}; use crate::sql::{Expression, Thing};
pub fn neg(a: Value) -> Result<Value, Error> { pub fn neg(a: Value) -> Result<Value, Error> {
@ -64,6 +58,10 @@ pub fn div(a: Value, b: Value) -> Result<Value, Error> {
a.try_div(b) a.try_div(b)
} }
pub fn rem(a: Value, b: Value) -> Result<Value, Error> {
a.try_rem(b)
}
pub fn pow(a: Value, b: Value) -> Result<Value, Error> { pub fn pow(a: Value, b: Value) -> Result<Value, Error> {
a.try_pow(b) a.try_pow(b)
} }

View file

@ -164,6 +164,7 @@ impl Expression {
Operator::Sub => fnc::operate::sub(l, r), Operator::Sub => fnc::operate::sub(l, r),
Operator::Mul => fnc::operate::mul(l, r), Operator::Mul => fnc::operate::mul(l, r),
Operator::Div => fnc::operate::div(l, r), Operator::Div => fnc::operate::div(l, r),
Operator::Rem => fnc::operate::rem(l, r),
Operator::Pow => fnc::operate::pow(l, r), Operator::Pow => fnc::operate::pow(l, r),
Operator::Equal => fnc::operate::equal(&l, &r), Operator::Equal => fnc::operate::equal(&l, &r),
Operator::Exact => fnc::operate::exact(&l, &r), Operator::Exact => fnc::operate::exact(&l, &r),

View file

@ -1,4 +1,4 @@
use super::value::{TryAdd, TryDiv, TryMul, TryNeg, TryPow, TrySub}; use super::value::{TryAdd, TryDiv, TryMul, TryNeg, TryPow, TryRem, TrySub};
use crate::err::Error; use crate::err::Error;
use crate::sql::ending::number as ending; use crate::sql::ending::number as ending;
use crate::sql::error::{IResult, ParseError}; use crate::sql::error::{IResult, ParseError};
@ -17,7 +17,7 @@ use std::fmt::{self, Display, Formatter};
use std::hash; use std::hash;
use std::iter::Product; use std::iter::Product;
use std::iter::Sum; use std::iter::Sum;
use std::ops::{self, Add, Div, Mul, Neg, Sub}; use std::ops::{self, Add, Div, Mul, Neg, Rem, Sub};
use std::str::FromStr; use std::str::FromStr;
pub(crate) const TOKEN: &str = "$surrealdb::private::sql::Number"; pub(crate) const TOKEN: &str = "$surrealdb::private::sql::Number";
@ -504,6 +504,7 @@ impl_simple_try_op!(TryAdd, try_add, add, checked_add);
impl_simple_try_op!(TrySub, try_sub, sub, checked_sub); impl_simple_try_op!(TrySub, try_sub, sub, checked_sub);
impl_simple_try_op!(TryMul, try_mul, mul, checked_mul); impl_simple_try_op!(TryMul, try_mul, mul, checked_mul);
impl_simple_try_op!(TryDiv, try_div, div, checked_div); impl_simple_try_op!(TryDiv, try_div, div, checked_div);
impl_simple_try_op!(TryRem, try_rem, rem, checked_rem);
impl TryPow for Number { impl TryPow for Number {
type Output = Self; type Output = Self;

View file

@ -70,6 +70,8 @@ pub enum Operator {
Intersects, Intersects,
// //
Knn(u32), // <{k}> Knn(u32), // <{k}>
//
Rem, // %
} }
impl Default for Operator { impl Default for Operator {
@ -90,6 +92,7 @@ impl Operator {
Self::Add => 7, Self::Add => 7,
Self::Mul => 8, Self::Mul => 8,
Self::Div => 9, Self::Div => 9,
Self::Rem => 10,
_ => 5, _ => 5,
} }
} }
@ -108,6 +111,7 @@ impl fmt::Display for Operator {
Self::Sub => f.write_char('-'), Self::Sub => f.write_char('-'),
Self::Mul => f.write_char('*'), Self::Mul => f.write_char('*'),
Self::Div => f.write_char('/'), Self::Div => f.write_char('/'),
Self::Rem => f.write_char('%'),
Self::Pow => f.write_str("**"), Self::Pow => f.write_str("**"),
Self::Inc => f.write_str("+="), Self::Inc => f.write_str("+="),
Self::Dec => f.write_str("-="), Self::Dec => f.write_str("-="),
@ -213,6 +217,7 @@ pub fn binary_symbols(i: &str) -> IResult<&str, Operator> {
value(Operator::Mul, char('∙')), value(Operator::Mul, char('∙')),
value(Operator::Div, char('/')), value(Operator::Div, char('/')),
value(Operator::Div, char('÷')), value(Operator::Div, char('÷')),
value(Operator::Rem, char('%')),
)), )),
alt(( alt((
value(Operator::Contain, char('∋')), value(Operator::Contain, char('∋')),

View file

@ -2694,6 +2694,23 @@ impl TryDiv for Value {
// ------------------------------ // ------------------------------
pub(crate) trait TryRem<Rhs = Self> {
type Output;
fn try_rem(self, v: Self) -> Result<Self::Output, Error>;
}
impl TryRem for Value {
type Output = Self;
fn try_rem(self, other: Self) -> Result<Self, Error> {
Ok(match (self, other) {
(Self::Number(v), Self::Number(w)) => Self::Number(v.try_rem(w)?),
(v, w) => return Err(Error::TryRem(v.to_raw_string(), w.to_raw_string())),
})
}
}
// ------------------------------
pub(crate) trait TryPow<Rhs = Self> { pub(crate) trait TryPow<Rhs = Self> {
type Output; type Output;
fn try_pow(self, v: Self) -> Result<Self::Output, Error>; fn try_pow(self, v: Self) -> Result<Self::Output, Error>;