<p>Stefan Sperling <strong>merged</strong> this change.</p><p><a href="https://gerrit.osmocom.org/11898">View Change</a></p><div style="white-space:pre-wrap">Approvals:
Jenkins Builder: Verified
Neels Hofmeyr: Looks good to me, approved
</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">add database schema versioning to the HLR database<br><br>Make use of pragma user_version to store our database schema version.<br>The present schema is now identitifed as 'version 0', which is also<br>the default value for databases on which we never ran the statement<br>'pragma user_version' before.<br><br>Only bootstrap the database if it hasn't been bootstrapped yet.<br>Previously, bootstrap SQL statements ran every time osmo-hlr<br>opened the database, and any errors were being ignored in SQL.<br>Instead, we now first run a query which checks whether tables<br>already exist, and only create them if necessary.<br>This change will allow future schema updates to work properly.<br><br>Prepare for future schema upgrades by adding a new command-line<br>option which enables upgrades. This option defaults to 'false'<br>in order to avoid accidental upgrades.<br><br>Change-Id: I8aeaa9a404b622657cbc7138106f38aa6ad8d01b<br>Related: OS#2838<br>---<br>M sql/hlr.sql<br>M src/db.c<br>M src/db.h<br>M src/hlr.c<br>M src/hlr_db_tool.c<br>M tests/db/db_test.c<br>6 files changed, 128 insertions(+), 25 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/sql/hlr.sql b/sql/hlr.sql</span><br><span>index 80eb3e5..3499109 100644</span><br><span>--- a/sql/hlr.sql</span><br><span>+++ b/sql/hlr.sql</span><br><span>@@ -1,4 +1,4 @@</span><br><span style="color: hsl(0, 100%, 40%);">-CREATE TABLE IF NOT EXISTS subscriber (</span><br><span style="color: hsl(120, 100%, 40%);">+CREATE TABLE subscriber (</span><br><span> -- OsmoHLR's DB scheme is modelled roughly after TS 23.008 version 13.3.0</span><br><span> id INTEGER PRIMARY KEY,</span><br><span> -- Chapter 2.1.1.1</span><br><span>@@ -39,24 +39,24 @@</span><br><span> ms_purged_ps BOOLEAN NOT NULL DEFAULT 0</span><br><span> );</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-CREATE TABLE IF NOT EXISTS subscriber_apn (</span><br><span style="color: hsl(120, 100%, 40%);">+CREATE TABLE subscriber_apn (</span><br><span> subscriber_id INTEGER, -- subscriber.id</span><br><span> apn VARCHAR(256) NOT NULL</span><br><span> );</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-CREATE TABLE IF NOT EXISTS subscriber_multi_msisdn (</span><br><span style="color: hsl(120, 100%, 40%);">+CREATE TABLE subscriber_multi_msisdn (</span><br><span> -- Chapter 2.1.3</span><br><span> subscriber_id INTEGER, -- subscriber.id</span><br><span> msisdn VARCHAR(15) NOT NULL</span><br><span> );</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-CREATE TABLE IF NOT EXISTS auc_2g (</span><br><span style="color: hsl(120, 100%, 40%);">+CREATE TABLE auc_2g (</span><br><span> subscriber_id INTEGER PRIMARY KEY, -- subscriber.id</span><br><span> algo_id_2g INTEGER NOT NULL, -- enum osmo_auth_algo value</span><br><span> ki VARCHAR(32) NOT NULL -- hex string: subscriber's secret key (128bit)</span><br><span> );</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-CREATE TABLE IF NOT EXISTS auc_3g (</span><br><span style="color: hsl(120, 100%, 40%);">+CREATE TABLE auc_3g (</span><br><span> subscriber_id INTEGER PRIMARY KEY, -- subscriber.id</span><br><span> algo_id_3g INTEGER NOT NULL, -- enum osmo_auth_algo value</span><br><span> k VARCHAR(32) NOT NULL, -- hex string: subscriber's secret key (128bit)</span><br><span>@@ -66,4 +66,7 @@</span><br><span> ind_bitlen INTEGER NOT NULL DEFAULT 5 -- nr of index bits at lower SQN end</span><br><span> );</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-CREATE UNIQUE INDEX IF NOT EXISTS idx_subscr_imsi ON subscriber (imsi);</span><br><span style="color: hsl(120, 100%, 40%);">+CREATE UNIQUE INDEX idx_subscr_imsi ON subscriber (imsi);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+-- Set HLR database schema version number</span><br><span style="color: hsl(120, 100%, 40%);">+PRAGMA user_version = 0;</span><br><span>diff --git a/src/db.c b/src/db.c</span><br><span>index bcf83c6..df52f9b 100644</span><br><span>--- a/src/db.c</span><br><span>+++ b/src/db.c</span><br><span>@@ -27,6 +27,8 @@</span><br><span> #include "db.h"</span><br><span> #include "db_bootstrap.h"</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#define CURRENT_SCHEMA_VERSION 0</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #define SEL_COLUMNS \</span><br><span> "id," \</span><br><span> "imsi," \</span><br><span>@@ -197,36 +199,90 @@</span><br><span> for (i = 0; i < ARRAY_SIZE(stmt_bootstrap_sql); i++) {</span><br><span> int rc;</span><br><span> sqlite3_stmt *stmt;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">- rc = sqlite3_prepare_v2(dbc->db, stmt_bootstrap_sql[i], -1,</span><br><span style="color: hsl(0, 100%, 40%);">- &stmt, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = sqlite3_prepare_v2(dbc->db, stmt_bootstrap_sql[i], -1, &stmt, NULL);</span><br><span> if (rc != SQLITE_OK) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DDB, LOGL_ERROR, "Unable to prepare SQL statement '%s'\n",</span><br><span style="color: hsl(0, 100%, 40%);">- stmt_bootstrap_sql[i]);</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DDB, LOGL_ERROR, "Unable to prepare SQL statement '%s'\n", stmt_bootstrap_sql[i]);</span><br><span> return rc;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- /* execute the statement */</span><br><span> rc = sqlite3_step(stmt);</span><br><span> db_remove_reset(stmt);</span><br><span> sqlite3_finalize(stmt);</span><br><span> if (rc != SQLITE_DONE) {</span><br><span> LOGP(DDB, LOGL_ERROR, "Cannot bootstrap database: SQL error: (%d) %s,"</span><br><span> " during stmt '%s'",</span><br><span style="color: hsl(0, 100%, 40%);">- rc, sqlite3_errmsg(dbc->db),</span><br><span style="color: hsl(0, 100%, 40%);">- stmt_bootstrap_sql[i]);</span><br><span style="color: hsl(120, 100%, 40%);">+ rc, sqlite3_errmsg(dbc->db), stmt_bootstrap_sql[i]);</span><br><span> return rc;</span><br><span> }</span><br><span> }</span><br><span> return SQLITE_OK;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-struct db_context *db_open(void *ctx, const char *fname, bool enable_sqlite_logging)</span><br><span style="color: hsl(120, 100%, 40%);">+/* https://www.sqlite.org/fileformat2.html#storage_of_the_sql_database_schema */</span><br><span style="color: hsl(120, 100%, 40%);">+static bool db_table_exists(struct db_context *dbc, const char *table_name)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *table_exists_sql = "SELECT name FROM sqlite_master WHERE type='table' AND name=?";</span><br><span style="color: hsl(120, 100%, 40%);">+ sqlite3_stmt *stmt;</span><br><span style="color: hsl(120, 100%, 40%);">+ int rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = sqlite3_prepare_v2(dbc->db, table_exists_sql, -1, &stmt, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc != SQLITE_OK) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DDB, LOGL_ERROR, "Unable to prepare SQL statement '%s'\n", table_exists_sql);</span><br><span style="color: hsl(120, 100%, 40%);">+ return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!db_bind_text(stmt, NULL, table_name))</span><br><span style="color: hsl(120, 100%, 40%);">+ return false;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = sqlite3_step(stmt);</span><br><span style="color: hsl(120, 100%, 40%);">+ db_remove_reset(stmt);</span><br><span style="color: hsl(120, 100%, 40%);">+ sqlite3_finalize(stmt);</span><br><span style="color: hsl(120, 100%, 40%);">+ return (rc == SQLITE_ROW);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Indicate whether the database is initialized with tables for schema version 0.</span><br><span style="color: hsl(120, 100%, 40%);">+ * We only check for the 'subscriber' table here because Neels said so. */</span><br><span style="color: hsl(120, 100%, 40%);">+static bool db_is_bootstrapped_v0(struct db_context *dbc)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!db_table_exists(dbc, "subscriber")) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DDB, LOGL_DEBUG, "Table 'subscriber' not found in database '%s'\n", dbc->fname);</span><br><span style="color: hsl(120, 100%, 40%);">+ return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return true;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static int db_get_user_version(struct db_context *dbc)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const char *user_version_sql = "PRAGMA user_version";</span><br><span style="color: hsl(120, 100%, 40%);">+ sqlite3_stmt *stmt;</span><br><span style="color: hsl(120, 100%, 40%);">+ int version, rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = sqlite3_prepare_v2(dbc->db, user_version_sql, -1, &stmt, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc != SQLITE_OK) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DDB, LOGL_ERROR, "Unable to prepare SQL statement '%s'\n", user_version_sql);</span><br><span style="color: hsl(120, 100%, 40%);">+ return -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = sqlite3_step(stmt);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc == SQLITE_ROW) {</span><br><span style="color: hsl(120, 100%, 40%);">+ version = sqlite3_column_int(stmt, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DDB, LOGL_ERROR, "SQL statement '%s' failed: %d\n", user_version_sql, rc);</span><br><span style="color: hsl(120, 100%, 40%);">+ version = -1;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ db_remove_reset(stmt);</span><br><span style="color: hsl(120, 100%, 40%);">+ sqlite3_finalize(stmt);</span><br><span style="color: hsl(120, 100%, 40%);">+ return version;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+struct db_context *db_open(void *ctx, const char *fname, bool enable_sqlite_logging, bool allow_upgrade)</span><br><span> {</span><br><span> struct db_context *dbc = talloc_zero(ctx, struct db_context);</span><br><span> unsigned int i;</span><br><span> int rc;</span><br><span> bool has_sqlite_config_sqllog = false;</span><br><span style="color: hsl(120, 100%, 40%);">+ int version;</span><br><span> </span><br><span> LOGP(DDB, LOGL_NOTICE, "using database: %s\n", fname);</span><br><span> LOGP(DDB, LOGL_INFO, "Compiled against SQLite3 lib version %s\n", SQLITE_VERSION);</span><br><span>@@ -275,10 +331,40 @@</span><br><span> LOGP(DDB, LOGL_ERROR, "Unable to set Write-Ahead Logging: %s\n",</span><br><span> err_msg);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- rc = db_bootstrap(dbc);</span><br><span style="color: hsl(0, 100%, 40%);">- if (rc != SQLITE_OK) {</span><br><span style="color: hsl(0, 100%, 40%);">- LOGP(DDB, LOGL_ERROR, "Failed to bootstrap DB: (rc=%d) %s\n",</span><br><span style="color: hsl(0, 100%, 40%);">- rc, sqlite3_errmsg(dbc->db));</span><br><span style="color: hsl(120, 100%, 40%);">+ version = db_get_user_version(dbc);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (version < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DDB, LOGL_ERROR, "Unable to read user version number from database '%s'\n", dbc->fname);</span><br><span style="color: hsl(120, 100%, 40%);">+ goto out_free;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* An empty database will always report version zero. */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (version == 0 && !db_is_bootstrapped_v0(dbc)) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DDB, LOGL_NOTICE, "Missing database tables detected; Bootstrapping database '%s'\n", dbc->fname);</span><br><span style="color: hsl(120, 100%, 40%);">+ rc = db_bootstrap(dbc);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (rc != SQLITE_OK) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DDB, LOGL_ERROR, "Failed to bootstrap DB: (rc=%d) %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ rc, sqlite3_errmsg(dbc->db));</span><br><span style="color: hsl(120, 100%, 40%);">+ goto out_free;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DDB, LOGL_NOTICE, "Database '%s' has HLR DB schema version %d\n", dbc->fname, version);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (version < CURRENT_SCHEMA_VERSION && allow_upgrade) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Future version upgrades will happen here. */</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ if (version != CURRENT_SCHEMA_VERSION) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (version < CURRENT_SCHEMA_VERSION) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DDB, LOGL_NOTICE, "HLR DB schema version %d is outdated\n", version);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (!allow_upgrade) {</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DDB, LOGL_ERROR, "Not upgrading HLR database to schema version %d; "</span><br><span style="color: hsl(120, 100%, 40%);">+ "use the --db-upgrade option to allow HLR database upgrades\n",</span><br><span style="color: hsl(120, 100%, 40%);">+ CURRENT_SCHEMA_VERSION);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+ } else</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DDB, LOGL_ERROR, "HLR DB schema version %d is unknown\n", version);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> goto out_free;</span><br><span> }</span><br><span> </span><br><span>diff --git a/src/db.h b/src/db.h</span><br><span>index 34582c8..66dfe57 100644</span><br><span>--- a/src/db.h</span><br><span>+++ b/src/db.h</span><br><span>@@ -39,7 +39,7 @@</span><br><span> bool db_bind_int(sqlite3_stmt *stmt, const char *param_name, int nr);</span><br><span> bool db_bind_int64(sqlite3_stmt *stmt, const char *param_name, int64_t nr);</span><br><span> void db_close(struct db_context *dbc);</span><br><span style="color: hsl(0, 100%, 40%);">-struct db_context *db_open(void *ctx, const char *fname, bool enable_sqlite3_logging);</span><br><span style="color: hsl(120, 100%, 40%);">+struct db_context *db_open(void *ctx, const char *fname, bool enable_sqlite3_logging, bool allow_upgrades);</span><br><span> </span><br><span> #include <osmocom/crypt/auth.h></span><br><span> </span><br><span>diff --git a/src/hlr.c b/src/hlr.c</span><br><span>index 78d6c91..14945b6 100644</span><br><span>--- a/src/hlr.c</span><br><span>+++ b/src/hlr.c</span><br><span>@@ -483,6 +483,7 @@</span><br><span> printf(" -s --disable-color Do not print ANSI colors in the log\n");</span><br><span> printf(" -T --timestamp Prefix every log line with a timestamp.\n");</span><br><span> printf(" -e --log-level number Set a global loglevel.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ printf(" -U --db-upgrade Allow HLR database schema upgrades.\n");</span><br><span> printf(" -V --version Print the version of OsmoHLR.\n");</span><br><span> }</span><br><span> </span><br><span>@@ -490,10 +491,12 @@</span><br><span> const char *config_file;</span><br><span> const char *db_file;</span><br><span> bool daemonize;</span><br><span style="color: hsl(120, 100%, 40%);">+ bool db_upgrade;</span><br><span> } cmdline_opts = {</span><br><span> .config_file = "osmo-hlr.cfg",</span><br><span> .db_file = "hlr.db",</span><br><span> .daemonize = false,</span><br><span style="color: hsl(120, 100%, 40%);">+ .db_upgrade = false,</span><br><span> };</span><br><span> </span><br><span> static void handle_options(int argc, char **argv)</span><br><span>@@ -509,11 +512,12 @@</span><br><span> {"disable-color", 0, 0, 's'},</span><br><span> {"log-level", 1, 0, 'e'},</span><br><span> {"timestamp", 0, 0, 'T'},</span><br><span style="color: hsl(120, 100%, 40%);">+ {"db-upgrade", 0, 0, 'U' },</span><br><span> {"version", 0, 0, 'V' },</span><br><span> {0, 0, 0, 0}</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- c = getopt_long(argc, argv, "hc:l:d:Dse:TV",</span><br><span style="color: hsl(120, 100%, 40%);">+ c = getopt_long(argc, argv, "hc:l:d:Dse:TUV",</span><br><span> long_options, &option_index);</span><br><span> if (c == -1)</span><br><span> break;</span><br><span>@@ -544,6 +548,9 @@</span><br><span> case 'T':</span><br><span> log_set_print_timestamp(osmo_stderr_target, 1);</span><br><span> break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case 'U':</span><br><span style="color: hsl(120, 100%, 40%);">+ cmdline_opts.db_upgrade = true;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span> case 'V':</span><br><span> print_version(1);</span><br><span> exit(0);</span><br><span>@@ -637,7 +644,7 @@</span><br><span> exit(1);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- g_hlr->dbc = db_open(hlr_ctx, cmdline_opts.db_file, true);</span><br><span style="color: hsl(120, 100%, 40%);">+ g_hlr->dbc = db_open(hlr_ctx, cmdline_opts.db_file, true, cmdline_opts.db_upgrade);</span><br><span> if (!g_hlr->dbc) {</span><br><span> LOGP(DMAIN, LOGL_FATAL, "Error opening database\n");</span><br><span> exit(1);</span><br><span>diff --git a/src/hlr_db_tool.c b/src/hlr_db_tool.c</span><br><span>index e83b098..1a9c60c 100644</span><br><span>--- a/src/hlr_db_tool.c</span><br><span>+++ b/src/hlr_db_tool.c</span><br><span>@@ -44,8 +44,10 @@</span><br><span> const char *db_file;</span><br><span> bool bootstrap;</span><br><span> const char *import_nitb_db;</span><br><span style="color: hsl(120, 100%, 40%);">+ bool db_upgrade;</span><br><span> } cmdline_opts = {</span><br><span> .db_file = "hlr.db",</span><br><span style="color: hsl(120, 100%, 40%);">+ .db_upgrade = false,</span><br><span> };</span><br><span> </span><br><span> static void print_help()</span><br><span>@@ -59,6 +61,7 @@</span><br><span> printf(" -s --disable-color Do not print ANSI colors in the log\n");</span><br><span> printf(" -T --timestamp Prefix every log line with a timestamp.\n");</span><br><span> printf(" -e --log-level number Set a global loglevel.\n");</span><br><span style="color: hsl(120, 100%, 40%);">+ printf(" -U --db-upgrade Allow HLR database schema upgrades.\n");</span><br><span> printf(" -V --version Print the version of OsmoHLR-db-tool.\n");</span><br><span> printf("\n");</span><br><span> printf("Commands:\n");</span><br><span>@@ -96,11 +99,12 @@</span><br><span> {"disable-color", 0, 0, 's'},</span><br><span> {"timestamp", 0, 0, 'T'},</span><br><span> {"log-level", 1, 0, 'e'},</span><br><span style="color: hsl(120, 100%, 40%);">+ {"db-upgrade", 0, 0, 'U' },</span><br><span> {"version", 0, 0, 'V' },</span><br><span> {0, 0, 0, 0}</span><br><span> };</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- c = getopt_long(argc, argv, "hl:d:sTe:V",</span><br><span style="color: hsl(120, 100%, 40%);">+ c = getopt_long(argc, argv, "hl:d:sTe:UV",</span><br><span> long_options, &option_index);</span><br><span> if (c == -1)</span><br><span> break;</span><br><span>@@ -124,6 +128,9 @@</span><br><span> case 'e':</span><br><span> log_set_log_level(osmo_stderr_target, atoi(optarg));</span><br><span> break;</span><br><span style="color: hsl(120, 100%, 40%);">+ case 'U':</span><br><span style="color: hsl(120, 100%, 40%);">+ cmdline_opts.db_upgrade = true;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span> case 'V':</span><br><span> print_version(1);</span><br><span> exit(EXIT_SUCCESS);</span><br><span>@@ -409,7 +416,7 @@</span><br><span> exit(EXIT_FAILURE);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- g_hlr_db_tool_ctx->dbc = db_open(g_hlr_db_tool_ctx, cmdline_opts.db_file, true);</span><br><span style="color: hsl(120, 100%, 40%);">+ g_hlr_db_tool_ctx->dbc = db_open(g_hlr_db_tool_ctx, cmdline_opts.db_file, true, cmdline_opts.db_upgrade);</span><br><span> if (!g_hlr_db_tool_ctx->dbc) {</span><br><span> LOGP(DMAIN, LOGL_FATAL, "Error opening database\n");</span><br><span> exit(EXIT_FAILURE);</span><br><span>diff --git a/tests/db/db_test.c b/tests/db/db_test.c</span><br><span>index 058588b..c4ed6ed 100644</span><br><span>--- a/tests/db/db_test.c</span><br><span>+++ b/tests/db/db_test.c</span><br><span>@@ -850,7 +850,7 @@</span><br><span> log_set_log_level(osmo_stderr_target, LOGL_ERROR);</span><br><span> /* Disable SQLite logging so that we're not vulnerable on SQLite error messages changing across</span><br><span> * library versions. */</span><br><span style="color: hsl(0, 100%, 40%);">- dbc = db_open(ctx, "db_test.db", false);</span><br><span style="color: hsl(120, 100%, 40%);">+ dbc = db_open(ctx, "db_test.db", false, false);</span><br><span> log_set_log_level(osmo_stderr_target, 0);</span><br><span> OSMO_ASSERT(dbc);</span><br><span> </span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/11898">change 11898</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/11898"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: osmo-hlr </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: I8aeaa9a404b622657cbc7138106f38aa6ad8d01b </div>
<div style="display:none"> Gerrit-Change-Number: 11898 </div>
<div style="display:none"> Gerrit-PatchSet: 10 </div>
<div style="display:none"> Gerrit-Owner: Stefan Sperling <ssperling@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder (1000002) </div>
<div style="display:none"> Gerrit-Reviewer: Neels Hofmeyr <nhofmeyr@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Pau Espin Pedrol <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Stefan Sperling <ssperling@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Vadim Yanitskiy <axilirator@gmail.com> </div>