compare schema version on "moonfire-nvr check"

This commit is contained in:
Scott Lamb 2021-02-11 15:21:05 -08:00
parent 51f43e9124
commit cdd878f452
2 changed files with 35 additions and 20 deletions

View File

@ -50,6 +50,14 @@ pub struct Options {
pub fn run(conn: &rusqlite::Connection, opts: &Options) -> Result<i32, Error> {
let mut printed_error = false;
// Compare stated schema version.
if let Err(e) = db::check_schema_version(conn) {
error!("Schema version is not as expected:\n{}", e);
printed_error = true;
} else {
info!("Schema at expected version {}.", db::EXPECTED_VERSION);
}
// Compare schemas.
{
let mut expected = rusqlite::Connection::open_in_memory()?;
@ -57,13 +65,16 @@ pub fn run(conn: &rusqlite::Connection, opts: &Options) -> Result<i32, Error> {
if let Some(diffs) = compare::get_diffs("actual", conn, "expected", &expected)? {
error!("Schema is not as expected:\n{}", &diffs);
printed_error = true;
warn!("The following analysis may be incorrect or encounter errors due to schema differences.");
} else {
println!("Schema is as expected.");
}
info!("Done comparing schemas.");
}
if printed_error {
warn!("The following analysis may be incorrect or encounter errors due to schema differences.");
}
let db_uuid = raw::get_db_uuid(&conn)?;
// Scan directories.

View File

@ -2025,6 +2025,28 @@ pub fn get_schema_version(conn: &rusqlite::Connection) -> Result<Option<i32>, Er
|row| row.get(0))?))
}
/// Checks that the schema version in the given database is as expected.
pub(crate) fn check_schema_version(conn: &rusqlite::Connection) -> Result<(), Error> {
let ver = get_schema_version(conn)?.ok_or_else(|| format_err!(
"no such table: version. \
\
If you are starting from an \
empty database, see README.md to complete the \
installation. If you are starting from a database \
that predates schema versioning, see guide/schema.md."))?;
if ver < EXPECTED_VERSION {
bail!("Database schema version {} is too old (expected {}); \
see upgrade instructions in guide/upgrade.md.",
ver, EXPECTED_VERSION);
} else if ver > EXPECTED_VERSION {
bail!("Database schema version {} is too new (expected {}); \
must use a newer binary to match.", ver,
EXPECTED_VERSION);
}
Ok(())
}
/// The recording database. Abstracts away SQLite queries. Also maintains in-memory state
/// (loaded on startup, and updated on successful commit) to avoid expensive scans over the
/// recording table on common queries.
@ -2060,25 +2082,7 @@ impl<C: Clocks + Clone> Database<C> {
pub fn new(clocks: C, mut conn: rusqlite::Connection,
read_write: bool) -> Result<Database<C>, Error> {
set_integrity_pragmas(&mut conn)?;
{
let ver = get_schema_version(&conn)?.ok_or_else(|| format_err!(
"no such table: version. \
\
If you are starting from an \
empty database, see README.md to complete the \
installation. If you are starting from a database \
that predates schema versioning, see guide/schema.md."))?;
if ver < EXPECTED_VERSION {
bail!("Database schema version {} is too old (expected {}); \
see upgrade instructions in guide/upgrade.md.",
ver, EXPECTED_VERSION);
} else if ver > EXPECTED_VERSION {
bail!("Database schema version {} is too new (expected {}); \
must use a newer binary to match.", ver,
EXPECTED_VERSION);
}
}
check_schema_version(&conn)?;
// Note: the meta check comes after the version check to improve the error message when
// trying to open a version 0 or version 1 database (which lacked the meta table).