Commit 68665c4a1c27de340617c156304a783a61bdb9bb

Authored by Cédric RICARD
1 parent 8a2b97fb

Improved DB migration library

calexium_lib/database/migration.anubis
... ... @@ -29,8 +29,8 @@ define String dir_save_database = "/db_backup/".
29 29 /**
30 30 * Compare two version string. Returns -1 if first is lower than second, 1 if first is greater than second, and 0 if equals.
31 31 */
32   -define Int
33   - compare_version
  32 +public define Int
  33 + compare_db_version
34 34 (
35 35 String version1,
36 36 String version2
... ... @@ -51,10 +51,10 @@ define Int
51 51 [h2 . t2] then
52 52 if h1 = h2 then compare(t1, t2)
53 53 else
54   - with v1 = force_Type(decimal_scan(h1), 0),
55   - v2 = force_Type(decimal_scan(h2), 0),
56   - if v1 < v2 then -1
57   - else if v1 > v2 then 1
  54 + with v1i = force_Type(decimal_scan(h1), 0),
  55 + v2i = force_Type(decimal_scan(h2), 0),
  56 + if v1i < v2i then -1
  57 + else if v1i > v2i then 1
58 58 else 0
59 59 },
60 60 },
... ... @@ -148,63 +148,78 @@ public type Migration:
148 148 define Maybe(One)
149 149 do_migration_loop
150 150 (
151   - SQLite3DataBase db,
152   - Logger logger,
153   - String current_version,
154   - String db_ver,
155   - List(Migration) migrations,
156   - Migration last,
157   - Bool need_to_create_table,
158   - )=
  151 + SQLite3DataBase db,
  152 + Logger logger,
  153 + String current_version,
  154 + String db_ver,
  155 + List(Migration) migrations,
  156 + Maybe(Migration) need_to_create_table // success in case of new DB or when no migration have been done
  157 + ) =
159 158 if migrations is
160 159 {
161 160 [] then
162   - if need_to_create_table then
163   - (
164   -// if reverse(all_migrations) is
165   -// {
166   -// [] then success(unique),
167   -// [last . _] then
168   - if last is migration(_, _, create_tables, create_indexes) then
169   - if create_tables(db, logger) is success(_) then
170   - if create_indexes(db, logger) is success(_) then
171   - update_version_settings(db, current_version);
172   - success(unique)
173   - else
174   - failure
  161 + if need_to_create_table is
  162 + {
  163 + failure then
  164 + update_version_settings(db, current_version);
  165 + success(unique),
  166 + success(last) then
  167 + if last is migration(_, _, create_tables, create_indexes) then
  168 + if create_tables(db, logger) is success(_) then
  169 + if create_indexes(db, logger) is success(_) then
  170 + update_version_settings(db, current_version);
  171 + success(unique)
175 172 else
176 173 failure
177   -// }
178   - )
179   - else
180   - update_version_settings(db, current_version);
181   - success(unique),
  174 + else
  175 + failure
  176 + },
182 177 [h . t] then
183 178 if h is migration(version, migrate_to, _, _) then
184   - if compare_version(db_ver, version) < 0 then
  179 + if compare_db_version(db_ver, version) < 0 then
185 180 logInfo(logger, "Migrating Database from version " + db_ver + " to version " + version);
186 181 if migrate_to(db, logger) is failure then
187 182 failure
188 183 else
189   - do_migration_loop(db, logger, current_version, version, t, h, false)
  184 + do_migration_loop(db, logger, current_version, version, t, failure)
190 185 else
191   - do_migration_loop(db, logger, current_version, db_ver, t, h, need_to_create_table),
  186 + do_migration_loop(db, logger, current_version, db_ver, t, success(h)),
192 187 }.
193 188  
194 189  
  190 +
195 191 public define Maybe(One)
196 192 do_migration
197 193 (
198 194 SQLite3DataBase db,
199 195 Logger logger,
200 196 String current_version,
201   - NonEmptyList(Migration) all_migrations,
  197 + List(Migration) all_migrations,
202 198 )=
203   - if is_table_exists(db, "mails") then // new empty database
  199 + if is_empty_database(db) then // new empty database
  200 + logInfo(logger, "No database found. Creating a new one...");
  201 + do_migration_loop(db, logger, current_version, "", [], last(all_migrations))
  202 + else
