blob: 892943a0421919df37e519edcf77203923fb8df0 [file] [log] [blame]
Harald Weltee72cf552016-04-28 07:18:49 +02001/* (C) 2015 by Harald Welte <laforge@gnumonks.org>
2 *
3 * All Rights Reserved
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU Affero General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU Affero General Public License for more details.
14 *
15 * You should have received a copy of the GNU Affero General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 *
18 */
19
20#include <osmocom/core/utils.h>
21
Max00b37152017-02-20 11:09:27 +010022#include <stdbool.h>
Harald Weltee72cf552016-04-28 07:18:49 +020023#include <sqlite3.h>
Neels Hofmeyrcd83b8a2017-10-06 04:20:37 +020024#include <string.h>
Harald Weltee72cf552016-04-28 07:18:49 +020025
26#include "logging.h"
27#include "db.h"
Neels Hofmeyr7750d2c2017-10-24 23:26:27 +020028#include "db_bootstrap.h"
Harald Weltee72cf552016-04-28 07:18:49 +020029
Stefan Sperling638ba8c2018-12-04 15:07:29 +010030/* This constant is currently duplicated in sql/hlr.sql and must be kept in sync! */
Neels Hofmeyr0f9daa62018-12-29 03:28:38 +010031#define CURRENT_SCHEMA_VERSION 3
Stefan Sperling8f3a7cc2018-11-27 12:10:45 +010032
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +020033#define SEL_COLUMNS \
34 "id," \
35 "imsi," \
36 "msisdn," \
37 "vlr_number," \
38 "sgsn_number," \
39 "sgsn_address," \
40 "periodic_lu_tmr," \
41 "periodic_rau_tau_tmr," \
42 "nam_cs," \
43 "nam_ps," \
44 "lmsi," \
45 "ms_purged_cs," \
Stefan Sperling638ba8c2018-12-04 15:07:29 +010046 "ms_purged_ps," \
Neels Hofmeyr0f9daa62018-12-29 03:28:38 +010047 "last_lu_seen," \
48 "last_lu_rat"
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +020049
Harald Weltee72cf552016-04-28 07:18:49 +020050static const char *stmt_sql[] = {
Neels Hofmeyr9c2bbc82017-10-09 17:30:32 +020051 [DB_STMT_SEL_BY_IMSI] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE imsi = ?",
52 [DB_STMT_SEL_BY_MSISDN] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE msisdn = ?",
53 [DB_STMT_SEL_BY_ID] = "SELECT " SEL_COLUMNS " FROM subscriber WHERE id = ?",
Neels Hofmeyrdd783052017-10-09 17:36:08 +020054 [DB_STMT_UPD_VLR_BY_ID] = "UPDATE subscriber SET vlr_number = $number WHERE id = $subscriber_id",
55 [DB_STMT_UPD_SGSN_BY_ID] = "UPDATE subscriber SET sgsn_number = $number WHERE id = $subscriber_id",
Neels Hofmeyr0cac0a02017-10-09 17:47:21 +020056 [DB_STMT_AUC_BY_IMSI] =
57 "SELECT id, algo_id_2g, ki, algo_id_3g, k, op, opc, sqn, ind_bitlen"
58 " FROM subscriber"
59 " LEFT JOIN auc_2g ON auc_2g.subscriber_id = subscriber.id"
60 " LEFT JOIN auc_3g ON auc_3g.subscriber_id = subscriber.id"
Neels Hofmeyrc5122f22017-10-09 23:12:57 +020061 " WHERE imsi = $imsi",
Neels Hofmeyr1cbdb702017-10-09 23:03:57 +020062 [DB_STMT_AUC_UPD_SQN] = "UPDATE auc_3g SET sqn = $sqn WHERE subscriber_id = $subscriber_id",
Neels Hofmeyre50121e2017-10-09 17:48:51 +020063 [DB_STMT_UPD_PURGE_CS_BY_IMSI] = "UPDATE subscriber SET ms_purged_cs = $val WHERE imsi = $imsi",
64 [DB_STMT_UPD_PURGE_PS_BY_IMSI] = "UPDATE subscriber SET ms_purged_ps = $val WHERE imsi = $imsi",
Neels Hofmeyre8ccd502017-10-06 04:10:06 +020065 [DB_STMT_UPD_NAM_CS_BY_IMSI] = "UPDATE subscriber SET nam_cs = $val WHERE imsi = $imsi",
66 [DB_STMT_UPD_NAM_PS_BY_IMSI] = "UPDATE subscriber SET nam_ps = $val WHERE imsi = $imsi",
Neels Hofmeyrf7c3e6e2017-10-09 17:55:16 +020067 [DB_STMT_SUBSCR_CREATE] = "INSERT INTO subscriber (imsi) VALUES ($imsi)",
68 [DB_STMT_DEL_BY_ID] = "DELETE FROM subscriber WHERE id = $subscriber_id",
69 [DB_STMT_SET_MSISDN_BY_IMSI] = "UPDATE subscriber SET msisdn = $msisdn WHERE imsi = $imsi",
Neels Hofmeyra820ea12018-12-02 19:46:46 +010070 [DB_STMT_DELETE_MSISDN_BY_IMSI] = "UPDATE subscriber SET msisdn = NULL WHERE imsi = $imsi",
Neels Hofmeyr1332a172017-10-10 02:25:00 +020071 [DB_STMT_AUC_2G_INSERT] =
72 "INSERT INTO auc_2g (subscriber_id, algo_id_2g, ki)"
73 " VALUES($subscriber_id, $algo_id_2g, $ki)",
74 [DB_STMT_AUC_2G_DELETE] = "DELETE FROM auc_2g WHERE subscriber_id = $subscriber_id",
75 [DB_STMT_AUC_3G_INSERT] =
76 "INSERT INTO auc_3g (subscriber_id, algo_id_3g, k, op, opc, ind_bitlen)"
77 " VALUES($subscriber_id, $algo_id_3g, $k, $op, $opc, $ind_bitlen)",
78 [DB_STMT_AUC_3G_DELETE] = "DELETE FROM auc_3g WHERE subscriber_id = $subscriber_id",
Neels Hofmeyr0f9daa62018-12-29 03:28:38 +010079 [DB_STMT_SET_LAST_LU_SEEN] = "UPDATE subscriber SET last_lu_seen = datetime($val, 'unixepoch'), last_lu_rat = $rat"
80 " WHERE id = $subscriber_id",
Neels Hofmeyr2fb33f12018-12-26 01:49:53 +010081 [DB_STMT_UPD_RAT_FLAG] = "INSERT OR REPLACE INTO subscriber_rat (subscriber_id, rat, allowed)"
82 " VALUES ($subscriber_id, $rat, $allowed)",
83 [DB_STMT_RAT_BY_ID] =
84 "SELECT rat, allowed"
85 " FROM subscriber_rat"
86 " WHERE subscriber_id = $subscriber_id",
Harald Weltee72cf552016-04-28 07:18:49 +020087};
88
89static void sql3_error_log_cb(void *arg, int err_code, const char *msg)
90{
91 LOGP(DDB, LOGL_ERROR, "(%d) %s\n", err_code, msg);
92}
93
94static void sql3_sql_log_cb(void *arg, sqlite3 *s3, const char *stmt, int type)
95{
96 switch (type) {
97 case 0:
98 LOGP(DDB, LOGL_DEBUG, "Opened database\n");
99 break;
100 case 1:
Max58d4a842017-02-20 11:06:12 +0100101 LOGP(DDB, LOGL_DEBUG, "%s\n", stmt);
Harald Weltee72cf552016-04-28 07:18:49 +0200102 break;
103 case 2:
104 LOGP(DDB, LOGL_DEBUG, "Closed database\n");
105 break;
106 default:
107 LOGP(DDB, LOGL_DEBUG, "Unknown %d\n", type);
108 break;
109 }
110}
111
Max00b37152017-02-20 11:09:27 +0100112/* remove bindings and reset statement to be re-executed */
Neels Hofmeyrd7d96972017-10-06 03:50:30 +0200113void db_remove_reset(sqlite3_stmt *stmt)
Max00b37152017-02-20 11:09:27 +0100114{
Neels Hofmeyrd7d96972017-10-06 03:50:30 +0200115 sqlite3_clear_bindings(stmt);
Neels Hofmeyr4f3841c2017-11-07 13:24:44 +0100116 /* sqlite3_reset() just repeats an error code already evaluated during sqlite3_step(). */
117 /* coverity[CHECKED_RETURN] */
Neels Hofmeyrd7d96972017-10-06 03:50:30 +0200118 sqlite3_reset(stmt);
Max00b37152017-02-20 11:09:27 +0100119}
120
Neels Hofmeyrf3144592017-10-06 03:40:52 +0200121/** bind text arg and do proper cleanup in case of failure. If param_name is
122 * NULL, bind to the first parameter (useful for SQL statements that have only
123 * one parameter). */
124bool db_bind_text(sqlite3_stmt *stmt, const char *param_name, const char *text)
Max00b37152017-02-20 11:09:27 +0100125{
Neels Hofmeyrf3144592017-10-06 03:40:52 +0200126 int rc;
127 int idx = param_name ? sqlite3_bind_parameter_index(stmt, param_name) : 1;
128 if (idx < 1) {
129 LOGP(DDB, LOGL_ERROR, "Error composing SQL, cannot bind parameter '%s'\n",
130 param_name);
131 return false;
132 }
133 rc = sqlite3_bind_text(stmt, idx, text, -1, SQLITE_STATIC);
Max00b37152017-02-20 11:09:27 +0100134 if (rc != SQLITE_OK) {
Neels Hofmeyrf3144592017-10-06 03:40:52 +0200135 LOGP(DDB, LOGL_ERROR, "Error binding text to SQL parameter %s: %d\n",
136 param_name ? param_name : "#1", rc);
Max00b37152017-02-20 11:09:27 +0100137 db_remove_reset(stmt);
138 return false;
139 }
Max00b37152017-02-20 11:09:27 +0100140 return true;
141}
142
Neels Hofmeyr28da26e2017-10-06 03:44:57 +0200143/** bind int arg and do proper cleanup in case of failure. If param_name is
144 * NULL, bind to the first parameter (useful for SQL statements that have only
145 * one parameter). */
146bool db_bind_int(sqlite3_stmt *stmt, const char *param_name, int nr)
147{
148 int rc;
149 int idx = param_name ? sqlite3_bind_parameter_index(stmt, param_name) : 1;
150 if (idx < 1) {
151 LOGP(DDB, LOGL_ERROR, "Error composing SQL, cannot bind parameter '%s'\n",
152 param_name);
153 return false;
154 }
155 rc = sqlite3_bind_int(stmt, idx, nr);
156 if (rc != SQLITE_OK) {
157 LOGP(DDB, LOGL_ERROR, "Error binding int64 to SQL parameter %s: %d\n",
158 param_name ? param_name : "#1", rc);
159 db_remove_reset(stmt);
160 return false;
161 }
162 return true;
163}
164
165/** bind int64 arg and do proper cleanup in case of failure. If param_name is
166 * NULL, bind to the first parameter (useful for SQL statements that have only
167 * one parameter). */
168bool db_bind_int64(sqlite3_stmt *stmt, const char *param_name, int64_t nr)
169{
170 int rc;
171 int idx = param_name ? sqlite3_bind_parameter_index(stmt, param_name) : 1;
172 if (idx < 1) {
173 LOGP(DDB, LOGL_ERROR, "Error composing SQL, cannot bind parameter '%s'\n",
174 param_name);
175 return false;
176 }
177 rc = sqlite3_bind_int64(stmt, idx, nr);
178 if (rc != SQLITE_OK) {
179 LOGP(DDB, LOGL_ERROR, "Error binding int64 to SQL parameter %s: %d\n",
180 param_name ? param_name : "#1", rc);
181 db_remove_reset(stmt);
182 return false;
183 }
184 return true;
185}
186
Harald Weltee72cf552016-04-28 07:18:49 +0200187void db_close(struct db_context *dbc)
188{
189 unsigned int i;
Vadim Yanitskiydc17e052018-07-30 20:14:16 +0700190 int rc;
Harald Weltee72cf552016-04-28 07:18:49 +0200191
192 for (i = 0; i < ARRAY_SIZE(dbc->stmt); i++) {
193 /* it is ok to call finalize on NULL */
194 sqlite3_finalize(dbc->stmt[i]);
195 }
Vadim Yanitskiydc17e052018-07-30 20:14:16 +0700196
197 /* Ask sqlite3 to close DB */
198 rc = sqlite3_close(dbc->db);
199 if (rc != SQLITE_OK) { /* Make sure it's actually closed! */
200 LOGP(DDB, LOGL_ERROR, "Couldn't close database: (rc=%d) %s\n",
201 rc, sqlite3_errmsg(dbc->db));
202 }
203
Harald Weltee72cf552016-04-28 07:18:49 +0200204 talloc_free(dbc);
205}
206
Neels Hofmeyr7750d2c2017-10-24 23:26:27 +0200207static int db_bootstrap(struct db_context *dbc)
208{
209 int i;
210 for (i = 0; i < ARRAY_SIZE(stmt_bootstrap_sql); i++) {
211 int rc;
212 sqlite3_stmt *stmt;
Stefan Sperling8f3a7cc2018-11-27 12:10:45 +0100213 rc = sqlite3_prepare_v2(dbc->db, stmt_bootstrap_sql[i], -1, &stmt, NULL);
Neels Hofmeyr7750d2c2017-10-24 23:26:27 +0200214 if (rc != SQLITE_OK) {
Stefan Sperling8f3a7cc2018-11-27 12:10:45 +0100215 LOGP(DDB, LOGL_ERROR, "Unable to prepare SQL statement '%s'\n", stmt_bootstrap_sql[i]);
Vadim Yanitskiy050eb1d2018-07-30 20:48:19 +0700216 return rc;
Neels Hofmeyr7750d2c2017-10-24 23:26:27 +0200217 }
218
Neels Hofmeyr7750d2c2017-10-24 23:26:27 +0200219 rc = sqlite3_step(stmt);
220 db_remove_reset(stmt);
Vadim Yanitskiydc17e052018-07-30 20:14:16 +0700221 sqlite3_finalize(stmt);
Neels Hofmeyr7750d2c2017-10-24 23:26:27 +0200222 if (rc != SQLITE_DONE) {
223 LOGP(DDB, LOGL_ERROR, "Cannot bootstrap database: SQL error: (%d) %s,"
224 " during stmt '%s'",
Stefan Sperling8f3a7cc2018-11-27 12:10:45 +0100225 rc, sqlite3_errmsg(dbc->db), stmt_bootstrap_sql[i]);
Vadim Yanitskiy050eb1d2018-07-30 20:48:19 +0700226 return rc;
Neels Hofmeyr7750d2c2017-10-24 23:26:27 +0200227 }
228 }
Vadim Yanitskiy050eb1d2018-07-30 20:48:19 +0700229 return SQLITE_OK;
Neels Hofmeyr7750d2c2017-10-24 23:26:27 +0200230}
231
Stefan Sperling8f3a7cc2018-11-27 12:10:45 +0100232/* https://www.sqlite.org/fileformat2.html#storage_of_the_sql_database_schema */
233static bool db_table_exists(struct db_context *dbc, const char *table_name)
234{
235 const char *table_exists_sql = "SELECT name FROM sqlite_master WHERE type='table' AND name=?";
236 sqlite3_stmt *stmt;
237 int rc;
238
239 rc = sqlite3_prepare_v2(dbc->db, table_exists_sql, -1, &stmt, NULL);
240 if (rc != SQLITE_OK) {
241 LOGP(DDB, LOGL_ERROR, "Unable to prepare SQL statement '%s'\n", table_exists_sql);
242 return false;
243 }
244
245 if (!db_bind_text(stmt, NULL, table_name))
246 return false;
247
248 rc = sqlite3_step(stmt);
249 db_remove_reset(stmt);
250 sqlite3_finalize(stmt);
251 return (rc == SQLITE_ROW);
252}
253
254/* Indicate whether the database is initialized with tables for schema version 0.
255 * We only check for the 'subscriber' table here because Neels said so. */
256static bool db_is_bootstrapped_v0(struct db_context *dbc)
257{
258 if (!db_table_exists(dbc, "subscriber")) {
259 LOGP(DDB, LOGL_DEBUG, "Table 'subscriber' not found in database '%s'\n", dbc->fname);
260 return false;
261 }
262
263 return true;
264}
265
Stefan Sperling638ba8c2018-12-04 15:07:29 +0100266static int
267db_upgrade_v1(struct db_context *dbc)
268{
269 sqlite3_stmt *stmt;
270 int rc;
271 const char *update_stmt_sql = "ALTER TABLE subscriber ADD COLUMN last_lu_seen TIMESTAMP default NULL";
272 const char *set_schema_version_sql = "PRAGMA user_version = 1";
273
274 rc = sqlite3_prepare_v2(dbc->db, update_stmt_sql, -1, &stmt, NULL);
275 if (rc != SQLITE_OK) {
276 LOGP(DDB, LOGL_ERROR, "Unable to prepare SQL statement '%s'\n", update_stmt_sql);
277 return rc;
278 }
279 rc = sqlite3_step(stmt);
280 db_remove_reset(stmt);
281 sqlite3_finalize(stmt);
282 if (rc != SQLITE_DONE) {
283 LOGP(DDB, LOGL_ERROR, "Unable to update HLR database schema to version %d\n", 1);
284 return rc;
285 }
286
287 rc = sqlite3_prepare_v2(dbc->db, set_schema_version_sql, -1, &stmt, NULL);
288 if (rc != SQLITE_OK) {
289 LOGP(DDB, LOGL_ERROR, "Unable to prepare SQL statement '%s'\n", set_schema_version_sql);
290 return rc;
291 }
292 rc = sqlite3_step(stmt);
293 if (rc != SQLITE_DONE)
294 LOGP(DDB, LOGL_ERROR, "Unable to update HLR database schema to version %d\n", 1);
295
296 db_remove_reset(stmt);
297 sqlite3_finalize(stmt);
298 return rc;
299}
300
Neels Hofmeyr2fb33f12018-12-26 01:49:53 +0100301static int db_upgrade_v2(struct db_context *dbc)
302{
303 int i;
304 const char *stmts[] = {
305 "CREATE TABLE subscriber_rat",
306 "CREATE UNIQUE INDEX idx_subscr_rat_flag",
307 NULL
308 };
309 sqlite3_stmt *stmt = NULL;
310
311 for (i = 0; i < ARRAY_SIZE(stmts); i++) {
312 int rc;
313 int j;
314 const char *stmt_sql = NULL;
315
316 if (stmts[i] != NULL) {
317 for (j = 0; j < ARRAY_SIZE(stmt_bootstrap_sql); j++) {
318 if (strstr(stmt_bootstrap_sql[j], stmts[i])) {
319 /* make sure we have a unique match, hence also not break; here */
320 OSMO_ASSERT(!stmt_sql);
321 stmt_sql = stmt_bootstrap_sql[j];
322 }
323 }
324 } else
325 stmt_sql = "PRAGMA user_version = 2";
326 OSMO_ASSERT(stmt_sql);
327
328 rc = sqlite3_prepare_v2(dbc->db, stmt_sql, -1, &stmt, NULL);
329 if (rc != SQLITE_OK) {
330 LOGP(DDB, LOGL_ERROR, "Unable to prepare SQL statement '%s'\n", stmt_sql);
331 return rc;
332 }
333 rc = sqlite3_step(stmt);
334 db_remove_reset(stmt);
335 sqlite3_finalize(stmt);
336 if (rc != SQLITE_DONE) {
337 LOGP(DDB, LOGL_ERROR, "Unable to update HLR database schema to version 2: '%s'\n",
338 stmt_sql);
339 return rc;
340 }
341 }
342
343 return SQLITE_DONE;
344}
345
Neels Hofmeyr0f9daa62018-12-29 03:28:38 +0100346static int db_upgrade_v3(struct db_context *dbc)
347{
348 sqlite3_stmt *stmt;
349 int rc;
350 const char *update_stmt_sql = "ALTER TABLE subscriber ADD COLUMN last_lu_rat TEXT default NULL";
351 const char *set_schema_version_sql = "PRAGMA user_version = 3";
352
353 rc = sqlite3_prepare_v2(dbc->db, update_stmt_sql, -1, &stmt, NULL);
354 if (rc != SQLITE_OK) {
355 LOGP(DDB, LOGL_ERROR, "Unable to prepare SQL statement '%s'\n", update_stmt_sql);
356 return rc;
357 }
358 rc = sqlite3_step(stmt);
359 db_remove_reset(stmt);
360 sqlite3_finalize(stmt);
361 if (rc != SQLITE_DONE) {
362 LOGP(DDB, LOGL_ERROR, "Unable to update HLR database schema to version %d\n", 1);
363 return rc;
364 }
365
366 rc = sqlite3_prepare_v2(dbc->db, set_schema_version_sql, -1, &stmt, NULL);
367 if (rc != SQLITE_OK) {
368 LOGP(DDB, LOGL_ERROR, "Unable to prepare SQL statement '%s'\n", set_schema_version_sql);
369 return rc;
370 }
371 rc = sqlite3_step(stmt);
372 if (rc != SQLITE_DONE)
373 LOGP(DDB, LOGL_ERROR, "Unable to update HLR database schema to version 3\n");
374
375 db_remove_reset(stmt);
376 sqlite3_finalize(stmt);
377 return rc;
378}
379
Stefan Sperling8f3a7cc2018-11-27 12:10:45 +0100380static int db_get_user_version(struct db_context *dbc)
381{
382 const char *user_version_sql = "PRAGMA user_version";
383 sqlite3_stmt *stmt;
384 int version, rc;
385
386 rc = sqlite3_prepare_v2(dbc->db, user_version_sql, -1, &stmt, NULL);
387 if (rc != SQLITE_OK) {
388 LOGP(DDB, LOGL_ERROR, "Unable to prepare SQL statement '%s'\n", user_version_sql);
389 return -1;
390 }
391 rc = sqlite3_step(stmt);
392 if (rc == SQLITE_ROW) {
393 version = sqlite3_column_int(stmt, 0);
394 } else {
395 LOGP(DDB, LOGL_ERROR, "SQL statement '%s' failed: %d\n", user_version_sql, rc);
396 version = -1;
397 }
398
399 db_remove_reset(stmt);
400 sqlite3_finalize(stmt);
401 return version;
402}
403
404struct db_context *db_open(void *ctx, const char *fname, bool enable_sqlite_logging, bool allow_upgrade)
Harald Weltee72cf552016-04-28 07:18:49 +0200405{
406 struct db_context *dbc = talloc_zero(ctx, struct db_context);
407 unsigned int i;
408 int rc;
Neels Hofmeyrcd83b8a2017-10-06 04:20:37 +0200409 bool has_sqlite_config_sqllog = false;
Stefan Sperling8f3a7cc2018-11-27 12:10:45 +0100410 int version;
Harald Weltee72cf552016-04-28 07:18:49 +0200411
Neels Hofmeyr7f9491f2017-01-30 13:30:47 +0100412 LOGP(DDB, LOGL_NOTICE, "using database: %s\n", fname);
Harald Weltee72cf552016-04-28 07:18:49 +0200413 LOGP(DDB, LOGL_INFO, "Compiled against SQLite3 lib version %s\n", SQLITE_VERSION);
414 LOGP(DDB, LOGL_INFO, "Running with SQLite3 lib version %s\n", sqlite3_libversion());
415
416 dbc->fname = talloc_strdup(dbc, fname);
417
418 for (i = 0; i < 0xfffff; i++) {
419 const char *o = sqlite3_compileoption_get(i);
420 if (!o)
421 break;
Neels Hofmeyre9c0c5b2017-10-10 16:52:22 +0200422 LOGP(DDB, LOGL_DEBUG, "SQLite3 compiled with '%s'\n", o);
Neels Hofmeyrcd83b8a2017-10-06 04:20:37 +0200423 if (!strcmp(o, "ENABLE_SQLLOG"))
424 has_sqlite_config_sqllog = true;
Harald Weltee72cf552016-04-28 07:18:49 +0200425 }
426
Neels Hofmeyrd3814b92017-11-21 12:28:07 +0100427 if (enable_sqlite_logging) {
428 rc = sqlite3_config(SQLITE_CONFIG_LOG, sql3_error_log_cb, NULL);
429 if (rc != SQLITE_OK)
430 LOGP(DDB, LOGL_NOTICE, "Unable to set SQLite3 error log callback\n");
431 }
Harald Weltee72cf552016-04-28 07:18:49 +0200432
Neels Hofmeyrcd83b8a2017-10-06 04:20:37 +0200433 if (has_sqlite_config_sqllog) {
434 rc = sqlite3_config(SQLITE_CONFIG_SQLLOG, sql3_sql_log_cb, NULL);
435 if (rc != SQLITE_OK)
436 LOGP(DDB, LOGL_NOTICE, "Unable to set SQLite3 SQL log callback\n");
437 } else
438 LOGP(DDB, LOGL_DEBUG, "Not setting SQL log callback:"
439 " SQLite3 compiled without support for it\n");
Harald Weltee72cf552016-04-28 07:18:49 +0200440
441 rc = sqlite3_open(dbc->fname, &dbc->db);
442 if (rc != SQLITE_OK) {
443 LOGP(DDB, LOGL_ERROR, "Unable to open DB; rc = %d\n", rc);
444 talloc_free(dbc);
445 return NULL;
446 }
447
448 /* enable extended result codes */
449 rc = sqlite3_extended_result_codes(dbc->db, 1);
450 if (rc != SQLITE_OK)
Neels Hofmeyre9c0c5b2017-10-10 16:52:22 +0200451 LOGP(DDB, LOGL_ERROR, "Unable to enable SQLite3 extended result codes\n");
Harald Weltee72cf552016-04-28 07:18:49 +0200452
Harald Welteabd1a542016-05-03 18:50:41 +0200453 char *err_msg;
454 rc = sqlite3_exec(dbc->db, "PRAGMA journal_mode=WAL; PRAGMA synchonous = NORMAL;", 0, 0, &err_msg);
455 if (rc != SQLITE_OK)
456 LOGP(DDB, LOGL_ERROR, "Unable to set Write-Ahead Logging: %s\n",
457 err_msg);
458
Stefan Sperling8f3a7cc2018-11-27 12:10:45 +0100459 version = db_get_user_version(dbc);
460 if (version < 0) {
461 LOGP(DDB, LOGL_ERROR, "Unable to read user version number from database '%s'\n", dbc->fname);
462 goto out_free;
463 }
464
465 /* An empty database will always report version zero. */
466 if (version == 0 && !db_is_bootstrapped_v0(dbc)) {
467 LOGP(DDB, LOGL_NOTICE, "Missing database tables detected; Bootstrapping database '%s'\n", dbc->fname);
468 rc = db_bootstrap(dbc);
469 if (rc != SQLITE_OK) {
470 LOGP(DDB, LOGL_ERROR, "Failed to bootstrap DB: (rc=%d) %s\n",
471 rc, sqlite3_errmsg(dbc->db));
472 goto out_free;
473 }
Stefan Sperling638ba8c2018-12-04 15:07:29 +0100474 version = CURRENT_SCHEMA_VERSION;
Stefan Sperling8f3a7cc2018-11-27 12:10:45 +0100475 }
476
477 LOGP(DDB, LOGL_NOTICE, "Database '%s' has HLR DB schema version %d\n", dbc->fname, version);
478
479 if (version < CURRENT_SCHEMA_VERSION && allow_upgrade) {
Neels Hofmeyr2fb33f12018-12-26 01:49:53 +0100480 int orig_version = version;
481
Stefan Sperling638ba8c2018-12-04 15:07:29 +0100482 switch (version) {
483 case 0:
484 rc = db_upgrade_v1(dbc);
485 if (rc != SQLITE_DONE) {
486 LOGP(DDB, LOGL_ERROR, "Failed to upgrade HLR DB schema to version 1: (rc=%d) %s\n",
487 rc, sqlite3_errmsg(dbc->db));
488 goto out_free;
489 }
490 version = 1;
491 /* fall through */
Neels Hofmeyr2fb33f12018-12-26 01:49:53 +0100492 case 1:
493 rc = db_upgrade_v2(dbc);
494 if (rc != SQLITE_DONE) {
495 LOGP(DDB, LOGL_ERROR, "Failed to upgrade HLR DB schema to version 2: (rc=%d) %s\n",
496 rc, sqlite3_errmsg(dbc->db));
497 goto out_free;
498 }
499 version = 2;
500 /* fall through */
Neels Hofmeyr0f9daa62018-12-29 03:28:38 +0100501 case 2:
502 rc = db_upgrade_v3(dbc);
503 if (rc != SQLITE_DONE) {
504 LOGP(DDB, LOGL_ERROR, "Failed to upgrade HLR DB schema to version 3: (rc=%d) %s\n",
505 rc, sqlite3_errmsg(dbc->db));
506 goto out_free;
507 }
508 version = 2;
509 /* fall through */
Stefan Sperling638ba8c2018-12-04 15:07:29 +0100510 /* case N: ... */
511 default:
512 break;
513 }
Neels Hofmeyr2fb33f12018-12-26 01:49:53 +0100514 LOGP(DDB, LOGL_NOTICE, "Database '%s' has been upgraded from HLR DB schema version %d to %d\n",
515 dbc->fname, orig_version, version);
Stefan Sperling8f3a7cc2018-11-27 12:10:45 +0100516 }
517
518 if (version != CURRENT_SCHEMA_VERSION) {
519 if (version < CURRENT_SCHEMA_VERSION) {
520 LOGP(DDB, LOGL_NOTICE, "HLR DB schema version %d is outdated\n", version);
521 if (!allow_upgrade) {
Neels Hofmeyr2fb33f12018-12-26 01:49:53 +0100522 LOGP(DDB, LOGL_ERROR, "Not upgrading HLR database from schema version %d to %d; "
Stefan Sperling8f3a7cc2018-11-27 12:10:45 +0100523 "use the --db-upgrade option to allow HLR database upgrades\n",
Neels Hofmeyr2fb33f12018-12-26 01:49:53 +0100524 version, CURRENT_SCHEMA_VERSION);
Stefan Sperling8f3a7cc2018-11-27 12:10:45 +0100525 }
526 } else
527 LOGP(DDB, LOGL_ERROR, "HLR DB schema version %d is unknown\n", version);
528
Vadim Yanitskiy050eb1d2018-07-30 20:48:19 +0700529 goto out_free;
530 }
Neels Hofmeyr7750d2c2017-10-24 23:26:27 +0200531
Harald Weltee72cf552016-04-28 07:18:49 +0200532 /* prepare all SQL statements */
533 for (i = 0; i < ARRAY_SIZE(dbc->stmt); i++) {
534 rc = sqlite3_prepare_v2(dbc->db, stmt_sql[i], -1,
535 &dbc->stmt[i], NULL);
536 if (rc != SQLITE_OK) {
537 LOGP(DDB, LOGL_ERROR, "Unable to prepare SQL statement '%s'\n", stmt_sql[i]);
538 goto out_free;
539 }
540 }
541
542 return dbc;
543out_free:
544 db_close(dbc);
545 return NULL;
546}