/* * Created by yuuta on 11/28/21. */ #include "db.h" #include "log.h" #include "botd.h" #include #include #include #include #include #include #ifndef SQL_PATH #define SQL_PATH "../sql/" #endif sqlite3 *db = NULL; void db_init(void) { int r; r = sqlite3_open(cmd.db_path, &db); if (r) { LOGFEV("Cannot open SQLite3 database: %s", r, sqlite3_errstr(r)); } char *errmsg = NULL; /* Enable foreign key support */ r = sqlite3_exec(db, "PRAGMA foreign_keys = ON;", NULL, NULL, &errmsg); if (r) { goto sql_err; sql_err: db_close(); LOGFEV("%s", r, errmsg); } /* Get user_version */ sqlite3_stmt *stmt; r = sqlite3_prepare_v2(db, "PRAGMA user_version", -1, &stmt, 0); if (r) { goto sql_err; } r = sqlite3_step(stmt); if (r != SQLITE_ROW) { sqlite3_finalize(stmt); goto sql_err; } const int current_var = sqlite3_column_int(stmt, 0); r = sqlite3_finalize(stmt); /* Upgrade one by one */ FILE *fd_sql = NULL; char *path_sql = NULL; const unsigned int path_len = strlen(SQL_PATH) + 20; path_sql = calloc(path_len, sizeof(char)); if (path_sql == NULL) { r = errno; db_close(); LOGFEV("Cannot allocate memory: %s", r, strerror(r)); } for (int i = current_var; true; i++) { snprintf(path_sql, path_len - 1, "%s/%d_%d.sql", SQL_PATH, i, i + 1); fd_sql = fopen(path_sql, "r"); if (fd_sql == NULL) { if (errno != ENOENT) { r = errno; free(path_sql); db_close(); LOGFEV("Cannot upgrade database to %d: %s", r, i + 1, strerror(r)); } break; } char *sql_str = NULL; char *line = NULL; size_t len = 0; ssize_t tread = 0; ssize_t nread; while ((nread = getline(&line, &len, fd_sql)) != -1) { tread += nread; if (sql_str == NULL) { sql_str = calloc(nread + 1, sizeof(char)); if (sql_str == NULL) { r = errno; fclose(fd_sql); free(line); free(path_sql); db_close(); LOGFEV("Cannot allocate memory: %s", r, strerror(r)); } strcpy(sql_str, line); } else { char *newptr = realloc(sql_str, (tread + 1) * sizeof(char)); if (newptr == NULL) { r = errno; fclose(fd_sql); free(line); free(sql_str); free(path_sql); db_close(); LOGFEV("Cannot allocate memory: %s", r, strerror(r)); } sql_str = newptr; strcat(sql_str, line); } } fclose(fd_sql); free(line); r = sqlite3_exec(db, sql_str, NULL, NULL, &errmsg); if (r) { free(sql_str); db_close(); LOGFV("%s", errmsg); break; } free(sql_str); } free(path_sql); } void db_close(void) { if (db == NULL) return; sqlite3_close(db); db = NULL; }