use super::super::*;
#[test]
fn test_cosine_distance_identical_vectors() {
let schema = vibesql_catalog::TableSchema::new("test".to_string(), vec![]);
let evaluator = ExpressionEvaluator::new(&schema);
let row = vibesql_storage::Row::new(vec![]);
let expr = vibesql_ast::Expression::BinaryOp {
left: Box::new(vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Vector(vec![
1.0, 0.0, 0.0,
]))),
op: vibesql_ast::BinaryOperator::CosineDistance,
right: Box::new(vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Vector(vec![
1.0, 0.0, 0.0,
]))),
};
let result = evaluator.eval(&expr, &row).unwrap();
if let vibesql_types::SqlValue::Double(d) = result {
assert!((d - 0.0).abs() < 1e-10, "Expected 0.0, got {}", d);
} else {
panic!("Expected Double, got {:?}", result);
}
}
#[test]
fn test_cosine_distance_orthogonal_vectors() {
let schema = vibesql_catalog::TableSchema::new("test".to_string(), vec![]);
let evaluator = ExpressionEvaluator::new(&schema);
let row = vibesql_storage::Row::new(vec![]);
let expr = vibesql_ast::Expression::BinaryOp {
left: Box::new(vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Vector(vec![
1.0, 0.0,
]))),
op: vibesql_ast::BinaryOperator::CosineDistance,
right: Box::new(vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Vector(vec![
0.0, 1.0,
]))),
};
let result = evaluator.eval(&expr, &row).unwrap();
if let vibesql_types::SqlValue::Double(d) = result {
assert!((d - 1.0).abs() < 1e-10, "Expected 1.0, got {}", d);
} else {
panic!("Expected Double, got {:?}", result);
}
}
#[test]
fn test_cosine_distance_opposite_vectors() {
let schema = vibesql_catalog::TableSchema::new("test".to_string(), vec![]);
let evaluator = ExpressionEvaluator::new(&schema);
let row = vibesql_storage::Row::new(vec![]);
let expr = vibesql_ast::Expression::BinaryOp {
left: Box::new(vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Vector(vec![
1.0, 0.0,
]))),
op: vibesql_ast::BinaryOperator::CosineDistance,
right: Box::new(vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Vector(vec![
-1.0, 0.0,
]))),
};
let result = evaluator.eval(&expr, &row).unwrap();
if let vibesql_types::SqlValue::Double(d) = result {
assert!((d - 2.0).abs() < 1e-10, "Expected 2.0, got {}", d);
} else {
panic!("Expected Double, got {:?}", result);
}
}
#[test]
fn test_l2_distance_identical_vectors() {
let schema = vibesql_catalog::TableSchema::new("test".to_string(), vec![]);
let evaluator = ExpressionEvaluator::new(&schema);
let row = vibesql_storage::Row::new(vec![]);
let expr = vibesql_ast::Expression::BinaryOp {
left: Box::new(vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Vector(vec![
1.0, 2.0, 3.0,
]))),
op: vibesql_ast::BinaryOperator::L2Distance,
right: Box::new(vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Vector(vec![
1.0, 2.0, 3.0,
]))),
};
let result = evaluator.eval(&expr, &row).unwrap();
if let vibesql_types::SqlValue::Double(d) = result {
assert!((d - 0.0).abs() < 1e-10, "Expected 0.0, got {}", d);
} else {
panic!("Expected Double, got {:?}", result);
}
}
#[test]
fn test_l2_distance_known_values() {
let schema = vibesql_catalog::TableSchema::new("test".to_string(), vec![]);
let evaluator = ExpressionEvaluator::new(&schema);
let row = vibesql_storage::Row::new(vec![]);
let expr = vibesql_ast::Expression::BinaryOp {
left: Box::new(vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Vector(vec![
0.0, 0.0,
]))),
op: vibesql_ast::BinaryOperator::L2Distance,
right: Box::new(vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Vector(vec![
3.0, 4.0,
]))),
};
let result = evaluator.eval(&expr, &row).unwrap();
if let vibesql_types::SqlValue::Double(d) = result {
assert!((d - 5.0).abs() < 1e-10, "Expected 5.0, got {}", d);
} else {
panic!("Expected Double, got {:?}", result);
}
}
#[test]
fn test_negative_inner_product() {
let schema = vibesql_catalog::TableSchema::new("test".to_string(), vec![]);
let evaluator = ExpressionEvaluator::new(&schema);
let row = vibesql_storage::Row::new(vec![]);
let expr = vibesql_ast::Expression::BinaryOp {
left: Box::new(vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Vector(vec![
1.0, 2.0, 3.0,
]))),
op: vibesql_ast::BinaryOperator::NegativeInnerProduct,
right: Box::new(vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Vector(vec![
4.0, 5.0, 6.0,
]))),
};
let result = evaluator.eval(&expr, &row).unwrap();
if let vibesql_types::SqlValue::Double(d) = result {
assert!((d - (-32.0)).abs() < 1e-10, "Expected -32.0, got {}", d);
} else {
panic!("Expected Double, got {:?}", result);
}
}
#[test]
fn test_negative_inner_product_orthogonal() {
let schema = vibesql_catalog::TableSchema::new("test".to_string(), vec![]);
let evaluator = ExpressionEvaluator::new(&schema);
let row = vibesql_storage::Row::new(vec![]);
let expr = vibesql_ast::Expression::BinaryOp {
left: Box::new(vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Vector(vec![
1.0, 0.0,
]))),
op: vibesql_ast::BinaryOperator::NegativeInnerProduct,
right: Box::new(vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Vector(vec![
0.0, 1.0,
]))),
};
let result = evaluator.eval(&expr, &row).unwrap();
if let vibesql_types::SqlValue::Double(d) = result {
assert!((d - 0.0).abs() < 1e-10, "Expected 0.0, got {}", d);
} else {
panic!("Expected Double, got {:?}", result);
}
}
#[test]
fn test_distance_operators_null_handling() {
let schema = vibesql_catalog::TableSchema::new("test".to_string(), vec![]);
let evaluator = ExpressionEvaluator::new(&schema);
let row = vibesql_storage::Row::new(vec![]);
let v = vibesql_types::SqlValue::Vector(vec![1.0, 2.0, 3.0]);
let expr = vibesql_ast::Expression::BinaryOp {
left: Box::new(vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Null)),
op: vibesql_ast::BinaryOperator::CosineDistance,
right: Box::new(vibesql_ast::Expression::Literal(v.clone())),
};
let result = evaluator.eval(&expr, &row).unwrap();
assert!(matches!(result, vibesql_types::SqlValue::Null));
let expr = vibesql_ast::Expression::BinaryOp {
left: Box::new(vibesql_ast::Expression::Literal(v.clone())),
op: vibesql_ast::BinaryOperator::L2Distance,
right: Box::new(vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Null)),
};
let result = evaluator.eval(&expr, &row).unwrap();
assert!(matches!(result, vibesql_types::SqlValue::Null));
let expr = vibesql_ast::Expression::BinaryOp {
left: Box::new(vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Null)),
op: vibesql_ast::BinaryOperator::NegativeInnerProduct,
right: Box::new(vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Null)),
};
let result = evaluator.eval(&expr, &row).unwrap();
assert!(matches!(result, vibesql_types::SqlValue::Null));
}
#[test]
fn test_dimension_mismatch_error() {
let schema = vibesql_catalog::TableSchema::new("test".to_string(), vec![]);
let evaluator = ExpressionEvaluator::new(&schema);
let row = vibesql_storage::Row::new(vec![]);
let expr = vibesql_ast::Expression::BinaryOp {
left: Box::new(vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Vector(vec![
1.0, 2.0,
]))),
op: vibesql_ast::BinaryOperator::CosineDistance,
right: Box::new(vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Vector(vec![
1.0, 2.0, 3.0,
]))),
};
let err = evaluator.eval(&expr, &row).unwrap_err();
match err {
ExecutorError::TypeError(msg) => {
assert!(
msg.contains("dimension mismatch"),
"Expected dimension mismatch error, got: {}",
msg
);
}
other => panic!("Expected TypeError, got {:?}", other),
}
}
#[test]
fn test_type_mismatch_error() {
let schema = vibesql_catalog::TableSchema::new("test".to_string(), vec![]);
let evaluator = ExpressionEvaluator::new(&schema);
let row = vibesql_storage::Row::new(vec![]);
let expr = vibesql_ast::Expression::BinaryOp {
left: Box::new(vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Vector(vec![
1.0, 2.0,
]))),
op: vibesql_ast::BinaryOperator::L2Distance,
right: Box::new(vibesql_ast::Expression::Literal(vibesql_types::SqlValue::Integer(42))),
};
let err = evaluator.eval(&expr, &row).unwrap_err();
match err {
ExecutorError::TypeError(msg) => {
assert!(msg.contains("VECTOR"), "Expected VECTOR type error, got: {}", msg);
}
other => panic!("Expected TypeError, got {:?}", other),
}
}