summaryrefslogtreecommitdiff
path: root/db.c
diff options
context:
space:
mode:
Diffstat (limited to 'db.c')
-rw-r--r--db.c124
1 files changed, 124 insertions, 0 deletions
diff --git a/db.c b/db.c
new file mode 100644
index 0000000..ff9388c
--- /dev/null
+++ b/db.c
@@ -0,0 +1,124 @@
+//
+// Created by yuuta on 11/28/21.
+//
+
+#include "db.h"
+#include "log.h"
+#include "botd.h"
+
+#include <stdio.h>
+#include <sqlite3.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <stdbool.h>
+
+#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;
+}