Commit 0fc61cbc939d9a98b06de068b854717367c5d0d9
1 parent
006acf6b
introduce version type and db_version and their helper function for managing
change migration according to that type
Showing
7 changed files
with
574 additions
and
373 deletions
Show diff stats
database/db_types.anubis
| @@ -22,19 +22,6 @@ transmit calexium_lib/database/types/db_integer.anubis | @@ -22,19 +22,6 @@ transmit calexium_lib/database/types/db_integer.anubis | ||
| 22 | public type DB_ID: | 22 | public type DB_ID: |
| 23 | none, | 23 | none, |
| 24 | pk(Int value). | 24 | pk(Int value). |
| 25 | - | ||
| 26 | -//public type DB_datetime: | ||
| 27 | -// db_datetime(String datetime). //Date and time in ISO8601 format "YYYY-MM-DD hh:mm:ss" | ||
| 28 | - | ||
| 29 | -//public type DB_date: | ||
| 30 | -// db_date(String date). //Date in ISO8601 format "YYYY-MM-DD" | ||
| 31 | -// | ||
| 32 | -//public type DB_time: | ||
| 33 | -// db_time(String time). //Time in ISO8601 format "hh:mm:ss" | ||
| 34 | -// | ||
| 35 | -//public type DB_integer: | ||
| 36 | -// db_integer(Int value). | ||
| 37 | - | ||
| 38 | 25 | ||
| 39 | public define String | 26 | public define String |
| 40 | to_String | 27 | to_String |
| 1 | +/* | ||
| 2 | + * Created by PyramIDE. | ||
| 3 | + * User: フランスのトトロ aka (David RENÉ) | ||
| 4 | + * Date: 09/07/2017 | ||
| 5 | + * Time: 00:52 | ||
| 6 | + * © Calexium | ||
| 7 | + */ | ||
| 8 | + | ||
| 9 | +transmit tools/basis.anubis | ||
| 10 | +transmit calexium_lib/types/version.anubis | ||
| 11 | + | ||
| 12 | +public type DB_Version_Compare_Result: | ||
| 13 | + less, | ||
| 14 | + more, | ||
| 15 | + equal, | ||
| 16 | + equal_but_sign | ||
| 17 | +. | ||
| 18 | + | ||
| 19 | +public type DB_Version: | ||
| 20 | + db_version ( | ||
| 21 | + Version version, //version of database | ||
| 22 | + String db_hash //signature like SHA1 etc | ||
| 23 | + ) | ||
| 24 | +. | ||
| 25 | + | ||
| 26 | +public define DB_Version | ||
| 27 | + db_v_0 = | ||
| 28 | + db_version(version(0), "") | ||
| 29 | +. | ||
| 30 | + | ||
| 31 | +public define String | ||
| 32 | + String s + DB_Version db_v = | ||
| 33 | + s + db_v.version + " " + db_v.db_hash | ||
| 34 | +. | ||
| 35 | + | ||
| 36 | + | ||
| 37 | +public define String | ||
| 38 | + DB_Version db_v + String s = | ||
| 39 | + db_v.version + " " + db_v.db_hash + s | ||
| 40 | +. | ||
| 41 | + | ||
| 42 | + | ||
| 43 | +public define DB_Version_Compare_Result | ||
| 44 | + compare_db_version | ||
| 45 | + ( | ||
| 46 | + DB_Version v_x, | ||
| 47 | + DB_Version v_y | ||
| 48 | + ) = | ||
| 49 | + if v_x.version.numeric +< v_y.version.numeric then | ||
| 50 | + more | ||
| 51 | + else if v_x.version.numeric = v_x.version.numeric then | ||
| 52 | + if v_x.db_hash = v_y.db_hash then | ||
| 53 | + equal | ||
| 54 | + else | ||
| 55 | + equal_but_sign | ||
| 56 | + else | ||
| 57 | + less | ||
| 58 | +. | ||
| 59 | + | ||
| 60 | +public define Bool | ||
| 61 | + db_version_less | ||
| 62 | + ( | ||
| 63 | + DB_Version v_x, | ||
| 64 | + DB_Version v_y | ||
| 65 | + )= | ||
| 66 | + // +=< below is unsigned comparison for Word32 | ||
| 67 | + if v_x.version.numeric +=< v_y.version.numeric then true else false | ||
| 68 | +. |
database/migration_common_sqlite3.anubis
| 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 | -public type DbTable: | ||
| 20 | - table(String name, String create_query), | ||
| 21 | - table(String db_name, String name, String create_query), | ||
| 22 | - view(String name, String create_query). | ||
| 23 | - | ||
| 24 | - | ||
| 25 | -public define Bool | ||
| 26 | - is_table_exists | ||
| 27 | - ( | ||
| 28 | - SQLite3DataBase db, | ||
| 29 | - String dbName, | ||
| 30 | - String table_name | ||
| 31 | - )= | ||
| 32 | - 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 | ||
| 33 | - { | ||
| 34 | - error(_) then false, //error in the SQL request | ||
| 35 | - ok(_, cursor, _) then | ||
| 36 | - if cursor(unique) is | ||
| 37 | - { | ||
| 38 | - error(_) then false, | ||
| 39 | - no_more_row then false, | ||
| 40 | - row(current) then true | ||
| 41 | - } | ||
| 42 | - }. | ||
| 43 | - | ||
| 44 | -public define Bool | ||
| 45 | - is_table_exists | ||
| 46 | - ( | ||
| 47 | - SQLite3DataBase db, | ||
| 48 | - String table_name | ||
| 49 | - )= | ||
| 50 | - is_table_exists(db, "main", table_name). | ||
| 51 | - | ||
| 52 | -public define Bool | ||
| 53 | - is_empty_database | ||
| 54 | - ( | ||
| 55 | - SQLite3DataBase db, | ||
| 56 | - String dbName, | ||
| 57 | - )= | ||
| 58 | - if sql_query_timeout(db, "SELECT * FROM " + dbName + ".sqlite_master", [], "is_empty_database("+dbName+")") is | ||
| 59 | - { | ||
| 60 | - error(_) then true, //error in the SQL request | ||
| 61 | - ok(_, cursor, _) then | ||
| 62 | - if cursor(unique) is | ||
| 63 | - { | ||
| 64 | - error(_) then true, | ||
| 65 | - no_more_row then true, | ||
| 66 | - row(current) then false | ||
| 67 | - } | ||
| 68 | - }. | ||
| 69 | - | ||
| 70 | -public define Bool | ||
| 71 | - is_empty_database | ||
| 72 | - ( | ||
| 73 | - SQLite3DataBase db, | ||
| 74 | - )= | ||
| 75 | - is_empty_database(db, "main"). | ||
| 76 | - | ||
| 77 | -public define Maybe(One) | ||
| 78 | - drop_all_triggers | ||
| 79 | - ( | ||
| 80 | - SQLite3DataBase db, | ||
| 81 | - Logger log | ||
| 82 | - ) = | ||
| 83 | - if sqlite3_query(db, "SELECT name FROM sqlite_master WHERE type = 'trigger'", []) is | ||
| 84 | - { | ||
| 85 | - error(err) then logError(log, db_error(err, "drop_all_triggers")); failure, | ||
| 86 | - ok(_, cursor, _) then | ||
| 87 | - with drop_trigger = (String name) |-> if sqlite3_query(db, "DROP TRIGGER " + name, []) is | ||
| 88 | - { | ||
| 89 | - error(err2) then logError(log, db_error(err2, "Failed to drop trigger '" + name + "'")), | ||
| 90 | - ok(_, cursor, _) then unique | ||
| 91 | - }, | ||
| 92 | - map_forget(drop_trigger, db_get_string_list(cursor, [])); | ||
| 93 | - success(unique) | ||
| 94 | - }. | ||
| 95 | - | ||
| 96 | -public define Maybe(One) | ||
| 97 | - create_tables | ||
| 98 | - ( | ||
| 99 | - SQLite3DataBase db, | ||
| 100 | - Logger logger, | ||
| 101 | - List(DbTable) tables, | ||
| 102 | - String version_string | ||
| 103 | - ) = | ||
| 104 | - if tables is | ||
| 105 | - { | ||
| 106 | - [] then success(unique), | ||
| 107 | - [h . t] then | ||
| 108 | - if h is | ||
| 109 | - { | ||
| 110 | - table(table_name, create_string) then | ||
| 111 | - if alter_table(db, table_name, create_string, logger) is | ||
| 112 | - { | ||
| 113 | - failure then logError(logger, "Version "+version_string+": Can't create '"+table_name+"' table"); failure, | ||
| 114 | - success(_) then create_tables(db, logger, t, version_string) | ||
| 115 | - }, | ||
| 116 | - table(db_name, table_name, create_string) then | ||
| 117 | - if alter_table(db, db_name, table_name, create_string, logger) is | ||
| 118 | - { | ||
| 119 | - failure then logError(logger, "Version "+version_string+": Can't create '"+db_name+"."+table_name+"' table"); failure, | ||
| 120 | - success(_) then create_tables(db, logger, t, version_string) | ||
| 121 | - }, | ||
| 122 | - view(view_name, create_string) then | ||
| 123 | - if alter_view(db, view_name, create_string, logger) is | ||
| 124 | - { | ||
| 125 | - failure then logError(logger, "Version "+version_string+": Can't create '"+view_name+"' view"); failure, | ||
| 126 | - success(_) then create_tables(db, logger, t, version_string) | ||
| 127 | - }, | ||
| 128 | - } | ||
| 129 | - }. | ||
| 130 | - | ||
| 131 | - | ||
| 132 | -public define Maybe(One) | ||
| 133 | - create_indexes | ||
| 134 | - ( | ||
| 135 | - SQLite3DataBase db, | ||
| 136 | - Logger logger, | ||
| 137 | - List(String) indexes, | ||
| 138 | - String version_string | ||
| 139 | - )= | ||
| 140 | - if indexes is | ||
| 141 | - { | ||
| 142 | - [] then success(unique), | ||
| 143 | - [h . t] then | ||
| 144 | - if sql_query_timeout(db, h, [], "Version "+version_string+": create indexes") is | ||
| 145 | - { | ||
| 146 | - error(_) then failure, | ||
| 147 | - ok(_,_,_) then create_indexes(db, logger, t, version_string) | ||
| 148 | - } | ||
| 149 | - }. | ||
| 150 | - | ||
| 151 | - | ||
| 152 | -public define One | ||
| 153 | - make_foreign_key | ||
| 154 | - ( | ||
| 155 | - SQLite3DataBase db, | ||
| 156 | - String table_name, | ||
| 157 | - String field_name, | ||
| 158 | - String foreign_table_name, | ||
| 159 | - String foreign_field_name, | ||
| 160 | - Bool fk_null, | ||
| 161 | - Bool fk_cascade, | ||
| 162 | - Logger log | ||
| 163 | - ) = | ||
| 164 | - if (Maybe(One))make_foreign_key(db, table_name, field_name, foreign_table_name, foreign_field_name, fk_null, fk_cascade, log) is | ||
| 165 | - { | ||
| 166 | - failure then | ||
| 167 | - logError(log, "Can't create foreign key constraint between '"+table_name+"' and '"+foreign_table_name+"' tables"), | ||
| 168 | - success(_) then | ||
| 169 | - unique | ||
| 170 | - }. | ||
| 171 | - | ||
| 172 | -public define Maybe(One) | ||
| 173 | - make_foreign_keys | ||
| 174 | - ( | ||
| 175 | - SQLite3DataBase db, | ||
| 176 | - Logger logger, | ||
| 177 | - List((String, String, String, String, FK_Null, FK_Cascade)) relations, | ||
| 178 | - String version_string | ||
| 179 | - )= | ||
| 180 | - if relations is | ||
| 181 | - { | ||
| 182 | - [] then success(unique), | ||
| 183 | - [h . t] then | ||
| 184 | - if h is (table_name, field_name, foreign_table_name, foreign_field_name, fk_null, fk_cascade) then | ||
| 185 | - if (Maybe(One))make_foreign_key(db, table_name, field_name, foreign_table_name, foreign_field_name, fk_null, fk_cascade, logger) is | ||
| 186 | - { | ||
| 187 | - failure then | ||
| 188 | - logError(logger, "Version "+version_string+": Can't create foreign key constraint between '"+table_name+"' and '"+foreign_table_name+"' tables"); failure, | ||
| 189 | - success(_) then | ||
| 190 | - make_foreign_keys(db, logger, t, version_string) | ||
| 191 | - } | ||
| 192 | - }. | 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 | +transmit db_version.anubis | ||
| 19 | + | ||
| 20 | +public type DbTable: | ||
| 21 | + table(String name, String create_query), | ||
| 22 | + table(String db_name, String name, String create_query), | ||
| 23 | + view(String name, String create_query). | ||
| 24 | + | ||
| 25 | + | ||
| 26 | +public define Bool | ||
| 27 | + is_table_exists | ||
| 28 | + ( | ||
| 29 | + SQLite3DataBase db, | ||
| 30 | + String dbName, | ||
| 31 | + String table_name | ||
| 32 | + )= | ||
| 33 | + 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 | ||
| 34 | + { | ||
| 35 | + error(_) then false, //error in the SQL request | ||
| 36 | + ok(_, cursor, _) then | ||
| 37 | + if cursor(unique) is | ||
| 38 | + { | ||
| 39 | + error(_) then false, | ||
| 40 | + no_more_row then false, | ||
| 41 | + row(current) then true | ||
| 42 | + } | ||
| 43 | + }. | ||
| 44 | + | ||
| 45 | +public define Bool | ||
| 46 | + is_table_exists | ||
| 47 | + ( | ||
| 48 | + SQLite3DataBase db, | ||
| 49 | + String table_name | ||
| 50 | + )= | ||
| 51 | + is_table_exists(db, "main", table_name). | ||
| 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 | + | ||
| 78 | +public define Maybe(One) | ||
| 79 | + drop_all_triggers | ||
| 80 | + ( | ||
| 81 | + SQLite3DataBase db, | ||
| 82 | + Logger log | ||
| 83 | + ) = | ||
| 84 | + if sqlite3_query(db, "SELECT name FROM sqlite_master WHERE type = 'trigger'", []) is | ||
| 85 | + { | ||
| 86 | + error(err) then logError(log, db_error(err, "drop_all_triggers")); failure, | ||
| 87 | + ok(_, cursor, _) then | ||
| 88 | + with drop_trigger = (String name) |-> if sqlite3_query(db, "DROP TRIGGER " + name, []) is | ||
| 89 | + { | ||
| 90 | + error(err2) then logError(log, db_error(err2, "Failed to drop trigger '" + name + "'")), | ||
| 91 | + ok(_, cursor, _) then unique | ||
| 92 | + }, | ||
| 93 | + map_forget(drop_trigger, db_get_string_list(cursor, [])); | ||
| 94 | + success(unique) | ||
| 95 | + }. | ||
| 96 | + | ||
| 97 | +public define Maybe(One) | ||
| 98 | + create_tables | ||
| 99 | + ( | ||
| 100 | + SQLite3DataBase db, | ||
| 101 | + Logger logger, | ||
| 102 | + List(DbTable) tables, | ||
| 103 | + String version_string | ||
| 104 | + ) = | ||
| 105 | + if tables is | ||
| 106 | + { | ||
| 107 | + [] then success(unique), | ||
| 108 | + [h . t] then | ||
| 109 | + if h is | ||
| 110 | + { | ||
| 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 | + }, | ||
| 123 | + view(view_name, create_string) then | ||
| 124 | + if alter_view(db, view_name, create_string, logger) is | ||
| 125 | + { | ||
| 126 | + failure then logError(logger, "Version "+version_string+": Can't create '"+view_name+"' view"); failure, | ||
| 127 | + success(_) then create_tables(db, logger, t, version_string) | ||
| 128 | + }, | ||
| 129 | + } | ||
| 130 | + }. | ||
| 131 | + | ||
| 132 | + | ||
| 133 | +public define Maybe(One) | ||
| 134 | + create_indexes | ||
| 135 | + ( | ||
| 136 | + SQLite3DataBase db, | ||
| 137 | + Logger logger, | ||
| 138 | + List(String) indexes, | ||
| 139 | + String version_string | ||
| 140 | + )= | ||
| 141 | + if indexes is | ||
| 142 | + { | ||
| 143 | + [] then success(unique), | ||
| 144 | + [h . t] then | ||
| 145 | + if sql_query_timeout(db, h, [], "Version "+version_string+": create indexes") is | ||
| 146 | + { | ||
| 147 | + error(_) then failure, | ||
| 148 | + ok(_,_,_) then create_indexes(db, logger, t, version_string) | ||
| 149 | + } | ||
| 150 | + }. | ||
| 151 | + | ||
| 152 | + | ||
| 153 | +public define One | ||
| 154 | + make_foreign_key | ||
| 155 | + ( | ||
| 156 | + SQLite3DataBase db, | ||
| 157 | + String table_name, | ||
| 158 | + String field_name, | ||
| 159 | + String foreign_table_name, | ||
| 160 | + String foreign_field_name, | ||
| 161 | + Bool fk_null, | ||
| 162 | + Bool fk_cascade, | ||
| 163 | + Logger log | ||
| 164 | + ) = | ||
| 165 | + if (Maybe(One))make_foreign_key(db, table_name, field_name, foreign_table_name, foreign_field_name, fk_null, fk_cascade, log) is | ||
| 166 | + { | ||
| 167 | + failure then | ||
| 168 | + logError(log, "Can't create foreign key constraint between '"+table_name+"' and '"+foreign_table_name+"' tables"), | ||
| 169 | + success(_) then | ||
| 170 | + unique | ||
| 171 | + }. | ||
| 172 | + | ||
| 173 | +public define Maybe(One) | ||
| 174 | + make_foreign_keys | ||
| 175 | + ( | ||
| 176 | + SQLite3DataBase db, | ||
| 177 | + Logger logger, | ||
| 178 | + List((String, String, String, String, FK_Null, FK_Cascade)) relations, | ||
| 179 | + String version_string | ||
| 180 | + )= | ||
| 181 | + if relations is | ||
| 182 | + { | ||
| 183 | + [] then success(unique), | ||
| 184 | + [h . t] then | ||
| 185 | + if h is (table_name, field_name, foreign_table_name, foreign_field_name, fk_null, fk_cascade) then | ||
| 186 | + if (Maybe(One))make_foreign_key(db, table_name, field_name, foreign_table_name, foreign_field_name, fk_null, fk_cascade, logger) is | ||
| 187 | + { | ||
| 188 | + failure then | ||
| 189 | + logError(logger, "Version "+version_string+": Can't create foreign key constraint between '"+table_name+"' and '"+foreign_table_name+"' tables"); failure, | ||
| 190 | + success(_) then | ||
| 191 | + make_foreign_keys(db, logger, t, version_string) | ||
| 192 | + } | ||
| 193 | + }. |
database/migration_sqlite3.anubis
| @@ -16,43 +16,60 @@ read calexium_lib/net_services_protocols/logger_service.anubis | @@ -16,43 +16,60 @@ read calexium_lib/net_services_protocols/logger_service.anubis | ||
| 16 | 16 | ||
| 17 | read migration_common_sqlite3.anubis | 17 | read migration_common_sqlite3.anubis |
| 18 | 18 | ||
| 19 | +public type Migration: | ||
| 20 | + migration(DB_Version version, | ||
| 21 | + (SQLite3DataBase, Logger) -> Maybe(One) migrate_to, | ||
| 22 | + (SQLite3DataBase, Logger) -> Maybe(One) create_tables, | ||
| 23 | + (SQLite3DataBase, Logger) -> Maybe(One) create_indexes, | ||
| 24 | + ). | ||
| 25 | + | ||
| 19 | 26 | ||
| 20 | define String dir_save_database = "/db_backup/". | 27 | define String dir_save_database = "/db_backup/". |
| 21 | 28 | ||
| 22 | 29 | ||
| 30 | +public define Bool | ||
| 31 | + migration_less | ||
| 32 | + ( | ||
| 33 | + Migration a, | ||
| 34 | + Migration b | ||
| 35 | + )= | ||
| 36 | + db_version_less(a.version, b.version) | ||
| 37 | +. | ||
| 38 | + | ||
| 39 | + | ||
| 23 | /** | 40 | /** |
| 24 | * Compare two version string. Returns -1 if first is lower than second, 1 if first is greater than second, and 0 if equals. | 41 | * Compare two version string. Returns -1 if first is lower than second, 1 if first is greater than second, and 0 if equals. |
| 25 | */ | 42 | */ |
| 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, '.')). | 43 | +//public define Int |
| 44 | +// compare_db_version | ||
| 45 | +// ( | ||
| 46 | +// String version1, | ||
| 47 | +// String version2 | ||
| 48 | +// ) = | ||
| 49 | +// with compare = (List(String) v1, List(String) v2) |-compare-> (Int) | ||
| 50 | +// if v1 is | ||
| 51 | +// { | ||
| 52 | +// [] then | ||
| 53 | +// if v2 is | ||
| 54 | +// { | ||
| 55 | +// [] then 0, | ||
| 56 | +// [h2 . t2] then -1 | ||
| 57 | +// }, | ||
| 58 | +// [h1 . t1] then | ||
| 59 | +// if v2 is | ||
| 60 | +// { | ||
| 61 | +// [] then 1, | ||
| 62 | +// [h2 . t2] then | ||
| 63 | +// if h1 = h2 then compare(t1, t2) | ||
| 64 | +// else | ||
| 65 | +// with v1i = force_Type(decimal_scan(h1), 0), | ||
| 66 | +// v2i = force_Type(decimal_scan(h2), 0), | ||
| 67 | +// if v1i < v2i then -1 | ||
| 68 | +// else if v1i > v2i then 1 | ||
| 69 | +// else 0 | ||
| 70 | +// }, | ||
| 71 | +// }, | ||
| 72 | +// compare(split(version1, '.'), split(version2, '.')). | ||
| 56 | 73 | ||
| 57 | public define Maybe(One) | 74 | public define Maybe(One) |
| 58 | backup_database | 75 | backup_database |
| @@ -107,155 +124,163 @@ public define Maybe(One) | @@ -107,155 +124,163 @@ public define Maybe(One) | ||
| 107 | } | 124 | } |
| 108 | //else success(unique) | 125 | //else success(unique) |
| 109 | . | 126 | . |
| 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, //current version of app | ||
| 131 | - String db_ver, //version found in db settings | ||
| 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 | - }. | 127 | +// |
| 128 | +//define Maybe(One) | ||
| 129 | +// do_migration_loop | ||
| 130 | +// ( | ||
| 131 | +// SQLite3DataBase db, | ||
| 132 | +// Logger logger, | ||
| 133 | +// String current_version, //current version of app | ||
| 134 | +// String db_ver, //version found in db settings | ||
| 135 | +// List(Migration) migrations, | ||
| 136 | +// Maybe(Migration) need_to_create_table, // success in case of new DB or when no migration have been done | ||
| 137 | +// (SQLite3DataBase, String) -> One update_db_version, | ||
| 138 | +// ) = | ||
| 139 | +// if migrations is | ||
| 140 | +// { | ||
| 141 | +// [] then | ||
| 142 | +// if need_to_create_table is | ||
| 143 | +// { | ||
| 144 | +// failure then | ||
| 145 | +// update_db_version(db, current_version); | ||
| 146 | +// success(unique), | ||
| 147 | +// success(last) then | ||
| 148 | +// if last is migration(_, _, create_tables, create_indexes) then | ||
| 149 | +// if create_tables(db, logger) is success(_) then | ||
| 150 | +// if create_indexes(db, logger) is success(_) then | ||
| 151 | +// update_db_version(db, current_version); | ||
| 152 | +// success(unique) | ||
| 153 | +// else | ||
| 154 | +// failure | ||
| 155 | +// else | ||
| 156 | +// failure | ||
| 157 | +// }, | ||
| 158 | +// [h . t] then | ||
| 159 | +// since h is migration(version, migrate_to, _, _), | ||
| 160 | +// if compare_db_version(db_ver, version) < 0 then | ||
| 161 | +// logInfo(logger, "Migrating Database from version " + db_ver + " to version " + version); | ||
| 162 | +// if migrate_to(db, logger) is failure then | ||
| 163 | +// failure | ||
| 164 | +// else | ||
| 165 | +// do_migration_loop(db, logger, current_version, version, t, failure, update_db_version) | ||
| 166 | +// else | ||
| 167 | +// do_migration_loop(db, logger, current_version, db_ver, t, success(h), update_db_version), | ||
| 168 | +// }. | ||
| 169 | +// | ||
| 170 | +///* SQLite 3 version */ | ||
| 171 | +//public define Maybe(One) | ||
| 172 | +// do_migration | ||
| 173 | +// ( | ||
| 174 | +// SQLite3DataBase db, | ||
| 175 | +// Logger logger, | ||
| 176 | +// String current_version, | ||
| 177 | +// (SQLite3DataBase) -> String get_db_version, | ||
| 178 | +// (SQLite3DataBase, String) -> One update_db_version, | ||
| 179 | +// List(Migration) all_migrations, | ||
| 180 | +// )= | ||
| 181 | +// if is_empty_database(db) then // new empty database | ||
| 182 | +// logInfo(logger, "No database found. Creating a new one..."); | ||
| 183 | +// do_migration_loop(db, logger, current_version, "", [], last(all_migrations), update_db_version) | ||
| 184 | +// else | ||
| 185 | +// ( | ||
| 186 | +// with db_version = get_db_version(db), | ||
| 187 | +// //if app required db version is same as db_version, there is nothing to migrate | ||
| 188 | +// if compare_db_version(db_version, current_version) = 0 then | ||
| 189 | +// logInfo(logger, "Database version "+db_version+". No database migration found."); | ||
| 190 | +// success(unique) | ||
| 191 | +// else | ||
| 192 | +// do_migration_loop(db, logger, current_version, db_version, all_migrations, failure, update_db_version) | ||
| 193 | +// ). | ||
| 166 | 194 | ||
| 195 | +/* SQLite 3 version hk_settings with DB_Version*/ | ||
| 167 | 196 | ||
| 168 | -/* SQLite 3 version */ | ||
| 169 | -public define Maybe(One) | ||
| 170 | - do_migration | 197 | +define Maybe(One) |
| 198 | + do_table_indexes | ||
| 171 | ( | 199 | ( |
| 172 | - SQLite3DataBase db, | ||
| 173 | - Logger logger, | ||
| 174 | - String current_version, | ||
| 175 | - (SQLite3DataBase) -> String get_db_version, | ||
| 176 | - (SQLite3DataBase, String) -> One update_db_version, | ||
| 177 | - List(Migration) all_migrations, | 200 | + SQLite3DataBase db, |
| 201 | + Logger logger, | ||
| 202 | + Migration _migration, | ||
| 203 | + (DB_Version) -> One update_db_version | ||
| 178 | )= | 204 | )= |
| 179 | - if is_empty_database(db) then // new empty database | ||
| 180 | - logInfo(logger, "No database found. Creating a new one..."); | ||
| 181 | - do_migration_loop(db, logger, current_version, "", [], last(all_migrations), update_db_version) | ||
| 182 | - else | ||
| 183 | - ( | ||
| 184 | - with db_version = get_db_version(db), | ||
| 185 | - //if app version is same as db_version, there is nothing to migrate | ||
| 186 | - if compare_db_version(db_version, current_version) = 0 then | ||
| 187 | - logInfo(logger, "Database version "+db_version+". No database migration found."); | 205 | + since _migration is migration(mig_version, _, create_tables, create_indexes), |
| 206 | + | ||
| 207 | + if create_tables(db, logger) is success(_) then | ||
| 208 | + if create_indexes(db, logger) is success(_) then | ||
| 209 | + update_db_version(mig_version); | ||
| 188 | success(unique) | 210 | success(unique) |
| 189 | else | 211 | else |
| 190 | - do_migration_loop(db, logger, current_version, db_version, all_migrations, failure, update_db_version) | ||
| 191 | - ). | ||
| 192 | - | ||
| 193 | -/* SQLite 3 version hk_settings*/ | ||
| 194 | - | 212 | + failure |
| 213 | + else | ||
| 214 | + failure | ||
| 215 | +. | ||
| 216 | + | ||
| 195 | define Maybe(One) | 217 | define Maybe(One) |
| 196 | do_migration_loop | 218 | do_migration_loop |
| 197 | ( | 219 | ( |
| 198 | SQLite3DataBase db, | 220 | SQLite3DataBase db, |
| 199 | Logger logger, | 221 | Logger logger, |
| 200 | - String current_version, //current version of app | ||
| 201 | - String db_ver, //version found in db settings | 222 | +// String current_version, //current version of app |
| 223 | + DB_Version db_ver, //version found in db settings | ||
| 202 | List(Migration) migrations, | 224 | List(Migration) migrations, |
| 203 | - Maybe(Migration) need_to_create_table, // success in case of new DB or when no migration have been done | ||
| 204 | - (String) -> One update_db_version, | 225 | + (DB_Version) -> One update_db_version, |
| 205 | ) = | 226 | ) = |
| 206 | if migrations is | 227 | if migrations is |
| 207 | { | 228 | { |
| 208 | - [] then | ||
| 209 | - if need_to_create_table is | 229 | + [] then success(unique), |
| 230 | + [h . t] then | ||
| 231 | + since h is migration(migration_version, migrate_to, create_tables, create_indexes), | ||
| 232 | + | ||
| 233 | + if compare_db_version(db_ver, migration_version) is | ||
| 210 | { | 234 | { |
| 211 | - failure then | ||
| 212 | - update_db_version(current_version); | ||
| 213 | - success(unique), | ||
| 214 | - success(last) then | ||
| 215 | - if last is migration(_, _, create_tables, create_indexes) then | ||
| 216 | - if create_tables(db, logger) is success(_) then | ||
| 217 | - if create_indexes(db, logger) is success(_) then | ||
| 218 | - update_db_version(current_version); | ||
| 219 | - success(unique) | ||
| 220 | - else | ||
| 221 | - failure | 235 | + less then |
| 236 | + logInfo(logger, "Migrating Database from version " + db_ver + " to version " + migration_version); | ||
| 237 | + if migrate_to(db, logger) is failure then | ||
| 238 | + failure | ||
| 239 | + else | ||
| 240 | + do_migration_loop(db, logger, migration_version, t, update_db_version) | ||
| 241 | + | ||
| 242 | + more then | ||
| 243 | + logInfo(logger, "No Database migration found from version " + db_ver + " to version " + migration_version); | ||
| 244 | + do_migration_loop(db, logger, db_ver, t, update_db_version) | ||
| 245 | + | ||
| 246 | + equal then | ||
| 247 | + logInfo(logger, "No Database migration found from version " + db_ver + " to version " + migration_version); | ||
| 248 | + do_migration_loop(db, logger, db_ver, t, update_db_version) | ||
| 249 | + | ||
| 250 | + equal_but_sign then | ||
| 251 | + logInfo(logger, "Database migration found from version " + db_ver + " to version " + migration_version+ " by hash difference "); | ||
| 252 | + if do_table_indexes(db, logger, h, update_db_version) is success(_) then | ||
| 253 | + do_migration_loop(db, logger, migration_version, t, update_db_version) | ||
| 222 | else | 254 | else |
| 223 | failure | 255 | failure |
| 224 | - }, | ||
| 225 | - [h . t] then | ||
| 226 | - if h is migration(version, migrate_to, _, _) then | ||
| 227 | - if compare_db_version(db_ver, version) < 0 then | ||
| 228 | - logInfo(logger, "Migrating Database from version " + db_ver + " to version " + version); | ||
| 229 | - if migrate_to(db, logger) is failure then | ||
| 230 | - failure | ||
| 231 | - else | ||
| 232 | - do_migration_loop(db, logger, current_version, version, t, failure, update_db_version) | ||
| 233 | - else | ||
| 234 | - do_migration_loop(db, logger, current_version, db_ver, t, success(h), update_db_version), | 256 | + } |
| 235 | }. | 257 | }. |
| 236 | 258 | ||
| 237 | public define Maybe(One) | 259 | public define Maybe(One) |
| 238 | do_migration | 260 | do_migration |
| 239 | ( | 261 | ( |
| 240 | - SQLite3DataBase db, | ||
| 241 | - Logger logger, | ||
| 242 | - String current_version, | ||
| 243 | - String get_db_version, | ||
| 244 | - (String) -> One update_db_version, | ||
| 245 | - List(Migration) all_migrations, | 262 | + SQLite3DataBase db, |
| 263 | + Logger logger, | ||
| 264 | + DB_Version current_db_version, | ||
| 265 | + (DB_Version) -> One update_db_version, | ||
| 266 | + List(Migration) all_migrations, | ||
| 246 | )= | 267 | )= |
| 247 | if is_empty_database(db) then // new empty database | 268 | if is_empty_database(db) then // new empty database |
| 248 | logInfo(logger, "No database found. Creating a new one..."); | 269 | logInfo(logger, "No database found. Creating a new one..."); |
| 249 | - do_migration_loop(db, logger, current_version, "", [], last(all_migrations), update_db_version) | 270 | + if last(all_migrations) is success(migration) then |
| 271 | + do_table_indexes(db, logger, migration, update_db_version) | ||
| 272 | + else | ||
| 273 | + logError(logger, "No database migration found. Can't create Database"); | ||
| 274 | + failure | ||
| 250 | else | 275 | else |
| 251 | ( | 276 | ( |
| 252 | - with db_version = get_db_version, | ||
| 253 | - //if app version is same as db_version, there is nothing to migrate | ||
| 254 | - if compare_db_version(db_version, current_version) = 0 then | ||
| 255 | - logInfo(logger, "Database version "+db_version+". No database migration found."); | ||
| 256 | - success(unique) | ||
| 257 | - else | ||
| 258 | - do_migration_loop(db, logger, current_version, db_version, all_migrations, failure, update_db_version) | 277 | +// with db_version = get_db_version, |
| 278 | +// //if app version is same as db_version, there is nothing to migrate | ||
| 279 | +// if compare_db_version(db_version, current_version) = 0 then | ||
| 280 | +// logInfo(logger, "Database version "+db_version+". No database migration found."); | ||
| 281 | +// success(unique) | ||
| 282 | +// else | ||
| 283 | + do_migration_loop(db, logger, current_db_version, all_migrations, update_db_version) | ||
| 259 | ). | 284 | ). |
| 260 | 285 | ||
| 261 | public define Maybe(One) | 286 | public define Maybe(One) |
| @@ -263,7 +288,7 @@ public define Maybe(One) | @@ -263,7 +288,7 @@ public define Maybe(One) | ||
| 263 | ( | 288 | ( |
| 264 | SQLite3DataBase db, | 289 | SQLite3DataBase db, |
| 265 | Logger logger, | 290 | Logger logger, |
| 266 | - String current_version, | 291 | + //String current_version, |
| 267 | List(Migration) all_migrations, | 292 | List(Migration) all_migrations, |
| 268 | )= | 293 | )= |
| 269 | if last(all_migrations) is | 294 | if last(all_migrations) is |
database/settings.anubis
| @@ -17,9 +17,9 @@ public define Maybe(String) | @@ -17,9 +17,9 @@ public define Maybe(String) | ||
| 17 | Database db, | 17 | Database db, |
| 18 | String var, | 18 | String var, |
| 19 | )= | 19 | )= |
| 20 | - if sql_query_timeout(db, "SELECT var_value FROM settings WHERE var_name=" + db_make_sql_string(var) + ";", "select_settings") is | 20 | + if sql_query_timeout(db, "SELECT var_value FROM settings WHERE var_name=:var_name;", [bind_String(":var_name",var)], "select_settings") is |
| 21 | { | 21 | { |
| 22 | - failure then failure, //error in the SQL request | 22 | + failure then failure, //error in the SQL request |
| 23 | success(table_cursor) then | 23 | success(table_cursor) then |
| 24 | if table_cursor(unique) is | 24 | if table_cursor(unique) is |
| 25 | { | 25 | { |
| @@ -33,30 +33,30 @@ public define String | @@ -33,30 +33,30 @@ public define String | ||
| 33 | select_settings | 33 | select_settings |
| 34 | ( | 34 | ( |
| 35 | Database db, | 35 | Database db, |
| 36 | - String var, | ||
| 37 | - String default | 36 | + String var, |
| 37 | + String default | ||
| 38 | )= | 38 | )= |
| 39 | if select_settings(db, var) is | 39 | if select_settings(db, var) is |
| 40 | { | 40 | { |
| 41 | - failure then default, //error in the SQL request | ||
| 42 | - success(value) then value | 41 | + failure then default, //error in the SQL request |
| 42 | + success(value) then value | ||
| 43 | }. | 43 | }. |
| 44 | 44 | ||
| 45 | public define Int | 45 | public define Int |
| 46 | select_settings | 46 | select_settings |
| 47 | ( | 47 | ( |
| 48 | Database db, | 48 | Database db, |
| 49 | - String var, | ||
| 50 | - Int default | 49 | + String var, |
| 50 | + Int default | ||
| 51 | )= | 51 | )= |
| 52 | if select_settings(db, var) is | 52 | if select_settings(db, var) is |
| 53 | { | 53 | { |
| 54 | - failure then default, //error in the SQL request | ||
| 55 | - success(value) then | 54 | + failure then default, //error in the SQL request |
| 55 | + success(value) then | ||
| 56 | if decimal_scan(value) is | 56 | if decimal_scan(value) is |
| 57 | { | 57 | { |
| 58 | - failure then default, | ||
| 59 | - success(v) then v | 58 | + failure then default, |
| 59 | + success(v) then v | ||
| 60 | } | 60 | } |
| 61 | }. | 61 | }. |
| 62 | 62 | ||
| @@ -69,12 +69,12 @@ public define Bool | @@ -69,12 +69,12 @@ public define Bool | ||
| 69 | )= | 69 | )= |
| 70 | if select_settings(db, var) is | 70 | if select_settings(db, var) is |
| 71 | { | 71 | { |
| 72 | - failure then default, //error in the SQL request | ||
| 73 | - success(value) then | 72 | + failure then default, //error in the SQL request |
| 73 | + success(value) then | ||
| 74 | if decimal_scan(value) is | 74 | if decimal_scan(value) is |
| 75 | { | 75 | { |
| 76 | - failure then default, | ||
| 77 | - success(v) then v!=0 | 76 | + failure then default, |
| 77 | + success(v) then v!=0 | ||
| 78 | } | 78 | } |
| 79 | }. | 79 | }. |
| 80 | 80 |
| 1 | +/* | ||
| 2 | + * Created by PyramIDE. | ||
| 3 | + * User: フランスのトトロ aka (David RENÉ) | ||
| 4 | + * Date: 09/07/2017 | ||
| 5 | + * Time: 00:25 | ||
| 6 | + * © Calexium | ||
| 7 | + */ | ||
| 8 | + | ||
| 9 | + | ||
| 10 | +public type DB_Version: | ||
| 11 | + db_version( | ||
| 12 | + String version, //in form A.B.C.D usually the version of the application | ||
| 13 | + String sha1 //the SHA1 of the db definition, schema etc... | ||
| 14 | + ) | ||
| 15 | +. |
| 1 | +/* | ||
| 2 | + * Created by PyramIDE. | ||
| 3 | + * User: フランスのトトロ aka (David RENÉ) | ||
| 4 | + * Date: 09/07/2017 | ||
| 5 | + * Time: 00:39 | ||
| 6 | + * © Calexium | ||
| 7 | + */ | ||
| 8 | + | ||
| 9 | +transmit tools/basis.anubis | ||
| 10 | +transmit system/string.anubis | ||
| 11 | + | ||
| 12 | +public type Version: | ||
| 13 | + version( | ||
| 14 | + Word32 numeric, | ||
| 15 | + | ||
| 16 | + ) | ||
| 17 | +. | ||
| 18 | + | ||
| 19 | +public define Version | ||
| 20 | + version( | ||
| 21 | + Word8 a, | ||
| 22 | + Word8 b, | ||
| 23 | + Word8 c, | ||
| 24 | + Word8 d | ||
| 25 | + )= | ||
| 26 | + | ||
| 27 | + version( word32(word16(d, c), word16(b, a))) | ||
| 28 | +. | ||
| 29 | + | ||
| 30 | + | ||
| 31 | +define Maybe(Version) | ||
| 32 | + convert_digits_to_Version | ||
| 33 | + ( | ||
| 34 | + List(String) digits, | ||
| 35 | + Int current, | ||
| 36 | + Word32 value | ||
| 37 | + )= | ||
| 38 | + if digits is | ||
| 39 | + { | ||
| 40 | + [] then success(version(value)), | ||
| 41 | + [h . t] then | ||
| 42 | + if length(h) = 0 then | ||
| 43 | + convert_digits_to_Version(t, current -1, value) | ||
| 44 | + else | ||
| 45 | + if decimal_scan(h) is | ||
| 46 | + { | ||
| 47 | + failure then failure, | ||
| 48 | + success(v) then | ||
| 49 | + if v > 255 then //the value is greater than Word8 capacity | ||
| 50 | + failure | ||
| 51 | + else | ||
| 52 | + with value = value | ((v&0xFF)<< (current * 8)), | ||
| 53 | + if current = 0 then | ||
| 54 | + success(version(value)) | ||
| 55 | + else | ||
| 56 | + convert_digits_to_Version(t, current -1, value) | ||
| 57 | + } | ||
| 58 | + }. | ||
| 59 | + | ||
| 60 | + | ||
| 61 | + /** convert a version string into Word32 value | ||
| 62 | + * The version string, is made up of 4 values separated by period. | ||
| 63 | + * At this time, these values musn't be higher than 255 because, each value are | ||
| 64 | + * concatenated into Word32. Then each word8 is a part of final value the most significant | ||
| 65 | + * value will be placed into most significant place into Word32 | ||
| 66 | + * for example | ||
| 67 | + * String Word32 Representation | ||
| 68 | + * 2.5 [ 2 | 5 | 0 | 0 ] | ||
| 69 | + * 1.34.2.165 [ 1 | 43 | 2 | 165 ] | ||
| 70 | + * | ||
| 71 | + */ | ||
| 72 | + | ||
| 73 | +public define Maybe(Version) | ||
| 74 | + to_Version | ||
| 75 | + ( | ||
| 76 | + String ver_string | ||
| 77 | + )= | ||
| 78 | + with list_digits = split_by_token(ver_string, '.'), | ||
| 79 | + if length(list_digits) > 4 then | ||
| 80 | + failure | ||
| 81 | + else | ||
| 82 | + convert_digits_to_Version(list_digits, 3, 0). | ||
| 83 | + | ||
| 84 | + | ||
| 85 | +public define String | ||
| 86 | + to_String | ||
| 87 | + ( | ||
| 88 | + Version _version | ||
| 89 | + ) = | ||
| 90 | + since _version is version(numeric), | ||
| 91 | + (numeric >> 24) + "." + | ||
| 92 | + ((numeric >> 16) & 0xFF) + "." + | ||
| 93 | + ((numeric >> 8) & 0xFF) + "." + | ||
| 94 | + (numeric & 0xFF) | ||
| 95 | +. | ||
| 96 | + | ||
| 97 | +public define String | ||
| 98 | + String s + Version v = | ||
| 99 | + s + to_String(v) | ||
| 100 | +. | ||
| 101 | + | ||
| 102 | +public define String | ||
| 103 | + Version v + String s = | ||
| 104 | + to_String(v) + s | ||
| 105 | +. |