class Knjdbrevision

Public Class Methods

new(args = {}) click to toggle source
# File lib/knjdbrevision.rb, line 2
def initialize(args = {})
  @args = args
end

Public Instance Methods

init_db(schema, db) click to toggle source
# File lib/knjdbrevision.rb, line 6
def init_db(schema, db)
  schema["tables"].each do |table_name, table_data|
    begin
      begin
        table_obj = db.tables[table_name.to_sym]
        
        if table_data["columns"]
          table_data["columns"].each do |col_data|
            begin
              col_obj = table_obj.column(col_data["name"])
              col_str = "#{table_name}.#{col_obj.name}"
              type = col_data["type"].to_s
              
              #BUGFIX: When using SQLite3 the primary-column or a autoincr-column may never change type from int... This will break it!
              if db.opts[:type] == "sqlite3" and col_obj.type.to_s == "int" and (col_data["primarykey"] or col_data["autoincr"]) and db.int_types.index(col_data["type"].to_s)
                type = "int"
              end
              
              dochange = false
              
              if type and col_obj.type.to_s != type
                print "Type mismatch on #{col_str}: #{col_data["type"]}, #{col_obj.type}\n"
                dochange = true
              end
              
              if col_data.has_key?("maxlength") and col_obj.maxlength.to_s != col_data["maxlength"].to_s
                print "Maxlength mismatch on #{col_str}: #{col_data["maxlength"]}, #{col_obj.maxlength}\n"
                dochange = true
              end
              
              if col_data.has_key?("null") and col_obj.null?.to_s != col_data["null"].to_s
                print "Null mismatch on #{col_str}: #{col_data["null"]}, #{col_obj.null?}\n"
                dochange = true
              end
              
              if col_data.has_key?("default") and col_obj.default.to_s != col_data["default"].to_s
                print "Default mismatch on #{col_str}: #{col_data["default"]}, #{col_obj.default}\n"
                dochange = true
              end
              
              if col_data.has_key?("comment") and col_obj.comment.to_s != col_data["comment"].to_s
                print "Comment mismatch on #{col_str}: #{col_data["comment"]}, #{col_obj.comment}\n"
                dochange = true
              end
              
              if col_data.is_a?(Hash) and col_data["on_before_alter"]
                callback_data = col_data["on_before_alter"].call("db" => db, "table" => table_obj, "col" => col_obj, "col_data" => col_data)
                if callback_data and callback_data["action"]
                  if callback_data["action"] == "retry"
                    raise Knj::Errors::Retry
                  end
                end
              end
              
              col_obj.change(col_data) if dochange
            rescue Knj::Errors::NotFound => e
              print "Column not found: #{table_obj.name}.#{col_data["name"]}.\n"
              
              if col_data.has_key?("renames")
                rename_found = false
                col_data["renames"].each do |col_name|
                  begin
                    col_rename = table_obj.column(col_name)
                  rescue Knj::Errors::NotFound => e
                    next
                  end
                  
                  print "Rename #{table_obj.name}.#{col_name} to #{table_obj.name}.#{col_data["name"]}\n"
                  if col_data.is_a?(Hash) and col_data["on_before_rename"]
                    col_data["on_before_rename"].call("db" => db, "table" => table_obj, "col" => col_rename, "col_data" => col_data)
                  end
                  
                  col_rename.change(col_data)
                  
                  if col_data.is_a?(Hash) and col_data["on_after_rename"]
                    col_data["on_after_rename"].call("db" => db, "table" => table_obj, "col" => col_rename, "col_data" => col_data)
                  end
                  
                  rename_found = true
                  break
                end
                
                retry if rename_found
              end
              
              #Try to find out the previous column - if so we can set "after" which makes the column being created in the right order as defined.
              if !col_data.has_key?("after")
                prev_no = table_data["columns"].index(col_data)
                if prev_no != nil and prev_no != 0
                  prev_no = prev_no - 1
                  prev_col_data = table_data["columns"][prev_no]
                  col_data["after"] = prev_col_data["name"]
                end
              end
              
              oncreated = col_data["on_created"]
              col_data.delete("on_created") if col_data["oncreated"]
              col_obj = table_obj.create_columns([col_data])
              oncreated.call("db" => db, "table" => table_obj) if oncreated
            end
          end
        end
        
        if table_data["columns_remove"]
          table_data["columns_remove"].each do |column_name, column_data|
            begin
              col_obj = table_obj.column(column_name)
            rescue Knj::Errors::NotFound => e
              next
            end
            
            column_data["callback"].call if column_data.is_a?(Hash) and column_data["callback"]
            col_obj.drop
          end
        end
        
        if table_data["indexes"]
          table_data["indexes"].each do |index_data|
            begin
              index_obj = table_obj.index(index_data["name"])
            rescue Knj::Errors::NotFound => e
              table_obj.create_indexes([index_data])
            end
          end
        end
        
        if table_data["indexes_remove"]
          table_data["indexes_remove"].each do |index_name, index_data|
            begin
              index_obj = table_obj.index(index_name)
            rescue Knj::Errors::NotFound => e
              next
            end
            
            if index_data.is_a?(Hash) and index_data["callback"]
              index_data["callback"].call if index_data["callback"]
            end
            
            index_obj.drop
          end
        end
        
        if table_data["rows"]
          table_data["rows"].each do |row_data|
            if row_data["find_by"]
              find_by = row_data["find_by"]
            elsif row_data["data"]
              find_by = row_data["data"]
            else
              raise "Could not figure out the find-by."
            end
            
            rows_found = 0
            q_rows = db.select(table_name, find_by)
            while d_rows = q_rows.fetch
              rows_found += 1
              
              if Knj::ArrayExt.hash_diff?(Knj::ArrayExt.hash_sym(row_data["data"]), Knj::ArrayExt.hash_sym(d_rows), {"h2_to_h1" => false})
                print "Data was not right - updating row: #{JSON.generate(row_data["data"])}\n"
                db.update(table_name, row_data["data"], d_rows)
              end
            end
            
            if rows_found == 0
              print "Inserting row: #{JSON.generate(row_data["data"])}\n"
              db.insert(table_name, row_data["data"])
            end
          end
        end
      rescue Knj::Errors::NotFound => e
        if table_data["renames"]
          table_data["renames"].each do |table_name_rename|
            begin
              table_rename = db.tables[table_name_rename]
              table_rename.rename(table_name)
              raise Knj::Errors::Retry
            rescue Knj::Errors::NotFound
              next
            end
          end
        end
        
        if table_data["on_create"]
          table_data["on_create"].call("db" => db, "table_name" => table_name, "table_data" => table_data)
        end
        
        table_obj = db.tables.create(table_name, table_data)
        
        if table_data["on_create_after"]
          table_data["on_create_after"].call("db" => db, "table_name" => table_name, "table_data" => table_data)
        end
      end
    rescue Knj::Errors::Retry
      retry
    end
  end
  
  if schema["tables_remove"]
    schema["tables_remove"].each do |table_name, table_data|
      begin
        table_obj = db.tables[table_name.to_sym]
        table_data["callback"].call if table_data.is_a?(Hash) and table_data["callback"]
        table_obj.drop
      rescue Knj::Errors::NotFound => e
        next
      end
    end
  end
end