Commit 1adb1b605936750dcf160827cf1696874db973f0

Authored by David RENE
1 parent 1290c664

add support of sqlite3 in the migration tools

calexium_lib/database/db_utils.anubis
@@ -11,6 +11,7 @@ read tools/basis.anubis @@ -11,6 +11,7 @@ read tools/basis.anubis
11 read system/logger.anubis 11 read system/logger.anubis
12 read system/string.anubis 12 read system/string.anubis
13 read data_base/db_tools.anubis 13 read data_base/db_tools.anubis
  14 +read data_base/sqlite.anubis
14 15
15 read calexium_lib/net_services_protocols/logger_service.anubis 16 read calexium_lib/net_services_protocols/logger_service.anubis
16 17
@@ -89,29 +90,24 @@ public define DbQueryResult @@ -89,29 +90,24 @@ public define DbQueryResult
89 }. 90 }.
90 91
91 // deprecated. Use one of the previous ones. 92 // deprecated. Use one of the previous ones.
92 -public define Maybe(SQLite3HeadersOrRow -> DbRow) 93 +public define SQLite3QueryResult
93 sql_query_timeout 94 sql_query_timeout
94 ( 95 (
95 - Database db, //database handle 96 + SQLite3DataBase db, //database handle
96 String sql_query, //sql query itself 97 String sql_query, //sql query itself
  98 + List(SQLite3Bind) initial_bindings,
97 String msg //message to be shown if an error occure 99 String msg //message to be shown if an error occure
98 ) = 100 ) =
99 //we try with 30 sec of timeout 101 //we try with 30 sec of timeout
100 with t0 = unow, 102 with t0 = unow,
101 - if sql_query_timeout(db, sql_query, [], 60, 100, (DbError _) |-> false) is 103 + if sql_query_timeout(db, sql_query, initial_bindings, 60, 100) is
102 { 104 {
103 error(sql_error) then logError("DB", db_error(sql_error,msg)); 105 error(sql_error) then logError("DB", db_error(sql_error,msg));
104 __logLongQueries(t0, sql_query); 106 __logLongQueries(t0, sql_query);
105 - failure, 107 + error(sql_error),
106 ok(headers, cursor, reset) then 108 ok(headers, cursor, reset) then
107 __logLongQueries(t0, sql_query); 109 __logLongQueries(t0, sql_query);
108 - success((SQLite3HeadersOrRow h_or_r) |-> if h_or_r is  
109 - {  
110 - headers then  
111 - with cols = map((String c) |-> (DbDatum)db_text(c), headers(unique)),  
112 - row((Int n) |-> force(nth(n, cols), no_such_column)),  
113 - next_row then cursor(unique)  
114 - }) 110 + ok(headers, cursor, reset)
115 }. 111 }.
116 112
117 // -- Extractors HELPERS --------------- 113 // -- Extractors HELPERS ---------------
@@ -135,10 +131,10 @@ public define List(String) @@ -135,10 +131,10 @@ public define List(String)
135 public define List(String) 131 public define List(String)
136 db_get_string_list 132 db_get_string_list
137 ( 133 (
138 - SQLite3HeadersOrRow -> DbRow table_cursor,  
139 - List(String) so_far 134 + One -> SQLite3Row table_cursor,
  135 + List(String) so_far
140 ) = 136 ) =
141 - if table_cursor(next_row) is 137 + if table_cursor(unique) is
142 { 138 {
143 error(sql_error) then logError("DB", db_error(sql_error, "db_get_string_list")); reverse(so_far), 139 error(sql_error) then logError("DB", db_error(sql_error, "db_get_string_list")); reverse(so_far),
144 no_more_row then reverse(so_far), //can't find the symbol in the table, because the row is empty 140 no_more_row then reverse(so_far), //can't find the symbol in the table, because the row is empty
@@ -151,10 +147,10 @@ public define List(String) @@ -151,10 +147,10 @@ public define List(String)
151 public define List(Int) 147 public define List(Int)
152 db_get_integer_list 148 db_get_integer_list
153 ( 149 (
154 - SQLite3HeadersOrRow -> DbRow table_cursor,  
155 - List(Int) so_far 150 + One -> SQLite3Row table_cursor,
  151 + List(Int) so_far
156 ) = 152 ) =
157 - if table_cursor(next_row) is 153 + if table_cursor(unique) is
158 { 154 {
159 error(sql_error) then logError("DB", db_error(sql_error, "db_get_integer_list")); reverse(so_far), 155 error(sql_error) then logError("DB", db_error(sql_error, "db_get_integer_list")); reverse(so_far),
160 no_more_row then reverse(so_far), //can't find the symbol in the table, because the row is empty 156 no_more_row then reverse(so_far), //can't find the symbol in the table, because the row is empty
calexium_lib/database/migration_common_sqlite3.anubis 0 → 100644
  1 +/*
  2 + * Created by PyramIDE.
  3 + * User: ricard
  4 + * Date: 03/12/2008
  5 + * Time: 13:07
  6 + *
  7 + */
  8 +
  9 +read tools/basis.anubis
  10 +read system/logger.anubis
  11 +read data_base/sqlite.anubis
  12 +read data_base/alter_table.anubis //for sqlite3 version of alter_table
  13 +read data_base/db_types.anubis //FK...
  14 +read data_base/sqlite_foreign_key.anubis
  15 +
  16 +read calexium_lib/database/db_utils.anubis
  17 +read calexium_lib/net_services_protocols/logger_service.anubis
  18 +
  19 + read ezmailbox_constants.anubis
  20 +
  21 +
  22 +public type DbTable:
  23 + table(String name, String create_query),
  24 + table(String db_name, String name, String create_query),
  25 + view(String name, String create_query).
  26 +
  27 +
  28 +public define Bool
  29 + is_table_exists
  30 + (
  31 + SQLite3DataBase db,
  32 + String dbName,
  33 + String table_name
  34 + )=
  35 + if sql_query_timeout(db, "SELECT * FROM " + dbName + ".sqlite_master WHERE type ='table' AND tbl_name =:table_name", [bind_String(":table_name", table_name)], "is_table_exists("+table_name+")") is
  36 + {
  37 + error(_) then false, //error in the SQL request
  38 + ok(_, cursor, _) then
  39 + if cursor(unique) is
  40 + {
  41 + error(_) then false,
  42 + no_more_row then false,
  43 + row(current) then true
  44 + }
  45 + }.
  46 +
  47 +public define Bool
  48 + is_table_exists
  49 + (
  50 + SQLite3DataBase db,
  51 + String table_name
  52 + )=
  53 + is_table_exists(db, "main", table_name).
  54 +
  55 +public define Bool
  56 + is_empty_database
  57 + (
  58 + SQLite3DataBase db,
  59 + String dbName,
  60 + )=
  61 + if sql_query_timeout(db, "SELECT * FROM " + dbName + ".sqlite_master", [], "is_empty_database("+dbName+")") is
  62 + {
  63 + error(_) then true, //error in the SQL request
  64 + ok(_, cursor, _) then
  65 + if cursor(unique) is
  66 + {
  67 + error(_) then true,
  68 + no_more_row then true,
  69 + row(current) then false
  70 + }
  71 + }.
  72 +
  73 +public define Bool
  74 + is_empty_database
  75 + (
  76 + SQLite3DataBase db,
  77 + )=
  78 + is_empty_database(db, "main").
  79 +
  80 +public define Maybe(One)
  81 + drop_all_triggers
  82 + (
  83 + SQLite3DataBase db,
  84 + Logger log
  85 + ) =
  86 + if sqlite3_query(db, "SELECT name FROM sqlite_master WHERE type = 'trigger'", []) is
  87 + {
  88 + error(err) then logError(log, db_error(err, "drop_all_triggers")); failure,
  89 + ok(_, cursor, _) then
  90 + with drop_trigger = (String name) |-> if sqlite3_query(db, "DROP TRIGGER " + name, []) is
  91 + {
  92 + error(err2) then logError(log, db_error(err2, "Failed to drop trigger '" + name + "'")),
  93 + ok(_, cursor, _) then unique
  94 + },
  95 + map_forget(drop_trigger, db_get_string_list(cursor, []));
  96 + success(unique)
  97 + }.
  98 +
  99 +public define Maybe(One)
  100 + create_tables
  101 + (
  102 + SQLite3DataBase db,
  103 + Logger logger,
  104 + List(DbTable) tables,
  105 + String version_string
  106 + ) =
  107 + if tables is
  108 + {
  109 + [] then success(unique),
  110 + [h . t] then
  111 + if h is
  112 + {
  113 + table(table_name, create_string) then
  114 + if alter_table(db, table_name, create_string, logger) is
  115 + {
  116 + failure then logError(logger, "Version "+version_string+": Can't create '"+table_name+"' table"); failure,
  117 + success(_) then create_tables(db, logger, t, version_string)
  118 + },
  119 + table(db_name, table_name, create_string) then
  120 + if alter_table(db, db_name, table_name, create_string, logger) is
  121 + {
  122 + failure then logError(logger, "Version "+version_string+": Can't create '"+db_name+"."+table_name+"' table"); failure,
  123 + success(_) then create_tables(db, logger, t, version_string)
  124 + },
  125 + view(view_name, create_string) then
  126 + if alter_view(db, view_name, create_string, logger) is
  127 + {
  128 + failure then logError(logger, "Version "+version_string+": Can't create '"+view_name+"' view"); failure,
  129 + success(_) then create_tables(db, logger, t, version_string)
  130 + },
  131 + }
  132 + }.
  133 +
  134 +
  135 +public define Maybe(One)
  136 + create_indexes
  137 + (
  138 + SQLite3DataBase db,
  139 + Logger logger,
  140 + List(String) indexes,
  141 + String version_string
  142 + )=
  143 + if indexes is
  144 + {
  145 + [] then success(unique),
  146 + [h . t] then
  147 + if sql_query_timeout(db, h, [], "Version "+version_string+": create indexes") is
  148 + {
  149 + error(_) then failure,
  150 + ok(_,_,_) then create_indexes(db, logger, t, version_string)
  151 + }
  152 + }.
  153 +
  154 +
  155 +public define One
  156 + make_foreign_key
  157 + (
  158 + SQLite3DataBase db,
  159 + String table_name,
  160 + String field_name,
  161 + String foreign_table_name,
  162 + String foreign_field_name,
  163 + Bool fk_null,
  164 + Bool fk_cascade,
  165 + Logger log
  166 + ) =
  167 + if (Maybe(One))make_foreign_key(db, table_name, field_name, foreign_table_name, foreign_field_name, fk_null, fk_cascade, log) is
  168 + {
  169 + failure then
  170 + logError(log, "Can't create foreign key constraint between '"+table_name+"' and '"+foreign_table_name+"' tables"),
  171 + success(_) then
  172 + unique
  173 + }.
  174 +
  175 +public define Maybe(One)
  176 + make_foreign_keys
  177 + (
  178 + SQLite3DataBase db,
  179 + Logger logger,
  180 + List((String, String, String, String, FK_Null, FK_Cascade)) relations,
  181 + String version_string
  182 + )=
  183 + if relations is
  184 + {
  185 + [] then success(unique),
  186 + [h . t] then
  187 + if h is (table_name, field_name, foreign_table_name, foreign_field_name, fk_null, fk_cascade) then
  188 + if (Maybe(One))make_foreign_key(db, table_name, field_name, foreign_table_name, foreign_field_name, fk_null, fk_cascade, logger) is
  189 + {
  190 + failure then
  191 + logError(logger, "Version "+version_string+": Can't create foreign key constraint between '"+table_name+"' and '"+foreign_table_name+"' tables"); failure,
  192 + success(_) then
  193 + make_foreign_keys(db, logger, t, version_string)
  194 + }
  195 + }.
calexium_lib/database/migration_sqlite3.anubis 0 → 100644
  1 +/*
  2 + * Created by PyramIDE.
  3 + * User: David René
  4 + * Date: 31/08/2011
  5 + * Time: 2:09
  6 + *
  7 + */
  8 +
  9 +read tools/basis.anubis
  10 +read system/files.anubis
  11 +read system/logger.anubis
  12 +read system/string.anubis
  13 +read data_base/sqlite.anubis
  14 +read calexium_lib/database/alter_table.anubis
  15 +read calexium_lib/net_services_protocols/logger_service.anubis
  16 +
  17 +read migration_common_sqlite3.anubis
  18 +
  19 +
  20 +define String dir_save_database = "/db_backup/".
  21 +
  22 +
  23 +/**
  24 + * Compare two version string. Returns -1 if first is lower than second, 1 if first is greater than second, and 0 if equals.
  25 + */
  26 +public define Int
  27 + compare_db_version
  28 + (
  29 + String version1,
  30 + String version2
  31 + ) =
  32 + with compare = (List(String) v1, List(String) v2) |-compare-> (Int)
  33 + if v1 is
  34 + {
  35 + [] then
  36 + if v2 is
  37 + {
  38 + [] then 0,
  39 + [h2 . t2] then -1
  40 + },
  41 + [h1 . t1] then
  42 + if v2 is
  43 + {
  44 + [] then 1,
  45 + [h2 . t2] then
  46 + if h1 = h2 then compare(t1, t2)
  47 + else
  48 + with v1i = force_Type(decimal_scan(h1), 0),
  49 + v2i = force_Type(decimal_scan(h2), 0),
  50 + if v1i < v2i then -1
  51 + else if v1i > v2i then 1
  52 + else 0
  53 + },
  54 + },
  55 + compare(split(version1, '.'), split(version2, '.')).
  56 +
  57 +public define Maybe(One)
  58 + backup_database
  59 + (
  60 + Logger logger,
  61 +// String current_version,
  62 + String db_path,
  63 + String main_db_name,
  64 + List(String) other_db_names,
  65 + )
  66 + =
  67 +// with should_copy = if file_exists(db_path + main_db_name) then
  68 +// if sqlite3_open(db_path + main_db_name) is
  69 +// {
  70 +// error(sql_error) then false, // maybe not created yet
  71 +// ok(Database db) then
  72 +// with ver = get_version_settings(db),
  73 +// ver != current_version
  74 +// }
  75 +// else false,
  76 +
  77 + //if should_copy then
  78 + with dir_save = db_path + dir_save_database,
  79 + if (Maybe(String))make_directory(dir_save) is
  80 + {
  81 + failure then logError(logger, "Can't create directory '"+db_path + dir_save_database+"'"); failure,
  82 + success(_) then
  83 + with copy_with_log = (String src, String dst) |->
  84 + if file_exists(src) then
  85 + if copy_file(src, dst) is
  86 + {
  87 + cant_read_file then logError(logger, "Can't read source file '" + src + "'."); failure,
  88 + cant_create_file then logError(logger, "Can't create destination file '" + dst + "'."); failure,
  89 + copy_error then logError(logger, "Can't copy file '" + src + "' to file '" + dst + "'."); failure,
  90 + copy_file_mode_error then logError(logger, "Can't get file mode for source file '" + src + "'."); failure,
  91 + copy_file_times_error then logError(logger, "Can't set file times into file '" + dst + "'."); failure,
  92 + copy_ok(_) then logInfo(logger, "File '" + dst + "' saved"); success(unique)
  93 + }
  94 + else success(unique),
  95 + with copy_db = (List(String) names) |-copy_db->
  96 + if names is
  97 + {
  98 + [] then success(unique),
  99 + [h . t] then
  100 + if copy_with_log(db_path + h, dir_save + h) is
  101 + {
  102 + failure then failure,
  103 + success(_) then copy_db(t)
  104 + }
  105 + },
  106 + copy_db([main_db_name . other_db_names])
  107 + }
  108 + //else success(unique)
  109 + .
  110 +
  111 +
  112 +
  113 +
  114 +
  115 +
  116 +public type Migration:
  117 + migration(String version,
  118 + (SQLite3DataBase, Logger) -> Maybe(One) migrate_to,
  119 + (SQLite3DataBase, Logger) -> Maybe(One) create_tables,
  120 + (SQLite3DataBase, Logger) -> Maybe(One) create_indexes,
  121 + ).
  122 +
  123 +
  124 +
  125 +define Maybe(One)
  126 + do_migration_loop
  127 + (
  128 + SQLite3DataBase db,
  129 + Logger logger,
  130 + String current_version,
  131 + String db_ver,
  132 + List(Migration) migrations,
  133 + Maybe(Migration) need_to_create_table, // success in case of new DB or when no migration have been done
  134 + (SQLite3DataBase, String) -> One update_db_version,
  135 + ) =
  136 + if migrations is
  137 + {
  138 + [] then
  139 + if need_to_create_table is
  140 + {
  141 + failure then
  142 + update_db_version(db, current_version);
  143 + success(unique),
  144 + success(last) then
  145 + if last is migration(_, _, create_tables, create_indexes) then
  146 + if create_tables(db, logger) is success(_) then
  147 + if create_indexes(db, logger) is success(_) then
  148 + update_db_version(db, current_version);
  149 + success(unique)
  150 + else
  151 + failure
  152 + else
  153 + failure
  154 + },
  155 + [h . t] then
  156 + if h is migration(version, migrate_to, _, _) then
  157 + if compare_db_version(db_ver, version) < 0 then
  158 + logInfo(logger, "Migrating Database from version " + db_ver + " to version " + version);
  159 + if migrate_to(db, logger) is failure then
  160 + failure
  161 + else
  162 + do_migration_loop(db, logger, current_version, version, t, failure, update_db_version)
  163 + else
  164 + do_migration_loop(db, logger, current_version, db_ver, t, success(h), update_db_version),
  165 + }.
  166 +
  167 +/* SQLite 3 version */
  168 +public define Maybe(One)
  169 + do_migration
  170 + (
  171 + SQLite3DataBase db,
  172 + Logger logger,
  173 + String current_version,
  174 + (SQLite3DataBase) -> String get_db_version,
  175 + (SQLite3DataBase, String) -> One update_db_version,
  176 + List(Migration) all_migrations,
  177 + )=
  178 + if is_empty_database(db) then // new empty database
  179 + logInfo(logger, "No database found. Creating a new one...");
  180 + do_migration_loop(db, logger, current_version, "", [], last(all_migrations), update_db_version)
  181 + else
  182 + (
  183 + with db_version = get_db_version(db),
  184 + do_migration_loop(db, logger, current_version, db_version, all_migrations, failure, update_db_version)
  185 + ).
  186 +
  187 +public define Maybe(One)
  188 + do_create_indexes
  189 + (
  190 + SQLite3DataBase db,
  191 + Logger logger,
  192 + String current_version,
  193 + List(Migration) all_migrations,
  194 + )=
  195 + if last(all_migrations) is
  196 + {
  197 + failure then logCriticalError(logger, "Index creation: migration list is empty!"); failure,
  198 + success(last_migration) then
  199 + if last_migration is migration(_, _, _, create_indexes) then
  200 + if create_indexes(db, logger) is success(_) then
  201 + success(unique)
  202 + else
  203 + failure
  204 + }.
calexium_lib/database/sqlite_foreign_key.anubis
@@ -17,6 +17,7 @@ read tools/basis.anubis @@ -17,6 +17,7 @@ read tools/basis.anubis
17 read data_base/sqlite.anubis 17 read data_base/sqlite.anubis
18 read data_base/db_tools.anubis 18 read data_base/db_tools.anubis
19 read system/logger.anubis 19 read system/logger.anubis
  20 +read data_base/db_types.anubis
20 21
21 22
22 23
@@ -64,13 +65,6 @@ public define Maybe(One) @@ -64,13 +65,6 @@ public define Maybe(One)
64 }. 65 }.
65 66
66 67
67 -public type FK_Null:  
68 - null,  
69 - not_null.  
70 -  
71 -public type FK_Cascade:  
72 - delete_in_cascade,  
73 - block_if_children.  
74 68
75 public define Maybe(One) 69 public define Maybe(One)
76 make_foreign_key 70 make_foreign_key