source: ogServer-Git/src/schema.c @ 7d74d42

Last change on this file since 7d74d42 was 7d74d42, checked in by OpenGnSys Support Team <soporte-og@…>, 3 years ago

#1042 Update database schema automatically

This patch adds database schema management capabilities to ogServer:

  • ogServer now tracks the version of its database schema, if no version

is detected, creates a 'version' table with a single row starting at 0.

  • ogServer can upgrade its database schema to a newer version if

detected. (ogServer ships required SQL commands to do so)

If ogServer is unable to upgrade the schema at startup (if needed be) it
*will not* start.

Defines schema update v1 which upgrades database engine tables of
ogServer database (usually named 'ogAdmBD') from myISAM to innoDB.

  • Property mode set to 100644
File size: 4.0 KB
Line 
1/*
2 * Copyright (C) 2021 Soleta Networks <info@soleta.eu>
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Affero General Public License as published by the
6 * Free Software Foundation, version 3.
7 */
8
9#include <syslog.h>
10#include <netinet/in.h>
11#include <arpa/inet.h>
12#include <string.h>
13#include "dbi.h"
14#include "cfg.h"
15#include <syslog.h>
16#include <string.h>
17#include <stdio.h>
18
19struct og_server_cfg ogconfig;
20
21static int og_dbi_create_version(struct og_dbi *dbi)
22{
23        const char *msglog;
24        dbi_result result;
25
26        result = dbi_conn_queryf(dbi->conn, "CREATE TABLE `version` "
27                                            "(`version` smallint unsigned NOT NULL) "
28                                            "ENGINE='MyISAM' COLLATE 'utf8_general_ci'");
29        if (!result) {
30                dbi_conn_error(dbi->conn, &msglog);
31                syslog(LOG_INFO, "Could not create schema version table (%s:%d) %s\n",
32                       __func__, __LINE__, msglog);
33                return -1;
34        }
35        dbi_result_free(result);
36
37        result = dbi_conn_queryf(dbi->conn, "INSERT INTO `version` (`version`) VALUES ('0')");
38        if (!result) {
39                dbi_conn_error(dbi->conn, &msglog);
40                syslog(LOG_INFO, "Could not insert into schema version table (%s:%d) %s\n",
41                       __func__, __LINE__, msglog);
42                return -1;
43        }
44        dbi_result_free(result);
45
46        return 0;
47}
48static int og_dbi_schema_version(struct og_dbi *dbi)
49{
50        const char *msglog;
51        dbi_result result;
52        uint32_t version;
53
54        result = dbi_conn_queryf(dbi->conn, "SELECT * from version");
55        if (!result) {
56                dbi_conn_error(dbi->conn, &msglog);
57                syslog(LOG_INFO, "no version table found (%s:%d) %s\n",
58                       __func__, __LINE__, msglog);
59                return -1;
60        }
61
62        if (!dbi_result_last_row(result)) {
63                dbi_conn_error(dbi->conn, &msglog);
64                syslog(LOG_ERR, "cannot get last row from version table (%s:%d) %s\n",
65                       __func__, __LINE__, msglog);
66                return -1;
67        }
68
69        version = dbi_result_get_uint(result, "version");
70
71        dbi_result_free(result);
72
73        return version;
74}
75static int og_dbi_schema_v1(struct og_dbi *dbi)
76{
77        const char *msglog, *command;
78        dbi_result result, result_alter;
79
80        result = dbi_conn_queryf(dbi->conn, "SELECT concat('alter table `',TABLE_SCHEMA,'`.`',TABLE_NAME,'` engine=innodb;')"
81                                            "AS cmd FROM information_schema.TABLES WHERE TABLE_SCHEMA='%s'",
82                                            ogconfig.db.name);
83
84        while (dbi_result_next_row(result)) {
85                command = dbi_result_get_string(result, "cmd");
86
87                syslog(LOG_DEBUG, "Upgrading to innoDB: %s\n", command);
88                result_alter = dbi_conn_query(dbi->conn, command);
89                if (!result_alter) {
90                        dbi_conn_error(dbi->conn, &msglog);
91                        syslog(LOG_INFO, "Error when upgrading engine to innoDB (%s:%d) %s\n",
92                               __func__, __LINE__, msglog);
93                        return -1;
94                }
95                dbi_result_free(result_alter);
96        }
97        dbi_result_free(result);
98
99        result = dbi_conn_query(dbi->conn, "UPDATE version SET version = 1");
100        if (!result) {
101                dbi_conn_error(dbi->conn, &msglog);
102                syslog(LOG_INFO, "Could not update version row (%s:%d) %s\n",
103                       __func__, __LINE__, msglog);
104                return -1;
105        }
106        dbi_result_free(result);
107
108        return 0;
109}
110
111static struct og_schema_version {
112        int     version;
113        int     (*update)(struct og_dbi *dbi);
114} schema_version[] = {
115        {       .version = 1,   .update = og_dbi_schema_v1      },
116        {       0,              NULL                            },
117};
118
119int og_dbi_schema_update(void)
120{
121        int version, i, err;
122        struct og_dbi *dbi;
123        const char *msglog;
124
125        dbi = og_dbi_open(&ogconfig.db);
126        if (!dbi) {
127                dbi_conn_error(dbi->conn, &msglog);
128                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
129                       __func__, __LINE__, msglog);
130                return -1;
131        }
132
133        version = og_dbi_schema_version(dbi);
134
135        if (version < 0) {
136                syslog(LOG_INFO, "creating table version in schema\n");
137                og_dbi_create_version(dbi);
138        } else {
139                syslog(LOG_INFO, "database schema version %d\n", version);
140        }
141
142        for (i = 0; schema_version[i].version; i++) {
143                if (version >= schema_version[i].version)
144                        continue;
145
146                syslog(LOG_INFO, "upgrading to schema version %d\n", schema_version[i].version);
147
148                err = schema_version[i].update(dbi);
149                if (err < 0) {
150                        syslog(LOG_ERR, "failed to update schema!\n");
151                        og_dbi_close(dbi);
152                        return -1;
153                }
154        }
155
156        og_dbi_close(dbi);
157
158        return 0;
159}
Note: See TracBrowser for help on using the repository browser.