From 94f905a503b9d7d1aa3d9208cc86cf9d0582a673 Mon Sep 17 00:00:00 2001 From: Matthew Heon Date: Tue, 28 Feb 2023 10:25:34 -0500 Subject: [PATCH] Fix SQLite DB schema migration code It now can safely run on bare databases, before any tables are created. Signed-off-by: Matthew Heon --- libpod/sqlite_state.go | 9 +++++---- libpod/sqlite_state_internal.go | 15 +++++++++++++++ 2 files changed, 20 insertions(+), 4 deletions(-) diff --git a/libpod/sqlite_state.go b/libpod/sqlite_state.go index 8317fe4b7c..9082e736e5 100644 --- a/libpod/sqlite_state.go +++ b/libpod/sqlite_state.go @@ -77,15 +77,16 @@ func NewSqliteState(runtime *Runtime) (_ State, defErr error) { return nil, fmt.Errorf("setting full fsync mode in db: %w", err) } + // Migrate schema (if necessary) + if err := state.migrateSchemaIfNecessary(); err != nil { + return nil, err + } + // Set up tables if err := sqliteInitTables(state.conn); err != nil { return nil, fmt.Errorf("creating tables: %w", err) } - if err := state.migrateSchemaIfNecessary(); err != nil { - return nil, err - } - state.valid = true state.runtime = runtime diff --git a/libpod/sqlite_state_internal.go b/libpod/sqlite_state_internal.go index 1f62d346bd..184b96971e 100644 --- a/libpod/sqlite_state_internal.go +++ b/libpod/sqlite_state_internal.go @@ -16,6 +16,20 @@ import ( ) func (s *SQLiteState) migrateSchemaIfNecessary() (defErr error) { + // First, check if the DBConfig table exists + checkRow := s.conn.QueryRow("SELECT 1 FROM sqlite_master WHERE type='table' AND name='DBConfig';") + var check int + if err := checkRow.Scan(&check); err != nil { + if errors.Is(err, sql.ErrNoRows) { + return nil + } + return fmt.Errorf("checking if DB config table exists: %w", err) + } + if check != 1 { + // Table does not exist, fresh database, no need to migrate. + return nil + } + row := s.conn.QueryRow("SELECT SchemaVersion FROM DBConfig;") var schemaVer int if err := row.Scan(&schemaVer); err != nil { @@ -24,6 +38,7 @@ func (s *SQLiteState) migrateSchemaIfNecessary() (defErr error) { // Schema was just created, so it has to be the latest. return nil } + return fmt.Errorf("scanning schema version from DB config: %w", err) } // If the schema version 0 or less, it's invalid