From 3b642ef214cf59ea5a8bf0002988e034305e72e9 Mon Sep 17 00:00:00 2001 From: Cedric RICARD Date: Fri, 8 May 2009 08:15:32 +0000 Subject: [PATCH] Moving database migration from NL to CXMLib --- calexium_lib/database/migration.anubis | 210 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ calexium_lib/database/migration_common.anubis | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ calexium_lib/database/settings.anubis | 76 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ calexium_lib/web/CXM_dojo.anubis | 8 +------- 4 files changed, 436 insertions(+), 7 deletions(-) create mode 100644 calexium_lib/database/migration.anubis create mode 100644 calexium_lib/database/migration_common.anubis create mode 100644 calexium_lib/database/settings.anubis diff --git a/calexium_lib/database/migration.anubis b/calexium_lib/database/migration.anubis new file mode 100644 index 0000000..01075a2 --- /dev/null +++ b/calexium_lib/database/migration.anubis @@ -0,0 +1,210 @@ +/* + * Created by PyramIDE. + * User: Steve Marechal + * Date: 25/11/2008 + * Time: 11:29 + * + */ + +read tools/basis.anubis +read system/files.anubis +read system/logger.anubis +read system/string.anubis +read data_base/alter_table.anubis +read data_base/sqlite.anubis + +read calexium_lib/database/db_utils.anubis +read calexium_lib/net_services_protocols/logger_service.anubis + + read mf_constants.anubis + +read settings.anubis +read migration_common.anubis + + read tools/mf_loggers.anubis + +define String dir_save_database = "/db_backup/". + + +/** + * Compare two version string. Returns -1 if first is lower than second, 1 if first is greater than second, and 0 if equals. + */ +define Int + compare_version + ( + String version1, + String version2 + ) = + with compare = (List(String) v1, List(String) v2) |-compare-> (Int) + if v1 is + { + [] then + if v2 is + { + [] then 0, + [h2 . t2] then -1 + }, + [h1 . t1] then + if v2 is + { + [] then 1, + [h2 . t2] then + if h1 = h2 then compare(t1, t2) + else + with v1 = force_Type(decimal_scan(h1), 0), + v2 = force_Type(decimal_scan(h2), 0), + if v1 < v2 then -1 + else if v1 > v2 then 1 + else 0 + }, + }, + compare(split(version1, '.'), split(version2, '.')). + +define String + get_version_settings + ( + SQLite3DataBase db + )= + if is_table_exists(db, "settings") then + select_settings(db, "MF_version", "0.0.0.0") + else "0.0.0.0". + +public define One + update_version_settings + ( + SQLite3DataBase db, + String version + )= + update_settings(db, "MF_version", version). + +public define Maybe(One) + backup_database + ( + Logger logger, + String current_version, + String db_path, + String main_db_name, + List(String) other_db_names, + ) + = + with should_copy = if file_exists(db_path + main_db_name) then + if sqlite3_open(db_path + main_db_name) is + { + error(sql_error) then false, // maybe not created yet + ok(SQLite3DataBase db) then + with ver = get_version_settings(db), + ver != current_version + } + else false, + + if should_copy then + with dir_save = db_path + dir_save_database, + if (Maybe(String))make_directory(dir_save) is + { + failure then logError(logger, "Can't create directory '"+db_path + dir_save_database+"'"); failure, + success(_) then + with copy_with_log = (String src, String dst) |-> + if file_exists(src) then + if copy_file(src, dst) is + { + cant_read_file then logError(logger, "Can't read source file '" + src + "'."); failure, + cant_create_file then logError(logger, "Can't create destination file '" + dst + "'."); failure, + copy_error then logError(logger, "Can't copy file '" + src + "' to file '" + dst + "'."); failure, + copy_file_mode_error then logError(logger, "Can't get file mode for source file '" + src + "'."); failure, + copy_file_times_error then logError(logger, "Can't set file times into file '" + dst + "'."); failure, + copy_ok(_) then logInfo(logger, "File '" + dst + "' saved"); success(unique) + } + else success(unique), + with copy_db = (List(String) names) |-copy_db-> + if names is + { + [] then success(unique), + [h . t] then + if copy_with_log(db_path + h, dir_save + h) is + { + failure then failure, + success(_) then copy_db(t) + } + }, + copy_db([main_db_name . other_db_names]) + } + else success(unique) + . + + + + + + +public type Migration: + migration(String version, + (SQLite3DataBase, Logger) -> Maybe(One) migrate_to, + (SQLite3DataBase, Logger) -> Maybe(One) create_tables, + (SQLite3DataBase, Logger) -> Maybe(One) create_indexes, + ). + + + +define Maybe(One) + do_migration_loop + ( + SQLite3DataBase db, + Logger logger, + String current_version, + String db_ver, + List(Migration) migrations, + Migration last, + Bool need_to_create_table, + )= + if migrations is + { + [] then + if need_to_create_table then + ( +// if reverse(all_migrations) is +// { +// [] then success(unique), +// [last . _] then + if last is migration(_, _, create_tables, create_indexes) then + if create_tables(db, logger) is success(_) then + if create_indexes(db, logger) is success(_) then + update_version_settings(db, current_version); + success(unique) + else + failure + else + failure +// } + ) + else + update_version_settings(db, current_version); + success(unique), + [h . t] then + if h is migration(version, migrate_to, _, _) then + if compare_version(db_ver, version) < 0 then + logInfo(logger, "Migrating Database from version " + db_ver + " to version " + version); + if migrate_to(db, logger) is failure then + failure + else + do_migration_loop(db, logger, current_version, version, t, h, false) + else + do_migration_loop(db, logger, current_version, db_ver, t, h, need_to_create_table), + }. + + +public define Maybe(One) + do_migration + ( + SQLite3DataBase db, + Logger logger, + String current_version, + NonEmptyList(Migration) all_migrations, + )= + if is_table_exists(db, "mails") then // new empty database + ( + with db_version = get_version_settings(db), + if all_migrations is [h . t] then + do_migration_loop(db, logger, current_version, db_version, [h . t], h, true) + ) + else + do_migration_loop(db, logger, current_version, "", [], all_migrations.head, true). diff --git a/calexium_lib/database/migration_common.anubis b/calexium_lib/database/migration_common.anubis new file mode 100644 index 0000000..3575b8b --- /dev/null +++ b/calexium_lib/database/migration_common.anubis @@ -0,0 +1,149 @@ +/* + * Created by PyramIDE. + * User: ricard + * Date: 03/12/2008 + * Time: 13:07 + * + */ + +read tools/basis.anubis +read system/logger.anubis +read data_base/sqlite.anubis +read data_base/alter_table.anubis +read data_base/sqlite_foreign_key.anubis + +read calexium_lib/database/db_utils.anubis +read calexium_lib/net_services_protocols/logger_service.anubis + + read ezmailbox_constants.anubis + + +public define Bool + is_table_exists + ( + SQLite3DataBase db, + String dbName, + String table_name + )= + if sql_query_timeout(db, "SELECT * FROM " + dbName + ".sqlite_master WHERE type ='table' AND name = @table_name", [bind_String("@table_name", table_name)], "is_table_exists("+table_name+")") is + { + error(_) then false, //error in the SQL request + ok(_, cursor, _) then + if cursor(unique) is + { + error(_) then false, + no_more_row then false, + row(current) then true + } + }. + +public define Bool + is_table_exists + ( + SQLite3DataBase db, + String table_name + )= + is_table_exists(db, "main", table_name). + +public define Maybe(One) + drop_all_triggers + ( + SQLite3DataBase db, + Logger log + ) = + if sqlite3_query(db, "SELECT name FROM sqlite_master WHERE type = 'trigger'", []) is + { + error(err) then logError(log, db_error(err, "drop_all_triggers")); failure, + ok(_, cursor, _) then + with drop_trigger = (String name) |-> if sqlite3_query(db, "DROP TRIGGER " + name, []) is + { + error(err2) then logError(log, db_error(err2, "Failed to drop trigger '" + name + "'")), + ok(_, cursor, _) then unique + }, + map_forget(drop_trigger, db_get_string_list(cursor, [])); + success(unique) + }. + +public define Maybe(One) + create_tables + ( + SQLite3DataBase db, + Logger logger, + List((String,String)) tables, + String version_string + ) = + if tables is + { + [] then success(unique), + [h . t] then + if h is (table_name, create_string) then + if alter_table(db, table_name, create_string, logger) is + { + failure then logError(logger, "Version "+version_string+": Can't create '"+table_name+"' table"); failure, + success(_) then create_tables(db, logger, t, version_string) + } + }. + + +public define Maybe(One) + create_indexes + ( + SQLite3DataBase db, + Logger logger, + List(String) indexes, + String version_string + )= + if indexes is + { + [] then success(unique), + [h . t] then + if sql_query_timeout(db, h, "Version "+version_string+": create indexes") is + { + failure then failure, + success(_) then + create_indexes(db, logger, t, version_string) + } + }. + + +public define One + make_foreign_key + ( + SQLite3DataBase db, + String table_name, + String field_name, + String foreign_table_name, + String foreign_field_name, + Bool fk_null, + Bool fk_cascade, + Logger log + ) = + if (Maybe(One))make_foreign_key(db, table_name, field_name, foreign_table_name, foreign_field_name, fk_null, fk_cascade, log) is + { + failure then + logError(log, "Can't create foreign key constraint between '"+table_name+"' and '"+foreign_table_name+"' tables"), + success(_) then + unique + }. + +public define Maybe(One) + make_foreign_keys + ( + SQLite3DataBase db, + Logger logger, + List((String, String, String, String, FK_Null, FK_Cascade)) relations, + String version_string + )= + if relations is + { + [] then success(unique), + [h . t] then + if h is (table_name, field_name, foreign_table_name, foreign_field_name, fk_null, fk_cascade) then + if (Maybe(One))make_foreign_key(db, table_name, field_name, foreign_table_name, foreign_field_name, fk_null, fk_cascade, logger) is + { + failure then + logError(logger, "Version "+version_string+": Can't create foreign key constraint between '"+table_name+"' and '"+foreign_table_name+"' tables"); failure, + success(_) then + make_foreign_keys(db, logger, t, version_string) + } + }. diff --git a/calexium_lib/database/settings.anubis b/calexium_lib/database/settings.anubis new file mode 100644 index 0000000..13a83e9 --- /dev/null +++ b/calexium_lib/database/settings.anubis @@ -0,0 +1,76 @@ +/* + * Created by PyramIDE. + * User: Steve Marechal + * Date: 09/12/2008 + * Time: 17:19 + */ + +read tools/basis.anubis +read data_base/sqlite.anubis + +read calexium_lib/database/db_utils.anubis + + +public define Maybe(String) + select_settings + ( + SQLite3DataBase db, + String var, + )= + if sql_query_timeout(db, "SELECT var_value FROM settings WHERE var_name=" + db_make_sql_string(var) + ";", "select_settings") is + { + failure then failure, //error in the SQL request + success(table_cursor) then + if table_cursor(next_row) is + { + error(_) then failure, + no_more_row then failure, //can't find the var_value in the table, because the row is empty + row(current) then success(text(current)(0)) + } + }. + +public define String + select_settings + ( + SQLite3DataBase db, + String var, + String default + )= + if select_settings(db, var) is + { + failure then default, //error in the SQL request + success(value) then value + }. + +public define Int + select_settings + ( + SQLite3DataBase db, + String var, + Int default + )= + if select_settings(db, var) is + { + failure then default, //error in the SQL request + success(value) then + if decimal_scan(value) is + { + failure then default, + success(v) then v + } + }. + + +public define One + update_settings + ( + SQLite3DataBase db, + String var, + String value + )= + if select_settings(db, var) is success(_) then + forget(sql_query_timeout(db, "UPDATE settings SET var_value = @value WHERE var_name = @name;", [bind_String("@name", var), bind_String("@value", value)], "update_settings")) + else + forget(sql_query_timeout(db, "INSERT INTO settings (var_name, var_value) VALUES (@name, @value)", [bind_String("@name", var), bind_String("@value", value)], "update_settings")) + . + diff --git a/calexium_lib/web/CXM_dojo.anubis b/calexium_lib/web/CXM_dojo.anubis index c79979e..d47e6ad 100644 --- a/calexium_lib/web/CXM_dojo.anubis +++ b/calexium_lib/web/CXM_dojo.anubis @@ -10,19 +10,13 @@ read tools/basis.anubis read tools/base64.anubis read locale/L3LanguageInfo.anubis read system/string.anubis +read system/logger.anubis read calexium_lib/web/CXM_common.anubis read calexium_lib/web/CXM_making_a_web_site.anubis read calexium_lib/web/CXM_multihost_http_server.anubis read calexium_lib/net_services_protocols/logger_service.anubis -read mailfountain_constants.anubis -read mailfountain_types.anubis -read common/language_management.anubis - -read tools/mf_loggers.anubis -read system/logger.anubis - public type Dojo_Grid_Data : grid_data(String). -- libgit2 0.21.4