icydb-core 0.94.0

IcyDB — A schema-first typed query engine and persistence runtime for Internet Computer canisters
Documentation
use super::*;

#[test]
fn fingerprint_and_signature_are_stable_for_reordered_and_non_canonical_map_predicates() {
    let map_a = Value::Map(vec![
        (Value::Text("z".to_string()), Value::Int(9)),
        (Value::Text("a".to_string()), Value::Int(1)),
    ]);
    let map_b = Value::Map(vec![
        (Value::Text("a".to_string()), Value::Int(1)),
        (Value::Text("z".to_string()), Value::Int(9)),
    ]);

    let predicate_a = Predicate::And(vec![
        FieldRef::new("other").eq(Value::Text("x".to_string())),
        Predicate::Compare(ComparePredicate::eq("meta".to_string(), map_a)),
    ]);
    let predicate_b = Predicate::And(vec![
        Predicate::Compare(ComparePredicate::eq("meta".to_string(), map_b)),
        FieldRef::new("other").eq(Value::Text("x".to_string())),
    ]);

    let mut plan_a: AccessPlannedQuery = full_scan_query();
    plan_a.scalar_plan_mut().predicate = Some(predicate_a);

    let mut plan_b: AccessPlannedQuery = full_scan_query();
    plan_b.scalar_plan_mut().predicate = Some(predicate_b);

    assert_eq!(plan_a.fingerprint(), plan_b.fingerprint());
    assert_eq!(
        plan_a.continuation_signature("tests::Entity"),
        plan_b.continuation_signature("tests::Entity")
    );
}

#[test]
fn fingerprint_and_signature_treat_equivalent_decimal_predicate_literals_as_identical() {
    let predicate_a = Predicate::Compare(ComparePredicate::eq(
        "rank".to_string(),
        Value::Decimal(Decimal::new(10, 1)),
    ));
    let predicate_b = Predicate::Compare(ComparePredicate::eq(
        "rank".to_string(),
        Value::Decimal(Decimal::new(100, 2)),
    ));

    let mut plan_a: AccessPlannedQuery = full_scan_query();
    plan_a.scalar_plan_mut().predicate = Some(predicate_a);

    let mut plan_b: AccessPlannedQuery = full_scan_query();
    plan_b.scalar_plan_mut().predicate = Some(predicate_b);

    assert_eq!(plan_a.fingerprint(), plan_b.fingerprint());
    assert_eq!(
        plan_a.continuation_signature("tests::Entity"),
        plan_b.continuation_signature("tests::Entity")
    );
}

#[test]
fn fingerprint_and_signature_treat_equivalent_in_list_predicates_as_identical() {
    let predicate_a = Predicate::Compare(ComparePredicate::in_(
        "rank".to_string(),
        vec![Value::Uint(3), Value::Uint(1), Value::Uint(2)],
    ));
    let predicate_b = Predicate::Compare(ComparePredicate::in_(
        "rank".to_string(),
        vec![Value::Uint(1), Value::Uint(2), Value::Uint(3)],
    ));

    let mut plan_a: AccessPlannedQuery = full_scan_query();
    plan_a.scalar_plan_mut().predicate = Some(predicate_a);

    let mut plan_b: AccessPlannedQuery = full_scan_query();
    plan_b.scalar_plan_mut().predicate = Some(predicate_b);

    assert_eq!(plan_a.fingerprint(), plan_b.fingerprint());
    assert_eq!(
        plan_a.continuation_signature("tests::Entity"),
        plan_b.continuation_signature("tests::Entity")
    );
}

#[test]
fn fingerprint_and_signature_treat_same_field_or_eq_and_in_as_identical() {
    let predicate_or_eq = Predicate::Or(vec![
        Predicate::Compare(ComparePredicate::with_coercion(
            "rank",
            CompareOp::Eq,
            Value::Uint(3),
            CoercionId::Strict,
        )),
        Predicate::Compare(ComparePredicate::with_coercion(
            "rank",
            CompareOp::Eq,
            Value::Uint(1),
            CoercionId::Strict,
        )),
        Predicate::Compare(ComparePredicate::with_coercion(
            "rank",
            CompareOp::Eq,
            Value::Uint(3),
            CoercionId::Strict,
        )),
    ]);
    let predicate_in = Predicate::Compare(ComparePredicate::with_coercion(
        "rank",
        CompareOp::In,
        Value::List(vec![Value::Uint(1), Value::Uint(3)]),
        CoercionId::Strict,
    ));

    let mut plan_or_eq: AccessPlannedQuery = full_scan_query();
    plan_or_eq.scalar_plan_mut().predicate = Some(predicate_or_eq);

    let mut plan_in: AccessPlannedQuery = full_scan_query();
    plan_in.scalar_plan_mut().predicate = Some(predicate_in);

    assert_eq!(plan_or_eq.fingerprint(), plan_in.fingerprint());
    assert_eq!(
        plan_or_eq.continuation_signature("tests::Entity"),
        plan_in.continuation_signature("tests::Entity")
    );
}

