dohmysql 0.1.8 → 0.1.9

Sign up to get free protection for your applications and to get access to all the features.
data/bin/makedb CHANGED
@@ -5,6 +5,7 @@ require 'doh/mysql/database_creator'
5
5
 
6
6
  opts = Doh::Options.new(
7
7
  {'drop_first' => [false, "-z", "--drop_first", "if true, will drop the database or tables before creating"] \
8
+ ,'skip_migrate' => [false, "-k", "--skip_migrate", "if true, will skip running migrates after creating"] \
8
9
  ,'database' => [Doh.config[:default_database], "-d", "--database <database>", "name of the source database -- defaults to Doh.config[:default_database], currently '#{Doh.config[:default_database]}'"] \
9
10
  ,'all' => [false, "-a", "--all", "create all databases"] \
10
11
  ,'target' => [nil, "-g", "--target <database>", "name of the target database -- defaults to same as source"] \
@@ -20,9 +21,9 @@ db_creator = DohDb::DatabaseCreator.new
20
21
  if opts.tables
21
22
  db_creator.create_tables(opts.database, opts.drop_first, opts.tables.split(/,/))
22
23
  elsif opts.all
23
- db_creator.create_all_databases(opts.drop_first)
24
+ db_creator.create_all_databases(opts.drop_first, !opts.skip_migrate)
24
25
  elsif opts.target
25
- db_creator.create_database_copy(opts.target, opts.database, opts.drop_first)
26
+ db_creator.create_database_copy(opts.target, opts.database, opts.drop_first, !opts.skip_migrate)
26
27
  else
27
- db_creator.create_database(opts.database, opts.drop_first)
28
+ db_creator.create_database(opts.database, opts.drop_first, !opts.skip_migrate)
28
29
  end
data/bin/migrate ADDED
@@ -0,0 +1,59 @@
1
+ #!/usr/bin/env ruby
2
+ require 'doh/app/cli'
3
+ require 'doh/mysql/migrate/runner'
4
+ require 'doh/mysql/migrate/analyzer'
5
+
6
+ COMMAND_INFO = [
7
+ ['make', '<name>', 'creates the files for a new migration'],
8
+ ['check', '<name>', 'checks that all migrations are valid'],
9
+ ['commit', '<name>', 'UNIMPLEMENTED: executes the check command, then git add,commit'],
10
+ ['apply', '<name>', 'applies one or more migrations'],
11
+ ['revert', '<name>', 'reverts one or more migrations'],
12
+ ['verify' ,'<name>', 'verifies that the migration has been integrated into the base files'],
13
+ ['merge', '<name>', 'UNIMPLEMENTED: executes the verify command, then git rm,commit'],
14
+ ].freeze
15
+ COMMANDS = COMMAND_INFO.collect {|name, args, desc| name}.freeze
16
+ NOTIFY_COMMANDS = %w(apply revert)
17
+
18
+ cmd_detail = COMMAND_INFO.collect do |name, args, desc|
19
+ args = ' ' + args unless args.empty?
20
+ name_rpad = ' ' * (33 - (name.size + args.size))
21
+ " #{name}#{args}#{name_rpad}#{desc}"
22
+ end.join("\n")
23
+
24
+ opts = Doh::Options.new(
25
+ {'database' => [Doh.config[:default_database], "-d", "--database <database>", "name of the database to migrate -- defaults to config[:default_database], currently '#{Doh.config[:default_database]}'"] \
26
+ }, true, "Commands:\n\n#{cmd_detail}")
27
+
28
+ cmd_name = opts.varargs.shift
29
+ cmd_args = opts.varargs
30
+
31
+ unless COMMANDS.include?(cmd_name)
32
+ warn "unrecognized command #{cmd_name}"
33
+ exit 1
34
+ end
35
+
36
+ if opts.database.to_s.empty?
37
+ warn "You must specify a database, either here with -d or in config"
38
+ exit 1
39
+ end
40
+
41
+ if ['make', 'apply', 'revert'].include?(cmd_name)
42
+ success, msg = DohDb::MigrateRunner.new(opts.database).send(cmd_name, *cmd_args)
43
+ elsif ['check', 'verify'].include?(cmd_name)
44
+ success, msg = DohDb::MigrateAnalyzer.new(opts.database).send(cmd_name, *cmd_args)
45
+ end
46
+
47
+ if success
48
+ puts "succcess: " + msg
49
+ if NOTIFY_COMMANDS.include?(cmd_name)
50
+ dohlog.notify("success: #{msg}")
51
+ end
52
+ else
53
+ warn "***************** FAILURE **********************"
54
+ warn msg
55
+ if NOTIFY_COMMANDS.include?(cmd_name)
56
+ dohlog.notify("FAILURE: #{msg}")
57
+ end
58
+ exit 1
59
+ end
@@ -2,27 +2,30 @@ require 'doh/core_ext/dir'
2
2
  require 'doh/mysql/handle'
3
3
  require 'doh/mysql/load_sql'
4
4
  require 'yaml'
5
+ require 'doh/mysql/file_util'
5
6
 
6
7
  module DohDb
7
8
 
8
9
  class DatabaseCreator
10
+ MIGRATE_TABLE_DEF = "CREATE TABLE migrate (migrated_at DATETIME NOT NULL, name CHAR(50) NOT NULL)"
11
+
9
12
  def initialize(sqlfiles_directory = nil, connector = nil)
10
- @sqlfiles_directory = sqlfiles_directory || File.join(Doh.root, 'data/mysql')
13
+ @sqlfiles_directory = sqlfiles_directory || DohDb.sql_files_path
11
14
  @connector = connector || DohDb.connector_instance
12
15
  @include_scripts = true
13
16
  end
14
17
 
15
- def create_database(dbname, drop_first = false)
16
- create_one_database(get_handle(''), dbname, dbname, drop_first)
18
+ def create_database(dbname, drop_first, include_migrates)
19
+ create_one_database(get_handle(''), dbname, dbname, drop_first, include_migrates)
17
20
  end
18
21
 
19
- def create_database_copy(dest_db, source_db, drop_first = false)
20
- create_one_database(get_handle(''), dest_db, source_db, drop_first)
22
+ def create_database_copy(dest_db, source_db, drop_first, include_migrates)
23
+ create_one_database(get_handle(''), dest_db, source_db, drop_first, include_migrates)
21
24
  end
22
25
 
23
- def create_all_databases(drop_first = false)
26
+ def create_all_databases(drop_first, include_migrates)
24
27
  dbh = get_handle('')
25
- Dir.directories(@sqlfiles_directory).each {|elem| create_one_database(dbh, elem, elem, drop_first)}
28
+ Dir.directories(@sqlfiles_directory).each {|elem| create_one_database(dbh, elem, elem, drop_first, include_migrates)}
26
29
  end
27
30
 
28
31
  def create_tables(database, drop_first, *table_and_view_names)
@@ -48,23 +51,21 @@ private
48
51
  File.join(@sqlfiles_directory, database, subdir, name) + '.sql'
49
52
  end
50
53
 
51
- def find_files(source_db, subdir, ext = '.sql')
52
- path = File.join(@sqlfiles_directory, source_db, subdir)
53
- return [] unless File.exist?(path)
54
- Dir.entries(path).find_all {|entry| entry.end_with?(ext)}.sort.collect {|elem| File.join(path, elem)}
54
+ def find_files(glob)
55
+ Dir.glob(File.join(@sqlfiles_directory, glob)).sort
55
56
  end
56
57
 
57
58
  def view_files(source_db)
58
59
  path = File.join(@sqlfiles_directory, source_db, 'views')
59
60
  return [] unless File.exist?(path)
60
61
  ordered_filenames = YAML.load_file(File.join(path, 'order.yml')).collect {|uqfn| File.join(path, uqfn) + '.sql'}
61
- ordered_filenames + (find_files(source_db, 'views') - ordered_filenames)
62
+ ordered_filenames + (find_files("#{source_db}/views/*.sql") - ordered_filenames)
62
63
  end
63
64
 
64
65
  def create_base_table(dbh, database, table_name, drop_first)
65
66
  dbh.query("DROP TABLE IF EXISTS #{table_name}") if drop_first
66
67
  files = [sql_filename(database, 'tables', table_name)]
67
- inserts_file = sql_filename(database, 'insert_sql', table_name)
68
+ inserts_file = sql_filename(database, 'inserts', table_name)
68
69
  files.push(inserts_file) if File.exist?(inserts_file)
69
70
  DohDb.load_sql(dbh.config, files)
70
71
  end
@@ -74,19 +75,34 @@ private
74
75
  DohDb.load_sql(dbh.config, [sql_filename(database, 'views', view_name)])
75
76
  end
76
77
 
77
- def create_one_database(dbh, dest_db, source_db, drop_first)
78
+ def create_one_database(dbh, dest_db, source_db, drop_first, include_migrates)
78
79
  dohlog.info("creating database " + dest_db + " from source files at " + File.join(@sqlfiles_directory, source_db))
79
80
  dbh.query("DROP DATABASE IF EXISTS " + dest_db) if drop_first
80
81
 
81
82
  dbh.query("CREATE DATABASE " + dest_db)
82
83
  dbh.query("USE " + dest_db)
84
+ dbh.query(MIGRATE_TABLE_DEF)
83
85
 
84
86
  @connector.config[:database] = dest_db
85
87
 
86
- files = find_files(source_db, 'tables') + find_files(source_db, 'insert_sql') + view_files(source_db)
88
+ files = find_files("#{source_db}/tables/*.sql") + find_files("#{source_db}/inserts/*.sql") + view_files(source_db)
87
89
  DohDb.load_sql(@connector.config, files)
88
- return unless @include_scripts
89
- find_files(source_db, 'insert_scripts', '.rb').each do |filename|
90
+ run_scripts(source_db) if @include_scripts
91
+ apply_migrates(dbh, source_db) if include_migrates
92
+ end
93
+
94
+ def apply_migrates(dbh, source_db)
95
+ apply_files = find_files("#{source_db}/migrate/*_apply.sql")
96
+ DohDb.load_sql(@connector.config, apply_files)
97
+ migrate_names = apply_files.collect {|path| File.basename(path).partition('_apply').first}
98
+ # NOTE: could package these up into one insert, but it is very small, and will have very few migrates, so not a big deal
99
+ migrate_names.each do |name|
100
+ dbh.query("INSERT INTO migrate SET migrated_at = NOW(), name = #{name.to_sql}")
101
+ end
102
+ end
103
+
104
+ def run_scripts(source_db)
105
+ find_files("#{source_db}/scripts/*.rb").each do |filename|
90
106
  dohlog.info("loading file: #{filename}")
91
107
  load(filename)
92
108
  end
@@ -0,0 +1,11 @@
1
+ module DohDb
2
+
3
+ def self.sql_files_path(database = nil)
4
+ if database
5
+ File.join(Doh.root, "data/mysql/#{database}")
6
+ else
7
+ File.join(Doh.root, 'data/mysql')
8
+ end
9
+ end
10
+
11
+ end
@@ -8,7 +8,7 @@ end
8
8
 
9
9
  # NOTE: this doesn't work on jruby, but keeping it around in case it's determined to be significantly faster than the more portable version in place now
10
10
  # in which case, we can use the popen version on the rubys that it works with and the other one as needed
11
- def self.load_sql_using_popen(dbconfig, filenames)
11
+ def self.load_sql_using_one_popen(dbconfig, filenames)
12
12
  dohlog.debug("loading sql file: " + filenames.first) if filenames.size == 1
13
13
 
14
14
  mysqlcmd = 'mysql' + mysql_arg(dbconfig[:host], 'h') + mysql_arg(dbconfig[:username], 'u') + mysql_arg(dbconfig[:password], 'p') + ' ' + dbconfig[:database]
@@ -19,7 +19,8 @@ def self.load_sql_using_popen(dbconfig, filenames)
19
19
  io.close
20
20
  end
21
21
 
22
- def self.load_sql(dbconfig, filenames)
22
+ # this works on JRuby, but is slower than popen
23
+ def self.load_sql_using_each_backtick(dbconfig, filenames)
23
24
  dohlog.debug("loading sql file: " + filenames.first) if filenames.size == 1
24
25
 
25
26
  basecmd = 'mysql' + mysql_arg(dbconfig[:host], 'h') + mysql_arg(dbconfig[:username], 'u') + mysql_arg(dbconfig[:password], 'p') + ' ' + dbconfig[:database] + ' < '
@@ -28,5 +29,25 @@ def self.load_sql(dbconfig, filenames)
28
29
  end
29
30
  end
30
31
 
32
+ # pass through so we can change implemenation easily
33
+ def self.load_sql(dbconfig, filenames)
34
+ DohDb.load_sql_using_each_backtick(dbconfig, filenames)
35
+ end
36
+
37
+ # trying Open3 now for better error handling; unknown as of yet if this works under JRuby
38
+ def self.load_sql_using_each_open3(dbconfig, filenames)
39
+ dohlog.debug("loading sql file: " + filenames.first) if filenames.size == 1
40
+
41
+ basecmd = 'mysql' + mysql_arg(dbconfig[:host], 'h') + mysql_arg(dbconfig[:username], 'u') + mysql_arg(dbconfig[:password], 'p') + ' ' + dbconfig[:database] + ' < '
42
+ filenames.each do |elem|
43
+ mysqlcmd = "#{basecmd} #{elem}"
44
+ stdin, stdout, stderr = Open3.popen3(mysqlcmd)
45
+ stdoutstr = stdout.read
46
+ stdout.close
47
+ stderrstr = stderr.read
48
+ raise "#{stderrstr}" if !stderrstr.empty?
49
+ end
50
+ end
51
+
31
52
  end
32
53
 
@@ -0,0 +1,118 @@
1
+ require 'doh/mysql/migrate/runner'
2
+ require 'doh/mysql/database_creator'
3
+ require 'open3'
4
+
5
+ module DohDb
6
+
7
+ class MigrateAnalyzer
8
+ CHECK_DATABASE = 'dohmysql_migrate_check'
9
+ FILE_PREFIX = '/tmp/dohmysql_migrate_check_'
10
+
11
+ def initialize(database)
12
+ @database = database
13
+ @directory = File.join(DohDb.sql_files_path(@database), 'migrate')
14
+ @sql_original = FILE_PREFIX + "#{@database}_original.sql"
15
+ @sql_final = FILE_PREFIX + "#{@database}_final.sql"
16
+ end
17
+
18
+ def check(migrate_name)
19
+ DohDb::DatabaseCreator.new.create_database_copy(CHECK_DATABASE, @database, true)
20
+ dump_sql(@sql_original)
21
+
22
+ runner = DohDb::MigrateRunner.new(@database)
23
+
24
+ success, msg = runner.apply(migrate_name)
25
+ return [success, msg] if !success
26
+
27
+ success, msg = runner.revert(migrate_name)
28
+ return [success, msg] if !success
29
+
30
+ dump_sql(@sql_final)
31
+
32
+ diffstr = diff(@sql_original, @sql_final)
33
+ return [false, diffstr] unless diffstr.empty?
34
+
35
+ File.delete(@sql_original)
36
+ File.delete(@sql_final)
37
+
38
+ [true, "migration #{migrate_name} checked successfully"]
39
+ end
40
+
41
+ def verify(migrate_name)
42
+ DohDb::DatabaseCreator.new.create_database_copy(CHECK_DATABASE, @database, true, false)
43
+ dump_sql(@sql_original)
44
+
45
+ runner = DohDb::MigrateRunner.new(@database)
46
+
47
+ success, msg = runner.apply(migrate_name)
48
+ return [success, msg] if !success
49
+
50
+ dump_sql(@sql_final)
51
+
52
+ diffstr = diff(@sql_original, @sql_final)
53
+ return [false, diffstr] unless diffstr.empty?
54
+
55
+ File.delete(@sql_original)
56
+ File.delete(@sql_final)
57
+
58
+ [true, "migration #{migrate_name} verified successfully"]
59
+ end
60
+
61
+ private
62
+ def execute_cmd(cmd)
63
+ dohlog.debug("executing: #{cmd}")
64
+ stdin, stdout, stderr = Open3.popen3(cmd)
65
+ stdoutstr = stdout.read
66
+ stdout.close
67
+ stderrstr = stderr.read
68
+ raise "stderr: #{stderrstr}" if !stderrstr.empty?
69
+ stdoutstr
70
+ end
71
+
72
+ def dump_sql(fname)
73
+ sql = execute_cmd("mysqldump -uroot -d #{CHECK_DATABASE}")
74
+ sql = remove_unwanted_comparisons(sql)
75
+ sql = sql.split(/[\r|\n]+/)
76
+ output = []
77
+ current_keys = []
78
+ #ignore order of keys
79
+ sql.each do |line|
80
+ if line =~ /(.*KEY[^,]*),?/
81
+ current_keys.push($1)
82
+ else
83
+ output.concat(current_keys.sort)
84
+ output.push(line)
85
+ current_keys = []
86
+ end
87
+ end
88
+
89
+ File.open(fname, 'wb') do |file|
90
+ output.each do |line|
91
+ file.write(line + "\n")
92
+ end
93
+ end
94
+ end
95
+
96
+ def remove_unwanted_comparisons(sql)
97
+ regexp = /--.-- Temporary table structure for view[^;]*;[^;]*;[^;]*;/m
98
+ regexp2 = /--.-- Table structure for table `[^;]*_deleteme`[^;]*;[^;]*;[^;]*;[^;]*;[^;]*;/m
99
+ sql.gsub(regexp, '').gsub(regexp2, '')
100
+ end
101
+
102
+ def remove_safe_diff_lines(result)
103
+ result.dup.delete_if do |elem|
104
+ elem =~ /\d+c\d+/ || elem =~ /-- Dump completed on.*/ || elem == '---' || elem =~ /.*ENGINE.*AUTO_INCREMENT=.*/ || elem =~ /.*ENGINE.*DEFAULT CHARSET=.*/
105
+ end
106
+ end
107
+
108
+ def diff(file1, file2)
109
+ result = remove_safe_diff_lines(execute_cmd("diff -b #{file1} #{file2}").split(/[\r|\n]+/))
110
+ if result.empty?
111
+ ''
112
+ else
113
+ "#{file1} and #{file2} differ\n" + result.join("\n")
114
+ end
115
+ end
116
+ end
117
+
118
+ end
@@ -0,0 +1,63 @@
1
+ require 'doh/mysql/load_sql'
2
+
3
+ module DohDb
4
+
5
+ class MigrateRunner
6
+ def initialize(database)
7
+ @database = database
8
+ @table = @database + '.migrate'
9
+ @directory = File.join(DohDb.sql_files_path(@database), 'migrate')
10
+ @config = DohDb::connector_instance.config
11
+ end
12
+
13
+ def make(migrate_name)
14
+ apply_fname = apply_filename(migrate_name)
15
+ if File.exist?(apply_fname)
16
+ return [false, "it appears that migration #{migrate_name} already exists"]
17
+ end
18
+ `touch #{apply_fname}`
19
+ `touch #{revert_filename(migrate_name)}`
20
+ [true, "files for migration #{migrate_name} created in #{@directory}"]
21
+ end
22
+
23
+ def apply(migrate_name)
24
+ if migrate_exist?(migrate_name)
25
+ return [false, "migration #{migrate_name} has already been applied"]
26
+ end
27
+ load_sql(apply_filename(migrate_name))
28
+ Doh.db.query("INSERT INTO #@table SET migrated_at = NOW(), name = #{migrate_name.to_sql}")
29
+ [true, "migration #{migrate_name} applied successfully"]
30
+ rescue Exception => excpt
31
+ [false, excpt.message]
32
+ end
33
+
34
+ def revert(migrate_name)
35
+ unless migrate_exist?(migrate_name)
36
+ return [false, "migration #{migrate_name} can't be reverted until it has been applied"]
37
+ end
38
+ load_sql(revert_filename(migrate_name))
39
+ Doh.db.query("DELETE FROM #@table WHERE name = #{migrate_name.to_sql}")
40
+ [true, "migration #{migrate_name} reverted successfully"]
41
+ rescue Exception => excpt
42
+ [false, excpt.message]
43
+ end
44
+
45
+ private
46
+ def apply_filename(migrate_name)
47
+ File.join(@directory, "#{migrate_name}_apply.sql")
48
+ end
49
+
50
+ def revert_filename(migrate_name)
51
+ File.join(@directory, "#{migrate_name}_revert.sql")
52
+ end
53
+
54
+ def load_sql(filename)
55
+ DohDb.load_sql_using_each_open3(@config, [filename])
56
+ end
57
+
58
+ def migrate_exist?(migrate_name)
59
+ Doh.db.select_field("SELECT COUNT(*) FROM #@table WHERE name = #{migrate_name.to_sql}") > 0
60
+ end
61
+ end
62
+
63
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dohmysql
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.8
4
+ version: 0.1.9
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,11 +10,11 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-05-02 00:00:00.000000000Z
13
+ date: 2012-05-03 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: dohroot
17
- requirement: &70310724663340 !ruby/object:Gem::Requirement
17
+ requirement: !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,21 +22,31 @@ dependencies:
22
22
  version: 0.1.0
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *70310724663340
25
+ version_requirements: !ruby/object:Gem::Requirement
26
+ none: false
27
+ requirements:
28
+ - - ! '>='
29
+ - !ruby/object:Gem::Version
30
+ version: 0.1.0
26
31
  - !ruby/object:Gem::Dependency
27
32
  name: dohutil
28
- requirement: &70310724662120 !ruby/object:Gem::Requirement
33
+ requirement: !ruby/object:Gem::Requirement
29
34
  none: false
30
35
  requirements:
31
36
  - - ! '>='
32
37
  - !ruby/object:Gem::Version
33
- version: 0.2.1
38
+ version: 0.2.3
34
39
  type: :runtime
35
40
  prerelease: false
36
- version_requirements: *70310724662120
41
+ version_requirements: !ruby/object:Gem::Requirement
42
+ none: false
43
+ requirements:
44
+ - - ! '>='
45
+ - !ruby/object:Gem::Version
46
+ version: 0.2.3
37
47
  - !ruby/object:Gem::Dependency
38
48
  name: mysql2
39
- requirement: &70310724660480 !ruby/object:Gem::Requirement
49
+ requirement: !ruby/object:Gem::Requirement
40
50
  none: false
41
51
  requirements:
42
52
  - - ! '>='
@@ -44,10 +54,15 @@ dependencies:
44
54
  version: 0.3.11
45
55
  type: :runtime
46
56
  prerelease: false
47
- version_requirements: *70310724660480
57
+ version_requirements: !ruby/object:Gem::Requirement
58
+ none: false
59
+ requirements:
60
+ - - ! '>='
61
+ - !ruby/object:Gem::Version
62
+ version: 0.3.11
48
63
  - !ruby/object:Gem::Dependency
49
64
  name: sqlstmt
50
- requirement: &70310724658640 !ruby/object:Gem::Requirement
65
+ requirement: !ruby/object:Gem::Requirement
51
66
  none: false
52
67
  requirements:
53
68
  - - ! '>='
@@ -55,10 +70,15 @@ dependencies:
55
70
  version: 0.1.1
56
71
  type: :runtime
57
72
  prerelease: false
58
- version_requirements: *70310724658640
73
+ version_requirements: !ruby/object:Gem::Requirement
74
+ none: false
75
+ requirements:
76
+ - - ! '>='
77
+ - !ruby/object:Gem::Version
78
+ version: 0.1.1
59
79
  - !ruby/object:Gem::Dependency
60
80
  name: dohtest
61
- requirement: &70310724657600 !ruby/object:Gem::Requirement
81
+ requirement: !ruby/object:Gem::Requirement
62
82
  none: false
63
83
  requirements:
64
84
  - - ! '>='
@@ -66,17 +86,24 @@ dependencies:
66
86
  version: 0.1.8
67
87
  type: :development
68
88
  prerelease: false
69
- version_requirements: *70310724657600
89
+ version_requirements: !ruby/object:Gem::Requirement
90
+ none: false
91
+ requirements:
92
+ - - ! '>='
93
+ - !ruby/object:Gem::Version
94
+ version: 0.1.8
70
95
  description: wrapper classes around low level mysql gem to provide a better interface
71
96
  email:
72
97
  - devinfo@atpsoft.com
73
98
  executables:
74
99
  - makedb
100
+ - migrate
75
101
  extensions: []
76
102
  extra_rdoc_files:
77
103
  - MIT-LICENSE
78
104
  files:
79
105
  - bin/makedb
106
+ - bin/migrate
80
107
  - lib/doh/mysql/abstract_row.rb
81
108
  - lib/doh/mysql/cache_connector.rb
82
109
  - lib/doh/mysql/connector_instance.rb
@@ -85,10 +112,13 @@ files:
85
112
  - lib/doh/mysql/database_creator.rb
86
113
  - lib/doh/mysql/db_date.rb
87
114
  - lib/doh/mysql/error.rb
115
+ - lib/doh/mysql/file_util.rb
88
116
  - lib/doh/mysql/handle.rb
89
117
  - lib/doh/mysql/hash_row.rb
90
118
  - lib/doh/mysql/load_sql.rb
91
119
  - lib/doh/mysql/metadata_util.rb
120
+ - lib/doh/mysql/migrate/analyzer.rb
121
+ - lib/doh/mysql/migrate/runner.rb
92
122
  - lib/doh/mysql/raw_row_builder.rb
93
123
  - lib/doh/mysql/readonly_row.rb
94
124
  - lib/doh/mysql/smart_row.rb
@@ -128,7 +158,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
128
158
  version: '0'
129
159
  requirements: []
130
160
  rubyforge_project:
131
- rubygems_version: 1.8.15
161
+ rubygems_version: 1.8.24
132
162
  signing_key:
133
163
  specification_version: 3
134
164
  summary: friendly mysql client interface
@@ -143,3 +173,4 @@ test_files:
143
173
  - test/to_sql.dt.rb
144
174
  - test/typecasting.dt.rb
145
175
  - test/writable_row.dt.rb
176
+ has_rdoc: