relay-knowledge 1.1.14

Graph-database-based knowledge graph project.
Documentation
use rusqlite::{Connection, params};

use super::*;

#[test]
fn core_column_upgrade_backfills_legacy_mutation_metadata() {
    let connection = legacy_core_schema();
    connection
        .execute(
            "
            INSERT INTO evidence (id, source_scope, content, created_graph_version)
            VALUES (?1, ?2, ?3, ?4)
            ",
            params!["ev", "scope", "legacy content", 1],
        )
        .expect("legacy evidence should insert");
    connection
        .execute(
            "INSERT INTO graph_mutations (graph_version, evidence_count) VALUES (?1, ?2)",
            params![1, 1],
        )
        .expect("legacy mutation should insert");

    ensure_core_schema_columns(&connection).expect("legacy columns should upgrade");

    let metadata = connection
        .query_row(
            "
            SELECT affected_scopes_json, evidence_ids_json, source_hashes_json
            FROM graph_mutations
            WHERE graph_version = 1
            ",
            [],
            |row| {
                Ok((
                    row.get::<_, String>(0)?,
                    row.get::<_, String>(1)?,
                    row.get::<_, String>(2)?,
                ))
            },
        )
        .expect("mutation metadata should load");
    assert_eq!(metadata.0, r#"["scope"]"#);
    assert_eq!(metadata.1, r#"["ev"]"#);
    assert_eq!(
        metadata.2,
        format!(
            r#"["{}"]"#,
            indexing::source_hash("scope", None, "legacy content")
        )
    );

    let evidence_defaults = connection
        .query_row(
            "
            SELECT confidence_basis_points, status, modality, extraction_status
            FROM evidence
            WHERE id = 'ev'
            ",
            [],
            |row| {
                Ok((
                    row.get::<_, u16>(0)?,
                    row.get::<_, String>(1)?,
                    row.get::<_, String>(2)?,
                    row.get::<_, String>(3)?,
                ))
            },
        )
        .expect("upgraded evidence should load");
    assert_eq!(
        evidence_defaults,
        (
            10_000,
            "accepted".to_owned(),
            "text_span".to_owned(),
            "succeeded".to_owned(),
        )
    );
}

#[test]
fn ensure_column_is_idempotent() {
    let connection = Connection::open_in_memory().expect("database should open");
    connection
        .execute("CREATE TABLE sample (id INTEGER PRIMARY KEY)", [])
        .expect("sample table should initialize");

    ensure_column(&connection, "sample", "label", "TEXT")
        .expect("first column addition should succeed");
    ensure_column(&connection, "sample", "label", "TEXT")
        .expect("existing column should be accepted");

    let label_columns = connection
        .prepare("PRAGMA table_info(sample)")
        .expect("table metadata should prepare")
        .query_map([], |row| row.get::<_, String>(1))
        .expect("table metadata should query")
        .collect::<Result<Vec<_>, _>>()
        .expect("table metadata should collect")
        .into_iter()
        .filter(|column| column == "label")
        .count();
    assert_eq!(label_columns, 1);
}

#[test]
fn ensure_column_recognizes_virtual_generated_columns() {
    let connection = Connection::open_in_memory().expect("database should open");
    connection
        .execute(
            "CREATE TABLE sample (
                value INTEGER NOT NULL,
                doubled INTEGER GENERATED ALWAYS AS (value * 2) VIRTUAL
            )",
            [],
        )
        .expect("sample table should initialize");

    ensure_column(
        &connection,
        "sample",
        "doubled",
        "INTEGER GENERATED ALWAYS AS (value * 2) VIRTUAL",
    )
    .expect("existing generated column should be accepted");

    let generated_columns = connection
        .prepare("PRAGMA table_xinfo(sample)")
        .expect("extended table metadata should prepare")
        .query_map([], |row| row.get::<_, String>(1))
        .expect("extended table metadata should query")
        .collect::<Result<Vec<_>, _>>()
        .expect("extended table metadata should collect")
        .into_iter()
        .filter(|column| column == "doubled")
        .count();
    assert_eq!(generated_columns, 1);
}

fn legacy_core_schema() -> Connection {
    let connection = Connection::open_in_memory().expect("database should open");
    connection
        .execute_batch(
            "
            CREATE TABLE entities (
                id TEXT PRIMARY KEY,
                label TEXT NOT NULL,
                created_graph_version INTEGER NOT NULL
            );
            CREATE TABLE evidence (
                id TEXT PRIMARY KEY,
                source_scope TEXT NOT NULL,
                content TEXT NOT NULL,
                created_graph_version INTEGER NOT NULL
            );
            CREATE TABLE graph_mutations (
                graph_version INTEGER PRIMARY KEY,
                evidence_count INTEGER NOT NULL
            );
            ",
        )
        .expect("legacy core schema should initialize");
    connection
}