use vibesql_types::SqlValue;
use super::exponential::numeric_to_f64;
use crate::errors::ExecutorError;
pub fn sin(args: &[SqlValue]) -> Result<SqlValue, ExecutorError> {
if args.len() != 1 {
return Err(ExecutorError::UnsupportedFeature(format!(
"SIN requires exactly 1 argument, got {}",
args.len()
)));
}
match &args[0] {
SqlValue::Null => Ok(SqlValue::Null),
val => {
let x = numeric_to_f64(val)?;
Ok(SqlValue::Double(x.sin()))
}
}
}
pub fn cos(args: &[SqlValue]) -> Result<SqlValue, ExecutorError> {
if args.len() != 1 {
return Err(ExecutorError::UnsupportedFeature(format!(
"COS requires exactly 1 argument, got {}",
args.len()
)));
}
match &args[0] {
SqlValue::Null => Ok(SqlValue::Null),
val => {
let x = numeric_to_f64(val)?;
Ok(SqlValue::Double(x.cos()))
}
}
}
pub fn tan(args: &[SqlValue]) -> Result<SqlValue, ExecutorError> {
if args.len() != 1 {
return Err(ExecutorError::UnsupportedFeature(format!(
"TAN requires exactly 1 argument, got {}",
args.len()
)));
}
match &args[0] {
SqlValue::Null => Ok(SqlValue::Null),
val => {
let x = numeric_to_f64(val)?;
Ok(SqlValue::Double(x.tan()))
}
}
}
pub fn asin(args: &[SqlValue]) -> Result<SqlValue, ExecutorError> {
if args.len() != 1 {
return Err(ExecutorError::UnsupportedFeature(format!(
"ASIN requires exactly 1 argument, got {}",
args.len()
)));
}
match &args[0] {
SqlValue::Null => Ok(SqlValue::Null),
val => {
let x = numeric_to_f64(val)?;
if !(-1.0..=1.0).contains(&x) {
Err(ExecutorError::UnsupportedFeature(
"ASIN requires value between -1 and 1".to_string(),
))
} else {
Ok(SqlValue::Double(x.asin()))
}
}
}
}
pub fn acos(args: &[SqlValue]) -> Result<SqlValue, ExecutorError> {
if args.len() != 1 {
return Err(ExecutorError::UnsupportedFeature(format!(
"ACOS requires exactly 1 argument, got {}",
args.len()
)));
}
match &args[0] {
SqlValue::Null => Ok(SqlValue::Null),
val => {
let x = numeric_to_f64(val)?;
if !(-1.0..=1.0).contains(&x) {
Err(ExecutorError::UnsupportedFeature(
"ACOS requires value between -1 and 1".to_string(),
))
} else {
Ok(SqlValue::Double(x.acos()))
}
}
}
}
pub fn atan(args: &[SqlValue]) -> Result<SqlValue, ExecutorError> {
if args.len() != 1 {
return Err(ExecutorError::UnsupportedFeature(format!(
"ATAN requires exactly 1 argument, got {}",
args.len()
)));
}
match &args[0] {
SqlValue::Null => Ok(SqlValue::Null),
val => {
let x = numeric_to_f64(val)?;
Ok(SqlValue::Double(x.atan()))
}
}
}
pub fn atan2(args: &[SqlValue]) -> Result<SqlValue, ExecutorError> {
if args.len() != 2 {
return Err(ExecutorError::UnsupportedFeature(format!(
"ATAN2 requires exactly 2 arguments, got {}",
args.len()
)));
}
match (&args[0], &args[1]) {
(SqlValue::Null, _) | (_, SqlValue::Null) => Ok(SqlValue::Null),
(y_val, x_val) => {
let y = numeric_to_f64(y_val)?;
let x = numeric_to_f64(x_val)?;
Ok(SqlValue::Double(y.atan2(x)))
}
}
}
pub fn radians(args: &[SqlValue]) -> Result<SqlValue, ExecutorError> {
if args.len() != 1 {
return Err(ExecutorError::UnsupportedFeature(format!(
"RADIANS requires exactly 1 argument, got {}",
args.len()
)));
}
match &args[0] {
SqlValue::Null => Ok(SqlValue::Null),
val => {
let degrees = numeric_to_f64(val)?;
Ok(SqlValue::Double(degrees.to_radians()))
}
}
}
pub fn degrees(args: &[SqlValue]) -> Result<SqlValue, ExecutorError> {
if args.len() != 1 {
return Err(ExecutorError::UnsupportedFeature(format!(
"DEGREES requires exactly 1 argument, got {}",
args.len()
)));
}
match &args[0] {
SqlValue::Null => Ok(SqlValue::Null),
val => {
let radians = numeric_to_f64(val)?;
Ok(SqlValue::Double(radians.to_degrees()))
}
}
}