migration.anubis 6.77 KB
/*
 * 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).