use rand::{Rng, RngExt};
use vibesql_types::SqlValue;
use crate::errors::ExecutorError;
pub(crate) fn random(args: &[SqlValue]) -> Result<SqlValue, ExecutorError> {
if !args.is_empty() {
return Err(ExecutorError::UnsupportedFeature(format!(
"RANDOM takes no arguments, got {}",
args.len()
)));
}
let value: i64 = rand::rng().random();
Ok(SqlValue::Integer(value))
}
pub(crate) fn likely(args: &[SqlValue]) -> Result<SqlValue, ExecutorError> {
if args.len() != 1 {
return Err(ExecutorError::UnsupportedFeature(format!(
"LIKELY requires exactly 1 argument, got {}",
args.len()
)));
}
Ok(args[0].clone())
}
pub(crate) fn unlikely(args: &[SqlValue]) -> Result<SqlValue, ExecutorError> {
if args.len() != 1 {
return Err(ExecutorError::UnsupportedFeature(format!(
"UNLIKELY requires exactly 1 argument, got {}",
args.len()
)));
}
Ok(args[0].clone())
}
pub(crate) fn likelihood(args: &[SqlValue]) -> Result<SqlValue, ExecutorError> {
if args.len() != 2 {
return Err(ExecutorError::UnsupportedFeature(format!(
"LIKELIHOOD requires exactly 2 arguments, got {}",
args.len()
)));
}
Ok(args[0].clone())
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_random() {
let result = random(&[]).unwrap();
assert!(matches!(result, SqlValue::Integer(_)));
let result1 = random(&[]).unwrap();
let result2 = random(&[]).unwrap();
assert_ne!(result1, result2);
assert!(random(&[SqlValue::Integer(1)]).is_err());
}
#[test]
fn test_likely_unlikely_likelihood() {
let val = SqlValue::Boolean(true);
assert_eq!(likely(std::slice::from_ref(&val)).unwrap(), val);
assert_eq!(unlikely(std::slice::from_ref(&val)).unwrap(), val);
assert_eq!(likelihood(&[val.clone(), SqlValue::Numeric(0.9)]).unwrap(), val);
}
}