velesdb-core 5.1.0

High-performance vector database engine written in Rust
Documentation
use super::*;
use crate::velesql::{
    CompareOp, Comparison, FusionConfig, SimilarityCondition, Value, VectorExpr, VectorFusedSearch,
    VectorSearch,
};

/// Helper: builds a `Condition::Similarity` leaf.
fn similarity_leaf() -> Condition {
    Condition::Similarity(SimilarityCondition {
        field: "embedding".to_string(),
        vector: VectorExpr::Parameter("v".to_string()),
        operator: CompareOp::Gt,
        threshold: 0.8,
    })
}

/// Helper: builds a `Condition::Comparison` leaf (non-vector).
fn comparison_leaf(column: &str) -> Condition {
    Condition::Comparison(Comparison {
        column: column.to_string(),
        operator: CompareOp::Eq,
        value: Value::Integer(1),
    })
}

/// Helper: builds a `Condition::VectorSearch` leaf.
fn vector_search_leaf() -> Condition {
    Condition::VectorSearch(VectorSearch {
        vector: VectorExpr::Literal(vec![0.1, 0.2, 0.3]),
    })
}

/// Helper: builds a `Condition::VectorFusedSearch` leaf.
fn vector_fused_leaf() -> Condition {
    Condition::VectorFusedSearch(VectorFusedSearch {
        vectors: vec![
            VectorExpr::Literal(vec![0.1, 0.2]),
            VectorExpr::Literal(vec![0.3, 0.4]),
        ],
        fusion: FusionConfig::rrf(),
    })
}

// ── any_subtree ──────────────────────────────────────────────────

#[test]
fn test_any_subtree_leaf_match() {
    let cond = similarity_leaf();
    assert!(any_subtree(&cond, &is_vector_leaf));
}

#[test]
fn test_any_subtree_leaf_no_match() {
    let cond = comparison_leaf("age");
    assert!(!any_subtree(&cond, &is_vector_leaf));
}

#[test]
fn test_any_subtree_nested_and() {
    // And(comparison, And(comparison, similarity))
    let inner_and = Condition::And(
        Box::new(comparison_leaf("status")),
        Box::new(similarity_leaf()),
    );
    let root = Condition::And(Box::new(comparison_leaf("age")), Box::new(inner_and));
    assert!(any_subtree(&root, &is_vector_leaf));
}

#[test]
fn test_any_subtree_nested_not_group() {
    // Not(Group(VectorSearch))
    let cond = Condition::Not(Box::new(Condition::Group(Box::new(vector_search_leaf()))));
    assert!(any_subtree(&cond, &is_vector_leaf));
}

// ── count_matching_leaves ────────────────────────────────────────

#[test]
fn test_count_matching_leaves_zero() {
    // Tree with no vector leaves at all.
    let cond = Condition::And(
        Box::new(comparison_leaf("a")),
        Box::new(Condition::Or(
            Box::new(comparison_leaf("b")),
            Box::new(comparison_leaf("c")),
        )),
    );
    assert_eq!(count_matching_leaves(&cond, is_vector_leaf), 0);
}

#[test]
fn test_count_matching_leaves_nested() {
    // And(Similarity, Or(VectorSearch, Comparison)) -> 2 vector leaves.
    let cond = Condition::And(
        Box::new(similarity_leaf()),
        Box::new(Condition::Or(
            Box::new(vector_search_leaf()),
            Box::new(comparison_leaf("x")),
        )),
    );
    assert_eq!(count_matching_leaves(&cond, is_vector_leaf), 2);
}

// ── is_vector_leaf ───────────────────────────────────────────────

#[test]
fn test_is_vector_leaf_variants() {
    // Positive cases: all three vector leaf types.
    assert!(is_vector_leaf(&similarity_leaf()));
    assert!(is_vector_leaf(&vector_search_leaf()));
    assert!(is_vector_leaf(&vector_fused_leaf()));

    // Negative cases: non-vector leaves and combinators.
    assert!(!is_vector_leaf(&comparison_leaf("col")));
    assert!(!is_vector_leaf(&Condition::And(
        Box::new(similarity_leaf()),
        Box::new(comparison_leaf("col")),
    )));
    assert!(!is_vector_leaf(&Condition::Or(
        Box::new(comparison_leaf("a")),
        Box::new(comparison_leaf("b")),
    )));
    assert!(!is_vector_leaf(&Condition::Not(
        Box::new(similarity_leaf())
    )));
    assert!(!is_vector_leaf(&Condition::Group(Box::new(
        similarity_leaf()
    ))));
}