#[test]
fn fingerprint_and_signature_treat_equivalent_in_list_duplicate_literals_as_identical() {
    let predicate_a = Predicate::Compare(ComparePredicate::in_(
        "rank".to_string(),
        vec![
            Value::Uint(3),
            Value::Uint(1),
            Value::Uint(3),
            Value::Uint(2),
        ],
    ));
    let predicate_b = Predicate::Compare(ComparePredicate::in_(
        "rank".to_string(),
        vec![Value::Uint(1), Value::Uint(2), Value::Uint(3)],
    ));

    let mut plan_a: AccessPlannedQuery = full_scan_query();
    plan_a.scalar_plan_mut().predicate = Some(predicate_a);

    let mut plan_b: AccessPlannedQuery = full_scan_query();
    plan_b.scalar_plan_mut().predicate = Some(predicate_b);

    assert_eq!(plan_a.fingerprint(), plan_b.fingerprint());
    assert_eq!(
        plan_a.continuation_signature("tests::Entity"),
        plan_b.continuation_signature("tests::Entity")
    );
}

#[test]
fn fingerprint_and_signature_treat_implicit_and_explicit_strict_coercion_as_identical() {
    let predicate_a = Predicate::Compare(ComparePredicate::eq("rank".to_string(), Value::Int(7)));
    let predicate_b = Predicate::Compare(ComparePredicate::with_coercion(
        "rank",
        CompareOp::Eq,
        Value::Int(7),
        CoercionId::Strict,
    ));

    let mut plan_a: AccessPlannedQuery = full_scan_query();
    plan_a.scalar_plan_mut().predicate = Some(predicate_a);

    let mut plan_b: AccessPlannedQuery = full_scan_query();
    plan_b.scalar_plan_mut().predicate = Some(predicate_b);

    assert_eq!(plan_a.fingerprint(), plan_b.fingerprint());
    assert_eq!(
        plan_a.continuation_signature("tests::Entity"),
        plan_b.continuation_signature("tests::Entity")
    );
}

#[test]
fn fingerprint_and_signature_distinguish_different_coercion_ids() {
    let predicate_strict = Predicate::Compare(ComparePredicate::with_coercion(
        "rank",
        CompareOp::Eq,
        Value::Int(7),
        CoercionId::Strict,
    ));
    let predicate_numeric_widen = Predicate::Compare(ComparePredicate::with_coercion(
        "rank",
        CompareOp::Eq,
        Value::Int(7),
        CoercionId::NumericWiden,
    ));

    let mut strict_plan: AccessPlannedQuery = full_scan_query();
    strict_plan.scalar_plan_mut().predicate = Some(predicate_strict);

    let mut numeric_widen_plan: AccessPlannedQuery = full_scan_query();
    numeric_widen_plan.scalar_plan_mut().predicate = Some(predicate_numeric_widen);

    assert_ne!(strict_plan.fingerprint(), numeric_widen_plan.fingerprint());
    assert_ne!(
        strict_plan.continuation_signature("tests::Entity"),
        numeric_widen_plan.continuation_signature("tests::Entity")
    );
}

#[test]
fn fingerprint_and_signature_treat_numeric_widen_equivalent_literal_subtypes_as_identical() {
    let predicate_int = Predicate::Compare(ComparePredicate::with_coercion(
        "rank",
        CompareOp::Eq,
        Value::Int(1),
        CoercionId::NumericWiden,
    ));
    let predicate_decimal = Predicate::Compare(ComparePredicate::with_coercion(
        "rank",
        CompareOp::Eq,
        Value::Decimal(Decimal::new(10, 1)),
        CoercionId::NumericWiden,
    ));

    let mut int_plan: AccessPlannedQuery = full_scan_query();
    int_plan.scalar_plan_mut().predicate = Some(predicate_int);

    let mut decimal_plan: AccessPlannedQuery = full_scan_query();
    decimal_plan.scalar_plan_mut().predicate = Some(predicate_decimal);

    assert_eq!(int_plan.fingerprint(), decimal_plan.fingerprint());
    assert_eq!(
        int_plan.continuation_signature("tests::Entity"),
        decimal_plan.continuation_signature("tests::Entity")
    );
}

#[test]
fn fingerprint_and_signature_treat_text_casefold_case_only_literals_as_identical() {
    let predicate_lower = Predicate::Compare(ComparePredicate::with_coercion(
        "name",
        CompareOp::Eq,
        Value::Text("ada".to_string()),
        CoercionId::TextCasefold,
    ));
    let predicate_upper = Predicate::Compare(ComparePredicate::with_coercion(
        "name",
        CompareOp::Eq,
        Value::Text("ADA".to_string()),
        CoercionId::TextCasefold,
    ));

    let mut lower_plan: AccessPlannedQuery = full_scan_query();
    lower_plan.scalar_plan_mut().predicate = Some(predicate_lower);

    let mut upper_plan: AccessPlannedQuery = full_scan_query();
    upper_plan.scalar_plan_mut().predicate = Some(predicate_upper);

    assert_eq!(lower_plan.fingerprint(), upper_plan.fingerprint());
    assert_eq!(
        lower_plan.continuation_signature("tests::Entity"),
        upper_plan.continuation_signature("tests::Entity")
    );
}

