summaryrefslogtreecommitdiff
path: root/db.c
blob: cc44489a3335c63878ad1399f92f2e6850ec19c5 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
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;
}