winbrew_database\catalog/
mod.rs

1use anyhow::{Context, Result, anyhow};
2use rusqlite::{Connection, OptionalExtension};
3
4use super::CatalogSchemaVersionMismatchError;
5use crate::models::catalog::metadata::CATALOG_DB_SCHEMA_VERSION as CATALOG_SCHEMA_VERSION;
6
7mod installers;
8mod row;
9mod search;
10
11pub(crate) use installers::get_installers;
12pub(crate) use search::{get_package_by_id, search};
13
14pub(crate) fn ensure_schema_version(conn: &Connection) -> Result<()> {
15    let version_text: Option<String> = conn
16        .query_row(
17            "SELECT value FROM schema_meta WHERE name = 'schema_version'",
18            [],
19            |row| row.get(0),
20        )
21        .optional()
22        .context("failed to read package catalog schema version metadata")?;
23
24    let version_text = version_text
25        .ok_or_else(|| anyhow!("package catalog schema version metadata is missing"))?;
26
27    let actual_version: i64 = version_text.parse().with_context(|| {
28        format!("failed to parse schema_meta schema_version value: {version_text}")
29    })?;
30    let expected_version = i64::from(CATALOG_SCHEMA_VERSION);
31
32    if actual_version != expected_version {
33        return Err(CatalogSchemaVersionMismatchError {
34            expected: CATALOG_SCHEMA_VERSION,
35            actual: actual_version,
36        }
37        .into());
38    }
39
40    Ok(())
41}
42
43#[cfg(test)]
44mod tests {
45    use super::{CATALOG_SCHEMA_VERSION, ensure_schema_version};
46    use rusqlite::Connection;
47
48    #[test]
49    fn ensure_schema_version_accepts_expected_version() {
50        let conn = Connection::open_in_memory().expect("open in-memory database");
51        conn.execute_batch(&format!(
52            "
53            CREATE TABLE schema_meta (
54                name TEXT PRIMARY KEY,
55                value TEXT NOT NULL
56            );
57
58            INSERT INTO schema_meta (name, value)
59            VALUES ('schema_version', '{}');
60            ",
61            CATALOG_SCHEMA_VERSION
62        ))
63        .expect("set schema version");
64
65        ensure_schema_version(&conn).expect("schema version should match");
66    }
67
68    #[test]
69    fn ensure_schema_version_rejects_mismatch() {
70        let conn = Connection::open_in_memory().expect("open in-memory database");
71        conn.execute_batch(
72            "
73            CREATE TABLE schema_meta (
74                name TEXT PRIMARY KEY,
75                value TEXT NOT NULL
76            );
77
78            INSERT INTO schema_meta (name, value)
79            VALUES ('schema_version', '99');
80            ",
81        )
82        .expect("set mismatched schema version");
83
84        let err = ensure_schema_version(&conn).expect_err("schema mismatch should fail");
85
86        assert!(
87            err.to_string()
88                .contains("Package catalog schema version mismatch")
89        );
90    }
91
92    #[test]
93    fn ensure_schema_version_rejects_missing_schema_version_row() {
94        let conn = Connection::open_in_memory().expect("open in-memory database");
95
96        conn.execute_batch(
97            "
98            CREATE TABLE schema_meta (
99                name TEXT PRIMARY KEY,
100                value TEXT NOT NULL
101            );
102            ",
103        )
104        .expect("create schema_meta table");
105
106        let err = ensure_schema_version(&conn).expect_err("missing schema version row should fail");
107
108        assert!(
109            err.to_string()
110                .contains("package catalog schema version metadata is missing")
111        );
112    }
113
114    #[test]
115    fn ensure_schema_version_rejects_missing_schema_meta_table() {
116        let conn = Connection::open_in_memory().expect("open in-memory database");
117
118        let err = ensure_schema_version(&conn).expect_err("missing schema_meta table should fail");
119
120        assert!(
121            err.to_string()
122                .contains("failed to read package catalog schema version metadata")
123        );
124    }
125}