require 'flydata/mysql/binlog_position' require 'flydata-core/mysql/command_generator' module Flydata module Mysql class TableDdl VERSION0 = 0 # the version where no .generated_ddl file was generated. # Therefore, this version never shows up in anywhere. VERSION1 = 1 # the version which doesn't handle server side encoding support. VERSION2 = 2 # the version with server side encoding support, migrated from # the previous versions. Format/functionality-wise, it's the # same as Version 3. VERSION3 = 3 # the version with server side encoding support, generated by # sync:generated_table_ddl command. VERSION4 = 4 # the version with server side encoding support, generated by # the auto-generated CREATE TABLE event. VERSION = VERSION3 def self.migrate_tables(tables, mysql_opts, sync_fm, position_file, context, &block) migrate_to_v2(tables, mysql_opts, sync_fm, position_file, context, &block) end private V2_TARGET_VERSION = VERSION2 EVENT_TYPE = 'Query' ALTER_TABLE_CHARSET_SQL = <= V2_TARGET_VERSION if mysql_tabledefs.nil? FlydataCore::Mysql::CommandGenerator.each_mysql_tabledef(tables, mysql_opts) do |mysql_tabledef, error| raise error if error mysql_tabledefs ||= {} mysql_tabledefs[mysql_tabledef.table_name] = mysql_tabledef end end mysql_tabledef = mysql_tabledefs[table] if binlog_pos.nil? # get binlog position binlog_pos = BinLogPosition.new(File.open(position_file){|f| f.read }) original_binlog_file = context.current_binlog_file context.current_binlog_file = binlog_pos.file end # get charset charset = mysql_tabledef.default_charset_mysql # construct queries # column charset column_event = nil at_subquery = mysql_tabledef.column_def.select{|col, coldef| /CHARACTER SET/.match(coldef) }.collect{|col, coldef| CHANGE_COLUMN_SQL % [col, coldef]}.join(",") unless at_subquery.empty? column_query = ALTER_TABLE_SQL % [database, table, at_subquery] column_event = QueryEvent.new(EVENT_TYPE, database, table, binlog_pos.pos, event_size, column_query, Time.now.to_i) yield column_event end # table charset table_query = ALTER_TABLE_CHARSET_SQL % [database, table, charset] # create events and yield table_event = QueryEvent.new(EVENT_TYPE, database, table, binlog_pos.pos, event_size, table_query, Time.now.to_i) yield table_event $log.info "migrating table `#{table}` from version #{version} to version #{V2_TARGET_VERSION}. Table event #{table_event} Column event #{column_event}" # update generated_ddl sync_fm.save_generated_ddl([table], V2_TARGET_VERSION.to_s) end context.current_binlog_file = original_binlog_file if binlog_pos end end # mimics RubyBinlog::QueryEvent class QueryEvent def initialize(event_type, database_name, event_table_name, next_position, event_length, query, timestamp) @event_type = event_type @database_name = database_name @event_table_name = event_table_name @next_position = next_position @event_length = event_length @query = query @timestamp = timestamp end attr_reader :event_type, :database_name, :event_table_name, :next_position, :event_length, :query, :timestamp def to_s <