204 203 (
205 204 with db_version = get_version_settings(db),
206   - if all_migrations is [h . t] then
207   - do_migration_loop(db, logger, current_version, db_version, [h . t], h, true)
208   - )
209   - else
210   - do_migration_loop(db, logger, current_version, "", [], all_migrations.head, true).
  205 + do_migration_loop(db, logger, current_version, db_version, all_migrations, failure)
  206 + ).
  207 +
  208 +public define Maybe(One)
  209 + do_create_indexes
  210 + (
  211 + SQLite3DataBase db,
  212 + Logger logger,
  213 + String current_version,
  214 + List(Migration) all_migrations,
  215 + )=
  216 + if last(all_migrations) is
  217 + {
  218 + failure then logCriticalError(logger, "Index creation: migration list is empty!"); failure,
  219 + success(last_migration) then
  220 + if last_migration is migration(_, _, _, create_indexes) then
  221 + if create_indexes(db, logger) is success(_) then
  222 + success(unique)
  223 + else
  224 + failure
  225 + }.
... ...
calexium_lib/database/migration_common.anubis
... ... @@ -18,6 +18,11 @@ read calexium_lib/net_services_protocols/logger_service.anubis
18 18 read ezmailbox_constants.anubis
19 19  
20 20  
  21 +public type DbTable:
  22 + table(String name, String create_query),
  23 + table(String db_name, String name, String create_query).
  24 +
  25 +
21 26 public define Bool
22 27 is_table_exists
23 28 (
... ... @@ -45,6 +50,31 @@ public define Bool
45 50 )=
46 51 is_table_exists(db, "main", table_name).
47 52  
  53 +public define Bool
  54 + is_empty_database
  55 + (
  56 + SQLite3DataBase db,
  57 + String dbName,
  58 + )=
  59 + if sql_query_timeout(db, "SELECT * FROM " + dbName + ".sqlite_master", [], "is_empty_database("+dbName+")") is
  60 + {
  61 + error(_) then true, //error in the SQL request
  62 + ok(_, cursor, _) then
  63 + if cursor(unique) is
  64 + {
  65 + error(_) then true,
  66 + no_more_row then true,
  67 + row(current) then false
  68 + }
  69 + }.
  70 +
  71 +public define Bool
  72 + is_empty_database
  73 + (
  74 + SQLite3DataBase db,
  75 + )=
  76 + is_empty_database(db, "main").
  77 +
48 78 public define Maybe(One)
49 79 drop_all_triggers
50 80 (
... ... @@ -69,18 +99,27 @@ public define Maybe(One)
69 99 (
70 100 SQLite3DataBase db,
71 101 Logger logger,
72   - List((String,String)) tables,
  102 + List(DbTable) tables,
73 103 String version_string
74 104 ) =
75 105 if tables is
76 106 {
77 107 [] then success(unique),
78 108 [h . t] then
79   - if h is (table_name, create_string) then
80   - if alter_table(db, table_name, create_string, logger) is
  109 + if h is
81 110 {
82   - failure then logError(logger, "Version "+version_string+": Can't create '"+table_name+"' table"); failure,
83   - success(_) then create_tables(db, logger, t, version_string)
  111 + table(table_name, create_string) then
  112 + if alter_table(db, table_name, create_string, logger) is
  113 + {
  114 + failure then logError(logger, "Version "+version_string+": Can't create '"+table_name+"' table"); failure,
  115 + success(_) then create_tables(db, logger, t, version_string)
  116 + },
  117 + table(db_name, table_name, create_string) then
  118 + if alter_table(db, db_name, table_name, create_string, logger) is
  119 + {
  120 + failure then logError(logger, "Version "+version_string+": Can't create '"+db_name+"."+table_name+"' table"); failure,
  121 + success(_) then create_tables(db, logger, t, version_string)
  122 + }
84 123 }
85 124 }.
86 125  
... ...
calexium_lib/database/settings.anubis
... ... @@ -60,7 +60,24 @@ public define Int
60 60 }
61 61 }.
62 62  
63   -
  63 +public define Bool
  64 + select_settings
  65 + (
  66 + SQLite3DataBase db,
  67 + String var,
  68 + Bool default
  69 + )=
  70 + if select_settings(db, var) is
  71 + {
  72 + failure then default, //error in the SQL request
  73 + success(value) then
  74 + if decimal_scan(value) is
  75 + {
  76 + failure then default,
  77 + success(v) then v!=0
  78 + }
  79 + }.
  80 +
64 81 public define One
65 82 update_settings
66 83 (
... ...