Guest User

Untitled

a guest
Feb 20th, 2018
95
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 4.11 KB | None | 0 0
  1. #!/usr/bin/env ruby
  2.  
  3. require 'rubygems'
  4. require 'mysql'
  5. require 'highline'
  6. require 'optparse'
  7.  
  8. class CopyDatabase
  9.  
  10. def initialize(options = {})
  11. @connection = Mysql.connect(options[:host], options[:username], options[:password])
  12. @connection.query_with_result = false
  13. @options = options
  14. Kernel.at_exit { @connection.close }
  15. end
  16.  
  17. def copy(from_database, to_database)
  18. @from_database, @to_database, @tables = [from_database, to_database, nil]
  19. @connection.select_db(from_database)
  20. return if tables.empty?
  21. drop_database if @options[:drop_database]
  22. create_database if @options[:create_database]
  23. copy_structure
  24. lock_tables { copy_data }
  25. end
  26.  
  27. private
  28.  
  29. def create_database
  30. query('CREATE DATABASE ' + "`#{@to_database}`")
  31. end
  32.  
  33. def drop_database
  34. query('DROP DATABASE IF EXISTS ' + "`#{@to_database}`")
  35. end
  36.  
  37. def copy_structure
  38. tables.each do |table|
  39. query('DROP TABLE IF EXISTS ' + sanitized_table(@to_database, table))
  40. query('CREATE TABLE ' + sanitized_table(@to_database, table) +
  41. ' LIKE ' + sanitized_table(@from_database, table))
  42. end
  43. end
  44.  
  45. def copy_data
  46. tables.each do |table|
  47. disable_keys(@to_database, table) do
  48. query('INSERT INTO ' + sanitized_table(@to_database, table) +
  49. ' SELECT * FROM ' + sanitized_table(@from_database, table))
  50. end
  51. end
  52. end
  53.  
  54. def disable_keys(database, table)
  55. query('ALTER TABLE ' + sanitized_table(database, table) + ' DISABLE KEYS')
  56. yield
  57. query('ALTER TABLE ' + sanitized_table(database, table) + ' ENABLE KEYS')
  58. end
  59.  
  60. def lock_tables
  61. query('LOCK TABLES ' + locks.join(', '))
  62. yield
  63. query('UNLOCK TABLES')
  64. end
  65.  
  66. def locks
  67. tables.inject(Array.new) do |arr, table|
  68. arr << (sanitized_table(@to_database, table) + ' WRITE') <<
  69. (sanitized_table(@from_database, table) + ' READ')
  70. end
  71. end
  72.  
  73. def tables
  74. @tables ||= @connection.list_tables
  75. end
  76.  
  77. def sanitized_table(database, table)
  78. "`#{database}`.`#{table}`"
  79. end
  80.  
  81. def query(sql)
  82. puts sql if @options[:verbose]
  83. @connection.query(sql)
  84. end
  85. end
  86.  
  87. class CopyDatabaseController
  88.  
  89. def self.run(args)
  90. new(args).run
  91. end
  92.  
  93. def initialize(args)
  94. @ui = HighLine.new
  95. parse(args)
  96. end
  97.  
  98. def run
  99. CopyDatabase.new(@options).
  100. copy(@from_database, @to_database)
  101. end
  102.  
  103. private
  104.  
  105. def parse(args)
  106. @options = {
  107. :user => ENV['USER'],
  108. :password => '',
  109. :verbose => false,
  110. :host => '127.0.0.1',
  111. :create_database => false,
  112. :drop_database => false
  113. }
  114.  
  115. parser = OptionParser.new do |opts|
  116. opts.banner = "Usage: #{File.basename($0)} [options] from-database to-database"
  117. opts.on('-u', '--user',
  118. 'User to use when connecting to MySQL.',
  119. "Default: #{@options[:user]}") do |value|
  120. @options[:user] = value
  121. end
  122. opts.on('-p', '--password',
  123. 'Prompt for a password to use when connecting to MySQL.') do
  124. @options[:password] = @ui.ask('Enter password: ') { |q| q.echo = false }
  125. end
  126. opts.on('-h', '--host HOST',
  127. 'Host or socket to connect to.',
  128. "Default: #{@options[:host]}") do |value|
  129. @options[:host] = value
  130. end
  131. opts.on('-v', '--verbose', 'Prints queries as they are executed.') do
  132. @options[:verbose] = true
  133. end
  134. opts.on('-C', '--create-database',
  135. 'Create the destination database before copying.') do
  136. @options[:create_database] = true
  137. end
  138. opts.on('-f', '--force',
  139. 'Drop and then create the destination database before copying.') do
  140. @options[:drop_database] = true
  141. @options[:create_database] = true
  142. end
  143. opts.on('--help', 'Display this help message.') do
  144. puts opts
  145. exit
  146. end
  147. end
  148.  
  149. parser.parse!(args)
  150.  
  151. if args.size != 2
  152. puts parser
  153. exit
  154. end
  155.  
  156. @from_database, @to_database = args
  157. end
  158. end
  159.  
  160. CopyDatabaseController.run(ARGV)
Add Comment
Please, Sign In to add comment