source: ogServer-Git/src/schema.c @ 927d42b

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

#1042 Add schema version 2

Add foreign keys (version 1 introduced innoDB as default db engine)
allowing cascade deletions for some tables:

  • perfilessoft_softwares

If a software profile or a software component is deleted, the
corresponding row in this table will be deleted too.

  • ordenadores_particiones

If a computer or a partition is deleted from the DB, delete the
corresponding row inside this table.

  • aulas

If the center the room is in is removed, delete the room too.

  • ordenadores

If the room in which a computer is in is removed, the computer
will be deleted accordingly.

We should take into account that this schema superseeds some code
regarding deletions inside WebConsole? that probably are not needed any
more, at least for the tables mentioned.
(See admin/WebConsole/gestores/relaciones/*.php in OpenGnsys repo)

  • Property mode set to 100644
File size: 6.0 KB
RevLine 
[7d74d42]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
[8775c06]19#define OG_SCHEMA_STMTS_V2      7
20
21static const char *stmts_v2[OG_SCHEMA_STMTS_V2] = {
22        [0]     =       "ALTER TABLE `aulas` "
23                        "ADD CONSTRAINT FK_centros "
24                        "FOREIGN KEY (`idcentro`) "
25                        "REFERENCES `centros` (`idcentro`) ON DELETE CASCADE",
26        [1]     =       "ALTER TABLE `ordenadores` "
27                        "ADD CONSTRAINT FK_aulas "
28                        "FOREIGN KEY (`idaula`) "
29                        "REFERENCES `aulas` (`idaula`) ON DELETE CASCADE",
30        [2]     =       "ALTER TABLE `ordenadores_particiones` "
31                        "ADD CONSTRAINT FK_ordenadores "
32                        "FOREIGN KEY (`idordenador`) "
33                        "REFERENCES `ordenadores` (`idordenador`) ON DELETE CASCADE",
34        [3]     =       "DELETE PS FROM perfilessoft_softwares AS PS "
35                        "WHERE NOT EXISTS ("
36                        "SELECT null FROM softwares AS S "
37                        "WHERE S.idsoftware = PS.idsoftware)",
38        [4]     =       "ALTER TABLE `perfilessoft_softwares` "
39                        "ADD CONSTRAINT FK_softwares "
40                        "FOREIGN KEY (`idsoftware`) "
41                        "REFERENCES `softwares` (`idsoftware`) ON DELETE CASCADE",
42        [5]     =       "ALTER TABLE `perfilessoft_softwares` "
43                        "ADD CONSTRAINT FK_perfilessoft "
44                        "FOREIGN KEY (`idperfilsoft`) "
45                        "REFERENCES `perfilessoft` (`idperfilsoft`) ON DELETE CASCADE",
46        [6]     =       "UPDATE version SET version = 2",
47};
48
[7d74d42]49struct og_server_cfg ogconfig;
50
51static int og_dbi_create_version(struct og_dbi *dbi)
52{
53        const char *msglog;
54        dbi_result result;
55
56        result = dbi_conn_queryf(dbi->conn, "CREATE TABLE `version` "
57                                            "(`version` smallint unsigned NOT NULL) "
58                                            "ENGINE='MyISAM' COLLATE 'utf8_general_ci'");
59        if (!result) {
60                dbi_conn_error(dbi->conn, &msglog);
61                syslog(LOG_INFO, "Could not create schema version table (%s:%d) %s\n",
62                       __func__, __LINE__, msglog);
63                return -1;
64        }
65        dbi_result_free(result);
66
67        result = dbi_conn_queryf(dbi->conn, "INSERT INTO `version` (`version`) VALUES ('0')");
68        if (!result) {
69                dbi_conn_error(dbi->conn, &msglog);
70                syslog(LOG_INFO, "Could not insert into schema version table (%s:%d) %s\n",
71                       __func__, __LINE__, msglog);
72                return -1;
73        }
74        dbi_result_free(result);
75
76        return 0;
77}
78static int og_dbi_schema_version(struct og_dbi *dbi)
79{
80        const char *msglog;
81        dbi_result result;
82        uint32_t version;
83
84        result = dbi_conn_queryf(dbi->conn, "SELECT * from version");
85        if (!result) {
86                dbi_conn_error(dbi->conn, &msglog);
87                syslog(LOG_INFO, "no version table found (%s:%d) %s\n",
88                       __func__, __LINE__, msglog);
89                return -1;
90        }
91
92        if (!dbi_result_last_row(result)) {
93                dbi_conn_error(dbi->conn, &msglog);
94                syslog(LOG_ERR, "cannot get last row from version table (%s:%d) %s\n",
95                       __func__, __LINE__, msglog);
96                return -1;
97        }
98
99        version = dbi_result_get_uint(result, "version");
100
101        dbi_result_free(result);
102
103        return version;
104}
[8775c06]105
[7d74d42]106static int og_dbi_schema_v1(struct og_dbi *dbi)
107{
108        const char *msglog, *command;
109        dbi_result result, result_alter;
110
111        result = dbi_conn_queryf(dbi->conn, "SELECT concat('alter table `',TABLE_SCHEMA,'`.`',TABLE_NAME,'` engine=innodb;')"
112                                            "AS cmd FROM information_schema.TABLES WHERE TABLE_SCHEMA='%s'",
113                                            ogconfig.db.name);
114
115        while (dbi_result_next_row(result)) {
116                command = dbi_result_get_string(result, "cmd");
117
118                syslog(LOG_DEBUG, "Upgrading to innoDB: %s\n", command);
119                result_alter = dbi_conn_query(dbi->conn, command);
120                if (!result_alter) {
121                        dbi_conn_error(dbi->conn, &msglog);
122                        syslog(LOG_INFO, "Error when upgrading engine to innoDB (%s:%d) %s\n",
123                               __func__, __LINE__, msglog);
124                        return -1;
125                }
126                dbi_result_free(result_alter);
127        }
128        dbi_result_free(result);
129
130        result = dbi_conn_query(dbi->conn, "UPDATE version SET version = 1");
131        if (!result) {
132                dbi_conn_error(dbi->conn, &msglog);
133                syslog(LOG_INFO, "Could not update version row (%s:%d) %s\n",
134                       __func__, __LINE__, msglog);
135                return -1;
136        }
137        dbi_result_free(result);
138
139        return 0;
140}
141
[8775c06]142static int og_dbi_schema_v2(struct og_dbi *dbi)
143{
144        const char *msglog;
145        dbi_result result;
146        int ret, i;
147
148        ret = dbi_conn_transaction_begin(dbi->conn);
149        if (ret) {
150                syslog(LOG_DEBUG, "could not begin a transaction (%s:%d)\n",
151                       __func__, __LINE__);
152                goto err_no_trans;
153        }
154
155        for (i = 0; i < OG_SCHEMA_STMTS_V2; i++) {
156                result = dbi_conn_query(dbi->conn, stmts_v2[i]);
157                if (!result) {
158                        dbi_conn_error(dbi->conn, &msglog);
159                        syslog(LOG_ERR, "Statement number %d failed (%s:%d): %s\n",
160                                        i, __func__, __LINE__, msglog);
161                        goto err_trans;
162                }
163                dbi_result_free(result);
164        }
165
166        ret = dbi_conn_transaction_commit(dbi->conn);
167        if (ret) {
168                syslog(LOG_DEBUG, "could not commit a transaction (%s:%d)\n",
169                       __func__, __LINE__);
170                goto err_trans;
171        }
172        return 0;
173
174err_trans:
175        dbi_conn_transaction_rollback(dbi->conn);
176err_no_trans:
177        return -1;
178}
179
[7d74d42]180static struct og_schema_version {
181        int     version;
182        int     (*update)(struct og_dbi *dbi);
183} schema_version[] = {
184        {       .version = 1,   .update = og_dbi_schema_v1      },
[8775c06]185        {       .version = 2,   .update = og_dbi_schema_v2      },
[7d74d42]186        {       0,              NULL                            },
187};
188
189int og_dbi_schema_update(void)
190{
191        int version, i, err;
192        struct og_dbi *dbi;
193        const char *msglog;
194
195        dbi = og_dbi_open(&ogconfig.db);
196        if (!dbi) {
197                dbi_conn_error(dbi->conn, &msglog);
198                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
199                       __func__, __LINE__, msglog);
200                return -1;
201        }
202
203        version = og_dbi_schema_version(dbi);
204
205        if (version < 0) {
206                syslog(LOG_INFO, "creating table version in schema\n");
207                og_dbi_create_version(dbi);
208        } else {
209                syslog(LOG_INFO, "database schema version %d\n", version);
210        }
211
212        for (i = 0; schema_version[i].version; i++) {
213                if (version >= schema_version[i].version)
214                        continue;
215
216                syslog(LOG_INFO, "upgrading to schema version %d\n", schema_version[i].version);
217
218                err = schema_version[i].update(dbi);
219                if (err < 0) {
220                        syslog(LOG_ERR, "failed to update schema!\n");
221                        og_dbi_close(dbi);
222                        return -1;
223                }
224        }
225
226        og_dbi_close(dbi);
227
228        return 0;
229}
Note: See TracBrowser for help on using the repository browser.