#[test]
fn fingerprint_and_signature_keep_strict_text_case_variants_distinct() {
    let predicate_lower = Predicate::Compare(ComparePredicate::with_coercion(
        "name",
        CompareOp::Eq,
        Value::Text("ada".to_string()),
        CoercionId::Strict,
    ));
    let predicate_upper = Predicate::Compare(ComparePredicate::with_coercion(
        "name",
        CompareOp::Eq,
        Value::Text("ADA".to_string()),
        CoercionId::Strict,
    ));

    let mut lower_plan: AccessPlannedQuery = full_scan_query();
    lower_plan.scalar_plan_mut().predicate = Some(predicate_lower);

    let mut upper_plan: AccessPlannedQuery = full_scan_query();
    upper_plan.scalar_plan_mut().predicate = Some(predicate_upper);

    assert_ne!(lower_plan.fingerprint(), upper_plan.fingerprint());
    assert_ne!(
        lower_plan.continuation_signature("tests::Entity"),
        upper_plan.continuation_signature("tests::Entity")
    );
}

#[test]
fn fingerprint_and_signature_treat_text_casefold_in_list_case_variants_as_identical() {
    let predicate_mixed = Predicate::Compare(ComparePredicate::with_coercion(
        "name",
        CompareOp::In,
        Value::List(vec![
            Value::Text("ADA".to_string()),
            Value::Text("ada".to_string()),
            Value::Text("Bob".to_string()),
        ]),
        CoercionId::TextCasefold,
    ));
    let predicate_canonical = Predicate::Compare(ComparePredicate::with_coercion(
        "name",
        CompareOp::In,
        Value::List(vec![
            Value::Text("ada".to_string()),
            Value::Text("bob".to_string()),
        ]),
        CoercionId::TextCasefold,
    ));

    let mut mixed_plan: AccessPlannedQuery = full_scan_query();
    mixed_plan.scalar_plan_mut().predicate = Some(predicate_mixed);

    let mut canonical_plan: AccessPlannedQuery = full_scan_query();
    canonical_plan.scalar_plan_mut().predicate = Some(predicate_canonical);

    assert_eq!(mixed_plan.fingerprint(), canonical_plan.fingerprint());
    assert_eq!(
        mixed_plan.continuation_signature("tests::Entity"),
        canonical_plan.continuation_signature("tests::Entity")
    );
}

#[test]
fn fingerprint_and_signature_distinguish_strict_from_text_casefold_coercion() {
    let predicate_strict = Predicate::Compare(ComparePredicate::with_coercion(
        "name",
        CompareOp::Eq,
        Value::Text("ada".to_string()),
        CoercionId::Strict,
    ));
    let predicate_casefold = Predicate::Compare(ComparePredicate::with_coercion(
        "name",
        CompareOp::Eq,
        Value::Text("ada".to_string()),
        CoercionId::TextCasefold,
    ));

    let mut strict_plan: AccessPlannedQuery = full_scan_query();
    strict_plan.scalar_plan_mut().predicate = Some(predicate_strict);

    let mut casefold_plan: AccessPlannedQuery = full_scan_query();
    casefold_plan.scalar_plan_mut().predicate = Some(predicate_casefold);

    assert_ne!(strict_plan.fingerprint(), casefold_plan.fingerprint());
    assert_ne!(
        strict_plan.continuation_signature("tests::Entity"),
        casefold_plan.continuation_signature("tests::Entity")
    );
}

#[test]
fn fingerprint_and_signature_distinguish_strict_from_collection_element_coercion() {
    let predicate_strict = Predicate::Compare(ComparePredicate::with_coercion(
        "rank",
        CompareOp::Eq,
        Value::Int(7),
        CoercionId::Strict,
    ));
    let predicate_collection_element = Predicate::Compare(ComparePredicate::with_coercion(
        "rank",
        CompareOp::Eq,
        Value::Int(7),
        CoercionId::CollectionElement,
    ));

    let mut strict_plan: AccessPlannedQuery = full_scan_query();
    strict_plan.scalar_plan_mut().predicate = Some(predicate_strict);

    let mut collection_plan: AccessPlannedQuery = full_scan_query();
    collection_plan.scalar_plan_mut().predicate = Some(predicate_collection_element);

    assert_ne!(strict_plan.fingerprint(), collection_plan.fingerprint());
    assert_ne!(
        strict_plan.continuation_signature("tests::Entity"),
        collection_plan.continuation_signature("tests::Entity")
    );
}