Skip to content

Commit

Permalink
Add support for interval * and /operators.
Browse files Browse the repository at this point in the history
  • Loading branch information
AmrDeveloper committed Jan 17, 2025
1 parent 9e5b540 commit f5b7284
Show file tree
Hide file tree
Showing 3 changed files with 61 additions and 3 deletions.
30 changes: 27 additions & 3 deletions crates/gitql-ast/src/interval.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
use std::cmp::Ordering;
use std::fmt::Display;
use std::fmt::Formatter;
use std::ops::Div;
use std::ops::Mul;

const INTERVAL_MAX_VALUE_I: i64 = 170_000_000;
const INTERVAL_MAX_VALUE_F: f64 = 170_000_000.0;
Expand Down Expand Up @@ -38,6 +40,28 @@ impl Interval {
Ok(result)
}

pub fn mul(&self, other: i64) -> Result<Interval, String> {
let mut result = self.clone();
result.years = interval_value_or_error_i64(result.years * other)?;
result.months = interval_value_or_error_i64(result.months * other)?;
result.days = interval_value_or_error_i64(result.days * other)?;
result.hours = interval_value_or_error_i64(result.hours * other)?;
result.minutes = interval_value_or_error_i64(result.minutes * other)?;
result.seconds = interval_value_or_error_f64(result.seconds.mul(other as f64))?;
Ok(result)
}

pub fn div(&self, other: i64) -> Result<Interval, String> {
let mut result = self.clone();
result.years = interval_value_or_error_i64(result.years / other)?;
result.months = interval_value_or_error_i64(result.months / other)?;
result.days = interval_value_or_error_i64(result.days / other)?;
result.hours = interval_value_or_error_i64(result.hours / other)?;
result.minutes = interval_value_or_error_i64(result.minutes / other)?;
result.seconds = interval_value_or_error_f64(result.seconds.div(other as f64))?;
Ok(result)
}

pub fn to_seconds(&self) -> i64 {
let days =
self.years as f64 * 365.25 + self.months as f64 * (365.25 / 12.0) + self.days as f64;
Expand Down Expand Up @@ -111,14 +135,14 @@ impl Display for Interval {
}

fn interval_value_or_error_i64(value: i64) -> Result<i64, String> {
if !(-INTERVAL_MAX_VALUE_I..=INTERVAL_MAX_VALUE_I).contains(&value) {
if (-INTERVAL_MAX_VALUE_I..=INTERVAL_MAX_VALUE_I).contains(&value) {
return Ok(value);
}
Err("Interval value out of range".to_string())
Err(format!("Interval value out of range {}", value))
}

fn interval_value_or_error_f64(value: f64) -> Result<f64, String> {
if !(-INTERVAL_MAX_VALUE_F..=INTERVAL_MAX_VALUE_F).contains(&value) {
if (-INTERVAL_MAX_VALUE_F..=INTERVAL_MAX_VALUE_F).contains(&value) {
return Ok(value);
}
Err("Interval value out of range".to_string())
Expand Down
18 changes: 18 additions & 0 deletions crates/gitql-ast/src/types/interval.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
use std::any::Any;

use crate::types::integer::IntType;

use super::base::DataType;

#[derive(Clone)]
Expand Down Expand Up @@ -57,4 +59,20 @@ impl DataType for IntervalType {
fn sub_op_result_type(&self, _other: &Box<dyn DataType>) -> Box<dyn DataType> {
Box::new(IntervalType)
}

fn can_perform_mul_op_with(&self) -> Vec<Box<dyn DataType>> {
vec![Box::new(IntType)]
}

fn mul_op_result_type(&self, _other: &Box<dyn DataType>) -> Box<dyn DataType> {
Box::new(IntervalType)
}

fn can_perform_div_op_with(&self) -> Vec<Box<dyn DataType>> {
vec![Box::new(IntType)]
}

fn div_op_result_type(&self, _other: &Box<dyn DataType>) -> Box<dyn DataType> {
Box::new(IntervalType)
}
}
16 changes: 16 additions & 0 deletions crates/gitql-core/src/values/interval.rs
Original file line number Diff line number Diff line change
Expand Up @@ -109,4 +109,20 @@ impl Value for IntervalValue {
}
Err("Unexpected type to perform `-` with".to_string())
}

fn mul_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
if let Some(value) = other.as_int() {
let interval = self.interval.mul(value)?;
return Ok(Box::new(IntervalValue::new(interval)));
}
Err("Unexpected type to perform `*` with".to_string())
}

fn div_op(&self, other: &Box<dyn Value>) -> Result<Box<dyn Value>, String> {
if let Some(value) = other.as_int() {
let interval = self.interval.div(value)?;
return Ok(Box::new(IntervalValue::new(interval)));
}
Err("Unexpected type to perform `/` with".to_string())
}
}

0 comments on commit f5b7284

Please sign in to comment.