mysql2postgres 0.3.3 → 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 44c431dce8b1d09c5ebef95e6f1a56dbc2d7b79e67b594821d9a33c287d5d2b5
4
- data.tar.gz: cf5352e91abcd255f2286a95a5a0c3c1dadae5cd3804f0914ea8dee999e27f4d
3
+ metadata.gz: cc905b9634e92298f5b5d192b6f4388294f6153a777b551b408bc5e944247b3f
4
+ data.tar.gz: 108d90760f0600e55f117df749147f8137d3044a7724dd901f76869db7b45caf
5
5
  SHA512:
6
- metadata.gz: 34cce30cf4cffd22bc21e0be57267da80f5806ebeebfcd2934acb6f306af79ba5da512065a8acd5367964a5af00265cea9b3c5cfbacc1f6e7425412300613420
7
- data.tar.gz: 72c40e74f83546cac80b33e8b22ecb7f8035ec15ace7a572d95373c83ce4055fde7809f52f7a0608fb7a426197d4c6a71cb39f815f3719f1a52adaf1ade266a2
6
+ metadata.gz: 6b08edc13623c942b61d03cecce1f577eca9fce3906e3c06ef17c848396dfebadb39017cb7ae7aecb5193e91cffc85d2a4cea2e49054f0e7dd3dffc8f53012eb
7
+ data.tar.gz: 5ef72f3a6ac5961102d282b38cf2eb5bc62d301f5e84b590dc4e9dd7d057fa51c43f5272b112478ab6b6d3513fc3ac67e8a24bae0d9f23d3f162c0ddd8f591e0
data/.gitignore CHANGED
@@ -7,3 +7,5 @@ config/database.yml
7
7
  Gemfile.lock
8
8
  pkg
9
9
  test/fixtures/test*.sql
10
+ .enable_dev
11
+ .enable_test
data/README.md CHANGED
@@ -2,8 +2,7 @@
2
2
 
3
3
  [![Run Linters](https://github.com/AlphaNodes/mysql2postgres/workflows/Run%20Rubocop/badge.svg)](https://github.com/AlphaNodes/mysql2postgres/actions/workflows/rubocop.yml) [![Run Tests](https://github.com/AlphaNodes/mysql2postgres/workflows/Tests/badge.svg)](https://github.com/AlphaNodes/mysql2postgres/actions/workflows/tests.yml)
4
4
 
5
- The minimum Ruby version supported in `main` branch is `2.7`,
6
- and the next release will have the same requirement.
5
+ Convert MySQL database to PostgreSQL database.
7
6
 
8
7
  ## Requirements
9
8
 
@@ -22,16 +21,22 @@ gem 'mysql2postgres'
22
21
  Configuration is written in [YAML format](http://www.yaml.org/ "YAML Ain't Markup Language")
23
22
  and passed as the first argument on the command line.
24
23
 
25
- Configuration file has be provided with config/database.yml, see config/default.database.yml for
26
- an example.
24
+ Configuration file has be provided with config/database.yml, see [config/default.database.yml](config/default.database.yml) for an example and for configuration information.
27
25
 
28
26
  ## Usage
29
27
 
30
28
  After providing settings, start migration with
31
29
 
32
30
  ```sh
31
+ # set destination to use
32
+ MYSQL2POSTGRES_ENV=test
33
+ # use can also use (MYSQL2POSTGRES_ENV is used, if both are defined)
34
+ RAILS_ENV=test
33
35
 
36
+ # with default configuration, which use config/database.yml
34
37
  bundle exec mysql2postgres
38
+ # OR with specified configuration file
39
+ bundle exec mysql2postgres /home/you/mysql2postgres.yml
35
40
  ```
36
41
 
37
42
  ## Tests
data/Rakefile CHANGED
@@ -22,7 +22,7 @@ end
22
22
 
23
23
  desc 'Run all tests'
24
24
  task :test do
25
- # Rake::Task['test:units'].invoke
25
+ Rake::Task['test:units'].invoke
26
26
  Rake::Task['test:integration'].invoke
27
27
  end
28
28
 
data/bin/mysql2postgres CHANGED
@@ -7,21 +7,13 @@ require 'rubygems'
7
7
  require 'bundler/setup'
8
8
  require 'mysql2postgres'
9
9
 
10
- CONFIG_FILE = File.join File.dirname(__dir__), 'config', 'database.yml'
10
+ config_file = ARGV.empty? ? File.join(File.dirname(__dir__), 'config', 'database.yml') : File.expand_path(ARGV[0])
11
11
 
12
- file = if ARGV.length.positive?
13
- ARGV[0]
14
- else
15
- CONFIG_FILE
16
- end
12
+ raise "'#{config_file}' does not exist" unless FileTest.exist? config_file
17
13
 
18
- unless FileTest.exist?(CONFIG_FILE) || (ARGV.length.positive? && FileTest.exist?(File.expand_path(ARGV[0])))
19
- raise "'#{file}' does not exist"
20
- end
14
+ db_yaml = YAML.safe_load File.read(config_file)
21
15
 
22
- db_yaml = YAML.safe_load File.read(file)
16
+ raise "'#{config_file}' does not contain a mysql configuration directive for conversion" unless db_yaml.key? 'mysql'
17
+ raise "'#{config_file}' does not contain destinations configuration directive for conversion" unless db_yaml.key? 'destinations'
23
18
 
24
- raise "'#{file}' does not contain a mysql configuration directive for conversion" unless db_yaml.key? 'mysql'
25
- raise "'#{file}' does not contain a destination configuration directive for conversion" unless db_yaml.key? 'destination'
26
-
27
- Mysql2postgres.new(db_yaml).convert
19
+ Mysql2postgres.new(db_yaml, config_file).convert
@@ -3,29 +3,17 @@
3
3
  class Mysql2postgres
4
4
  class Connection
5
5
  attr_reader :conn,
6
- :adapter,
7
6
  :hostname,
8
7
  :login,
9
8
  :password,
10
9
  :database,
11
10
  :schema,
12
11
  :port,
13
- :environment,
14
12
  :copy_manager,
15
13
  :stream,
16
14
  :is_copying
17
15
 
18
- def initialize(options)
19
- @environment = (ENV['RAILS_ENV'] || 'development').to_sym
20
-
21
- if options[:destination].nil? ||
22
- options[:destination].empty? ||
23
- options[:destination][environment].nil? ||
24
- options[:destination][environment].empty?
25
- raise 'Unable to locate PostgreSQL destination environment in the configuration file'
26
- end
27
-
28
- pg_options = options[:destination][environment]
16
+ def initialize(pg_options)
29
17
  @hostname = pg_options[:hostname] || 'localhost'
30
18
  @login = pg_options[:username]
31
19
  @password = pg_options[:password]
@@ -33,18 +21,20 @@ class Mysql2postgres
33
21
  @port = (pg_options[:port] || 5432).to_s
34
22
 
35
23
  @database, @schema = database.split ':'
36
- @adapter = pg_options[:adapter] || 'jdbcpostgresql'
37
24
 
25
+ @conn = open
26
+ raise_nil_connection if conn.nil?
27
+
28
+ @is_copying = false
29
+ @current_statement = ''
30
+ end
31
+
32
+ def open
38
33
  @conn = PG::Connection.open dbname: database,
39
34
  user: login,
40
35
  password: password,
41
36
  host: hostname,
42
37
  port: port
43
-
44
- raise_nil_connection if conn.nil?
45
-
46
- @is_copying = false
47
- @current_statement = ''
48
38
  end
49
39
 
50
40
  # ensure that the copy is completed, in case we hadn't seen a '\.' in the data stream.
@@ -120,6 +110,16 @@ class Mysql2postgres
120
110
  raise 'No Connection'
121
111
  end
122
112
 
113
+ def tables
114
+ result = run_statement <<~SQL_TABLES
115
+ SELECT table_name
116
+ FROM information_schema.tables
117
+ WHERE table_schema = 'public' AND table_type = 'BASE TABLE'
118
+ SQL_TABLES
119
+
120
+ result.map { |t| t['table_name'] }
121
+ end
122
+
123
123
  private
124
124
 
125
125
  def run_statement(statement)
@@ -16,7 +16,6 @@ class Mysql2postgres
16
16
  def initialize(reader, writer, options)
17
17
  @reader = reader
18
18
  @writer = writer
19
- @options = options
20
19
  @exclude_tables = options[:exclude_tables] || []
21
20
  @only_tables = options[:tables]
22
21
  @suppress_data = options[:suppress_data] || false
@@ -164,6 +164,24 @@ class Mysql2postgres
164
164
  end
165
165
  end
166
166
 
167
+ attr_reader :mysql
168
+
169
+ def initialize(options)
170
+ @host = options[:mysql][:hostname]
171
+ @user = options[:mysql][:username]
172
+ @passwd = options[:mysql][:password]
173
+ @db = options[:mysql][:database]
174
+ @port = if options[:mysql][:port]
175
+ options[:mysql][:port] unless options[:mysql][:port].to_s.empty?
176
+ else
177
+ 3306
178
+ end
179
+ @sock = options[:mysql][:socket] && !options[:mysql][:socket].empty? ? options[:mysql][:socket] : nil
180
+ @flag = options[:mysql][:flag] && !options[:mysql][:flag].empty? ? options[:mysql][:flag] : nil
181
+
182
+ connect
183
+ end
184
+
167
185
  def connect
168
186
  @mysql = ::Mysql.connect @host, @user, @passwd, @db, @port, @sock
169
187
  # utf8_unicode_ci :: https://rubydoc.info/gems/ruby-mysql/Mysql/Charset
@@ -197,20 +215,6 @@ class Mysql2postgres
197
215
  end
198
216
  end
199
217
 
200
- def initialize(options)
201
- @host = options[:mysql][:hostname]
202
- @user = options[:mysql][:username]
203
- @passwd = options[:mysql][:password]
204
- @db = options[:mysql][:database]
205
- @port = options[:mysql][:port] || 3306
206
- @sock = options[:mysql][:socket] && !options[:mysql][:socket].empty? ? options[:mysql][:socket] : nil
207
- @sock = options[:mysql][:flag] && !options[:mysql][:flag].empty? ? options[:mysql][:flag] : nil
208
-
209
- connect
210
- end
211
-
212
- attr_reader :mysql
213
-
214
218
  def tables
215
219
  @tables ||= @mysql.query('SHOW TABLES').map { |row| Table.new(self, row.first) }
216
220
  end
@@ -5,14 +5,13 @@ require 'mysql2postgres/connection'
5
5
 
6
6
  class Mysql2postgres
7
7
  class PostgresDbWriter < PostgresFileWriter
8
- attr_reader :connection, :filename
8
+ attr_reader :connection
9
9
 
10
- def initialize(filename, options)
10
+ def initialize(file, destination)
11
11
  # NOTE: the superclass opens and truncates filename for writing
12
- super filename
12
+ super
13
13
 
14
- @filename = filename
15
- @connection = Connection.new options
14
+ @connection = Connection.new destination
16
15
  end
17
16
 
18
17
  def inload(path = filename)
@@ -1,12 +1,16 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'mysql2postgres/postgres_writer'
4
+ require 'fileutils'
4
5
 
5
6
  class Mysql2postgres
6
7
  class PostgresFileWriter < PostgresWriter
7
- def initialize(file)
8
+ def initialize(file, destination)
8
9
  super()
9
10
 
11
+ @filename = file
12
+ @destination = destination
13
+
10
14
  @f = File.open file, 'w+:UTF-8'
11
15
  @f << <<~SQL_HEADER
12
16
  -- MySQL 2 PostgreSQL dump\n
@@ -88,7 +92,7 @@ class Mysql2postgres
88
92
  @f << columns
89
93
 
90
94
  if (primary_index = table.indexes.find { |index| index[:primary] })
91
- @f << ",\n CONSTRAINT #{table.name}_pkey PRIMARY KEY(#{primary_index[:columns].map { |col| PG::Connection.quote_ident(col) }.join(', ')})"
95
+ @f << ",\n CONSTRAINT #{table.name}_pkey PRIMARY KEY(#{quoted_list primary_index[:columns]})"
92
96
  end
93
97
 
94
98
  @f << <<~SQL_OIDS
@@ -103,7 +107,7 @@ class Mysql2postgres
103
107
  @f << <<~SQL_INDEX
104
108
  DROP INDEX IF EXISTS #{PG::Connection.quote_ident index[:name]} CASCADE;
105
109
  CREATE #{unique}INDEX #{PG::Connection.quote_ident index[:name]}
106
- ON #{PG::Connection.quote_ident table.name} (#{index[:columns].map { |col| PG::Connection.quote_ident(col) }.join(', ')});
110
+ ON #{PG::Connection.quote_ident table.name} (#{quoted_list index[:columns]});
107
111
  SQL_INDEX
108
112
  end
109
113
  end
@@ -113,8 +117,8 @@ class Mysql2postgres
113
117
  def write_constraints(table)
114
118
  table.foreign_keys.each do |key|
115
119
  @f << "ALTER TABLE #{PG::Connection.quote_ident table.name} " \
116
- "ADD FOREIGN KEY (#{key[:column].map { |c| PG::Connection.quote_ident(c) }.join(', ')}) " \
117
- "REFERENCES #{PG::Connection.quote_ident key[:ref_table]}(#{key[:ref_column].map { |c| PG::Connection.quote_ident(c) }.join(', ')}) " \
120
+ "ADD FOREIGN KEY (#{quoted_list key[:column]}) " \
121
+ "REFERENCES #{PG::Connection.quote_ident key[:ref_table]}(#{quoted_list key[:ref_column]}) " \
118
122
  "ON UPDATE #{key[:on_update]} ON DELETE #{key[:on_delete]};\n"
119
123
  end
120
124
  end
@@ -125,7 +129,7 @@ class Mysql2postgres
125
129
  -- Data for Name: #{table.name}; Type: TABLE DATA; Schema: public
126
130
  --
127
131
 
128
- COPY "#{table.name}" (#{table.columns.map { |column| PG::Connection.quote_ident(column[:name]) }.join(', ')}) FROM stdin;
132
+ COPY "#{table.name}" (#{quoted_list(table.columns.map { |m| m[:name] })}) FROM stdin;
129
133
  SQL_COPY
130
134
 
131
135
  reader.paginated_read table, 1000 do |row, _counter|
@@ -139,5 +143,15 @@ class Mysql2postgres
139
143
  def close
140
144
  @f.close
141
145
  end
146
+
147
+ def inload
148
+ puts "\nSkip import to PostgreSQL DB. SQL file created successfully."
149
+ end
150
+
151
+ private
152
+
153
+ def quoted_list(list)
154
+ list.map { |c| PG::Connection.quote_ident(c) }.join(', ')
155
+ end
142
156
  end
143
157
  end
@@ -1,10 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'zlib'
4
- require 'mysql2postgres/writer'
5
4
 
6
5
  class Mysql2postgres
7
- class PostgresWriter < Writer
6
+ class PostgresWriter
7
+ attr_reader :filename, :destination
8
+
8
9
  def column_description(column)
9
10
  "#{PG::Connection.quote_ident column[:name]} #{column_type_info column}"
10
11
  end
@@ -57,9 +58,14 @@ class Mysql2postgres
57
58
  default = nil
58
59
  'date'
59
60
  when 'timestamp'
60
- default = ' DEFAULT CURRENT_TIMESTAMP' if column[:default] == 'CURRENT_TIMESTAMP'
61
- default = " DEFAULT '1970-01-01 00:00'" if column[:default] == '0000-00-00 00:00'
62
- default = " DEFAULT '1970-01-01 00:00:00'" if column[:default] == '0000-00-00 00:00:00'
61
+ case column[:default]
62
+ when 'CURRENT_TIMESTAMP'
63
+ default = ' DEFAULT CURRENT_TIMESTAMP'
64
+ when datetime_zero
65
+ default = " DEFAULT '#{datetime_zero_fix}'"
66
+ when datetime_zero(with_seconds: true) # rubocop: disable Style/MethodCallWithArgsParentheses
67
+ default = " DEFAULT '#{datetime_zero_fix with_seconds: true}'"
68
+ end
63
69
  'timestamp without time zone'
64
70
  when 'time'
65
71
  default = ' DEFAULT NOW()' if default
@@ -89,45 +95,74 @@ class Mysql2postgres
89
95
  row[index] = Time.at(row[index]).utc.strftime('%H:%M:%S') if column[:type] == 'time' && row[index]
90
96
 
91
97
  if row[index].is_a? Time
92
- row[index] = row[index].to_s.gsub '0000-00-00 00:00', '1970-01-01 00:00'
93
- row[index] = row[index].to_s.gsub '0000-00-00 00:00:00', '1970-01-01 00:00:00'
98
+ row[index] = row[index].to_s.gsub datetime_zero, datetime_zero_fix
99
+ row[index] = row[index].to_s.gsub datetime_zero(with_seconds: true), datetime_zero_fix(with_seconds: true)
94
100
  end
95
101
 
96
102
  if column_type(column) == 'boolean'
97
103
  row[index] = if row[index] == 1
98
104
  't'
105
+ elsif row[index].zero?
106
+ 'f'
99
107
  else
100
- row[index].zero? ? 'f' : row[index]
108
+ row[index]
101
109
  end
102
110
  end
103
111
 
104
- if row[index].is_a? String
105
- row[index] = if column_type(column) == 'bytea'
106
- if column[:name] == 'data'
107
- with_gzip = false
108
- table.columns.each_with_index do |column_data, index_data|
109
- if column_data[:name] == 'compression' && row[index_data] == 'gzip'
110
- with_gzip = true
111
- break
112
- end
113
- end
114
- if with_gzip
115
- PG::Connection.escape_bytea(Zlib::Inflate.inflate(row[index])).gsub(/\\/, '\\\\\\').gsub(/''/, "'")
116
- else
117
- PG::Connection.escape_bytea(row[index]).gsub(/\\/, '\\\\\\').gsub(/''/, "'")
118
- end
119
- else
120
- PG::Connection.escape_bytea(row[index]).gsub(/\\/, '\\\\\\').gsub(/''/, "'")
121
- end
122
- else
123
- row[index].gsub(/\\/, '\\\\\\').gsub(/\n/, '\n').gsub(/\t/, '\t').gsub(/\r/, '\r').gsub(/\0/, '')
124
- end
125
- end
112
+ row[index] = string_data row, index, column if row[index].is_a? String
126
113
 
127
114
  row[index] = '\N' unless row[index]
128
115
  end
129
116
  end
130
117
 
131
118
  def truncate(_table) end
119
+
120
+ def inload
121
+ raise "Method 'inload' needs to be overridden..."
122
+ end
123
+
124
+ private
125
+
126
+ def datetime_zero(with_seconds: false)
127
+ datetime_value date: '0000-00-00', with_seconds: with_seconds
128
+ end
129
+
130
+ def datetime_zero_fix(with_seconds: false)
131
+ datetime_value date: '1970-01-01', with_seconds: with_seconds
132
+ end
133
+
134
+ def datetime_value(date:, with_seconds: false)
135
+ value = ["#{date} 00:00"]
136
+ value << '00' if with_seconds
137
+ value.join ':'
138
+ end
139
+
140
+ def string_data(row, index, column)
141
+ if column_type(column) == 'bytea'
142
+ if column[:name] == 'data'
143
+ with_gzip = false
144
+ table.columns.each_with_index do |column_data, index_data|
145
+ if column_data[:name] == 'compression' && row[index_data] == 'gzip'
146
+ with_gzip = true
147
+ break
148
+ end
149
+ end
150
+
151
+ escape_bytea(with_gzip ? Zlib::Inflate.inflate(row[index]) : row[index])
152
+ else
153
+ escape_bytea row[index]
154
+ end
155
+ else
156
+ escape_data(row[index]).gsub(/\n/, '\n').gsub(/\t/, '\t').gsub(/\r/, '\r').gsub(/\0/, '')
157
+ end
158
+ end
159
+
160
+ def escape_bytea(data)
161
+ escape_data(PG::Connection.escape_bytea(data)).gsub(/''/, "'")
162
+ end
163
+
164
+ def escape_data(value)
165
+ value.gsub(/\\/, '\\\\\\')
166
+ end
132
167
  end
133
168
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  class Mysql2postgres
4
- VERSION = '0.3.3'
4
+ VERSION = '0.4.0'
5
5
  end
@@ -12,7 +12,6 @@ require 'pg/result'
12
12
  require 'mysql2postgres/version'
13
13
  require 'mysql2postgres/converter'
14
14
  require 'mysql2postgres/mysql_reader'
15
- require 'mysql2postgres/writer'
16
15
  require 'mysql2postgres/postgres_writer'
17
16
  require 'mysql2postgres/postgres_file_writer'
18
17
  require 'mysql2postgres/postgres_db_writer'
@@ -20,42 +19,76 @@ require 'mysql2postgres/postgres_db_writer'
20
19
  require 'debug' if ENV.fetch('ENABLE_DEBUG', nil) == '1'
21
20
 
22
21
  class Mysql2postgres
23
- attr_reader :options, :reader, :writer
22
+ attr_reader :options, :config_file, :reader, :writer
24
23
 
25
- def initialize(yaml)
24
+ def initialize(yaml, config_file = nil)
25
+ @config_file = config_file
26
26
  @options = build_options yaml
27
27
  end
28
28
 
29
- def build_options(yaml)
30
- yaml.transform_keys(&:to_sym).tap do |opts|
31
- opts[:mysql].transform_keys!(&:to_sym)
32
- opts[:destination].transform_keys!(&:to_sym)
33
- opts[:destination].each do |env, settings|
34
- opts[:destination][env] = settings.transform_keys(&:to_sym)
35
- end
36
- end
37
- end
29
+ def convert
30
+ @reader = MysqlReader.new options
31
+
32
+ puts "mysql2postgres #{Mysql2postgres::VERSION}"
33
+ puts "Config file: #{config_file}"
34
+ puts "Dumpfile: #{dump_file}"
35
+
36
+ @writer = if to_file?
37
+ puts 'Target: File'
38
+ PostgresFileWriter.new dump_file, options[:destination]
39
+ else
40
+ puts "Target: PostgreSQL DB (#{adapter})"
41
+ PostgresDbWriter.new dump_file, options[:destination]
42
+ end
38
43
 
39
- def send_file_to_postgres(path)
40
- connection = Connection.new options
41
- connection.load_file path
44
+ Converter.new(reader, writer, options).convert
45
+ File.delete dump_file if options[:remove_dump_file] && File.exist?(dump_file)
42
46
  end
43
47
 
44
- def convert
45
- @reader = MysqlReader.new options
48
+ private
46
49
 
47
- tag = Time.new.strftime '%Y%m%d-%H%M%S'
50
+ def adapter
51
+ if options[:destination][:adapter].nil? || options[:destination][:adapter].empty?
52
+ 'postgresql'
53
+ else
54
+ options[:destination][:adapter]
55
+ end
56
+ end
48
57
 
49
- path = './'
50
- path = options[:dump_file_directory] if options[:dump_file_directory]
58
+ def environment
59
+ if ENV['MYSQL2POSTGRES_ENV']
60
+ ENV['MYSQL2POSTGRES_ENV']
61
+ elsif ENV['RAILS_ENV']
62
+ ENV['RAILS_ENV']
63
+ else
64
+ 'development'
65
+ end
66
+ end
51
67
 
52
- filename = File.expand_path File.join(path, "output_#{tag}.sql")
53
- puts "Dumpfile: #{filename}"
68
+ def to_file?
69
+ adapter == 'file'
70
+ end
54
71
 
55
- @writer = PostgresDbWriter.new filename, options
72
+ def build_options(yaml)
73
+ yaml.transform_keys(&:to_sym).tap do |opts|
74
+ opts[:mysql].transform_keys!(&:to_sym)
56
75
 
57
- Converter.new(reader, writer, options).convert
76
+ destinations = opts.delete :destinations
77
+ opts[:destination] = destinations[environment]&.transform_keys(&:to_sym)
78
+
79
+ if opts[:destination].nil? || opts[:destination].empty?
80
+ raise "no configuration for environment '#{environment}' in destinations available. Use MYSQL2POSTGRES_ENV or RAILS_ENV."
81
+ end
82
+ end
83
+ end
58
84
 
59
- File.delete filename if options[:remove_dump_file] && File.exist?(filename)
85
+ def dump_file
86
+ @dump_file ||= if to_file? && options[:destination][:filename] && options[:destination][:filename] != ''
87
+ options[:destination][:filename]
88
+ else
89
+ tag = Time.new.strftime '%Y%m%d-%H%M%S'
90
+ path = options[:dump_file_directory] || './'
91
+ File.expand_path File.join(path, "output_#{tag}.sql")
92
+ end
60
93
  end
61
94
  end
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  lib = File.expand_path '../lib', __FILE__
4
- puts lib
5
4
  $LOAD_PATH.unshift lib unless $LOAD_PATH.include? lib
6
5
  require 'mysql2postgres/version'
7
6
 
@@ -50,31 +49,28 @@ Gem::Specification.new do |s|
50
49
  'lib/mysql2postgres/postgres_db_writer.rb',
51
50
  'lib/mysql2postgres/postgres_writer.rb',
52
51
  'lib/mysql2postgres/version.rb',
53
- 'lib/mysql2postgres/writer.rb',
54
52
  'mysql2postgres.gemspec',
55
53
  'test/fixtures/config_all_options.yml',
54
+ 'test/fixtures/config_min_options.yml',
55
+ 'test/fixtures/config_to_file.yml',
56
56
  'test/fixtures/seed_integration_tests.sql',
57
57
  'test/integration/convert_to_db_test.rb',
58
58
  'test/integration/convert_to_file_test.rb',
59
59
  'test/integration/converter_test.rb',
60
- 'test/integration/mysql_reader_base_test.rb',
60
+ 'test/integration/mysql_reader_connection_test.rb',
61
61
  'test/integration/mysql_reader_test.rb',
62
- 'test/integration/postgres_db_writer_base_test.rb',
62
+ 'test/integration/postgres_db_writer_test.rb',
63
+ 'test/units/mysql_test.rb',
63
64
  'test/units/option_test.rb',
64
65
  'test/units/postgres_file_writer_test.rb',
65
66
  'test/test_helper.rb'
66
67
  ]
67
- s.homepage = 'https://code.alphanodes.com/alphanodes/mysql2postgres'
68
+ s.homepage = 'https://github.com/AlphaNodes/mysql2postgres'
68
69
  s.rdoc_options = ['--charset=UTF-8']
69
70
  s.require_paths = ['lib']
70
71
  s.summary = 'MySQL to PostgreSQL Data Translation'
71
72
 
72
- s.add_dependency 'rake'
73
73
  s.add_runtime_dependency 'pg', '~> 1.2.2'
74
- s.add_runtime_dependency 'postgres-pr', '~> 0.7'
74
+ s.add_runtime_dependency 'rake'
75
75
  s.add_runtime_dependency 'ruby-mysql', '~> 3.0'
76
- s.add_development_dependency 'debug'
77
- s.add_development_dependency 'rubocop-minitest'
78
- s.add_development_dependency 'rubocop-performance'
79
- s.add_development_dependency 'test-unit', '~> 3.5.3'
80
76
  end
@@ -1,20 +1,21 @@
1
1
  mysql:
2
- hostname: localhost
2
+ hostname: 127.0.0.1
3
3
  port: 3306
4
- socket: /tmp/mysql.sock
5
- username: somename
6
- password: secretpassword
4
+ username: root
5
+ password: BestPasswordEver
7
6
  database: somename
7
+ encoding: utf8mb4
8
8
 
9
-
10
- destination:
11
- # if file is given, output goes to file, else postgres
12
- file: somefile
9
+ # if MYSQL2POSTGRES_ENV and RAILS_ENV is missing, development is used!
10
+ destinations:
11
+ development:
12
+ adapter: file
13
+ filename: /tmp/exported_file.sql
13
14
  test:
14
15
  hostname: localhost
15
16
  port: 5432
16
- username: somename
17
- password: secretpassword
17
+ username: postgres
18
+ password: postgres
18
19
  database: somename
19
20
 
20
21
  # if tables is given, only the listed tables will be converted. leave empty to convert all tables.
@@ -29,8 +30,10 @@ exclude_tables:
29
30
  - table5
30
31
  - table6
31
32
 
33
+ dump_file_directory: /tmp
34
+
32
35
  # if suppress_data is true, only the schema definition will be exported/migrated, and not the data
33
- suppress_data: true
36
+ suppress_data: false
34
37
 
35
38
  # if suppress_ddl is true, only the data will be exported/imported, and not the schema
36
39
  suppress_ddl: false
@@ -0,0 +1,16 @@
1
+ mysql:
2
+ hostname: localhost
3
+ username: root
4
+ password: BestPasswordEver
5
+ database: somename
6
+
7
+ # if MYSQL2POSTGRES_ENV and RAILS_ENV is missing, development is used!
8
+ destinations:
9
+ test:
10
+ hostname: localhost
11
+ port: 5432
12
+ username: somename
13
+ password: secretpassword
14
+ database: somename
15
+
16
+ # all options are false as default
@@ -0,0 +1,31 @@
1
+ mysql:
2
+ hostname: 127.0.0.1
3
+ port: 3306
4
+ username: root
5
+ password: BestPasswordEver
6
+ database: somename
7
+ encoding: utf8mb4
8
+
9
+ # if MYSQL2POSTGRES_ENV and RAILS_ENV is missing, development is used!
10
+ destinations:
11
+ test:
12
+ adapter: file
13
+ filename: /tmp/exported_file.sql
14
+
15
+ # if tables is given, only the listed tables will be converted. leave empty to convert all tables.
16
+ tables:
17
+ - table1
18
+ - table2
19
+ - table3
20
+ - table4
21
+
22
+ dump_file_directory: /tmp
23
+
24
+ # if suppress_data is true, only the schema definition will be exported/migrated, and not the data
25
+ suppress_data: false
26
+
27
+ # if suppress_ddl is true, only the data will be exported/imported, and not the schema
28
+ suppress_ddl: false
29
+
30
+ # if force_truncate is true, forces a table truncate before table loading
31
+ force_truncate: false
@@ -6,18 +6,25 @@ class ConvertToDbTest < Test::Unit::TestCase
6
6
  class << self
7
7
  def startup
8
8
  seed_test_database
9
- @options = get_test_config_by_label :localmysql_to_db_convert_all
10
- @mysql2postgres = Mysql2postgres.new @options
11
- @mysql2postgres.convert
12
- @mysql2postgres.writer.open
13
9
  end
10
+ end
14
11
 
15
- def shutdown
16
- @@mysql2postgres.writer.close
17
- end
12
+ def setup
13
+ @mysql2postgres = instance_from_file
14
+ @options = @mysql2postgres.options
15
+ @options[:force_truncate] = true
16
+ @options.delete :tables # convert all available tables
17
+
18
+ @mysql2postgres.convert
19
+ @mysql2postgres.writer.connection.open
20
+ end
21
+
22
+ def teardown
23
+ @mysql2postgres&.writer&.connection&.finish
18
24
  end
19
25
 
20
26
  def test_table_creation
21
- assert_true @mysql2postgres.writer.exists?('numeric_types_basics')
27
+ tables = @mysql2postgres.writer.connection.tables
28
+ assert tables.include?('numeric_types_basics')
22
29
  end
23
30
  end
@@ -3,18 +3,22 @@
3
3
  require File.expand_path '../test_helper', __dir__
4
4
 
5
5
  class ConvertToFileTest < Test::Unit::TestCase
6
+ attr_reader :content
7
+
6
8
  class << self
7
9
  def startup
8
- seed_test_database
9
- @options = get_test_config_by_label :localmysql_to_file_convert_all
10
- @mysql2postgres = Mysql2postgres.new @options
11
- @mysql2postgres.convert
12
- @content = File.read @mysql2postgres.options[:destfile]
10
+ seed_test_database option_file: 'config_to_file'
13
11
  end
14
12
  end
15
13
 
16
- def content
17
- @@content
14
+ def setup
15
+ @mysql2postgres = instance_from_file 'config_to_file'
16
+ @options = @mysql2postgres.options
17
+ @options[:force_truncate] = true
18
+ @options.delete :tables # convert all available tables
19
+
20
+ @mysql2postgres.convert
21
+ @content = File.read @mysql2postgres.options[:destination][:filename]
18
22
  end
19
23
 
20
24
  def test_table_creation
@@ -23,46 +27,57 @@ class ConvertToFileTest < Test::Unit::TestCase
23
27
  end
24
28
 
25
29
  def test_basic_numerics_tinyint
26
- assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_tinyint" smallint,.*\)', Regexp::MULTILINE).match(content)
30
+ assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_tinyint" smallint,.*\)', Regexp::MULTILINE)
31
+ .match(content)
27
32
  end
28
33
 
29
34
  def test_basic_numerics_smallint
30
- assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_smallint" integer,.*\)', Regexp::MULTILINE).match(content)
35
+ assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_smallint" integer,.*\)', Regexp::MULTILINE)
36
+ .match(content)
31
37
  end
32
38
 
33
39
  def test_basic_numerics_mediumint
34
- assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_mediumint" integer,.*\)', Regexp::MULTILINE).match(content)
40
+ assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_mediumint" integer,.*\)', Regexp::MULTILINE)
41
+ .match(content)
35
42
  end
36
43
 
37
44
  def test_basic_numerics_int
38
- assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_int" integer,.*\)', Regexp::MULTILINE).match(content)
45
+ assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_int" integer,.*\)', Regexp::MULTILINE)
46
+ .match(content)
39
47
  end
40
48
 
41
49
  def test_basic_numerics_integer
42
- assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_integer" integer,.*\)', Regexp::MULTILINE).match(content)
50
+ assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_integer" integer,.*\)', Regexp::MULTILINE)
51
+ .match(content)
43
52
  end
44
53
 
45
54
  def test_basic_numerics_bigint
46
- assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_bigint" bigint,.*\)', Regexp::MULTILINE).match(content)
55
+ assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_bigint" bigint,.*\)', Regexp::MULTILINE)
56
+ .match(content)
47
57
  end
48
58
 
49
59
  def test_basic_numerics_real
50
- assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_real" double precision,.*\)', Regexp::MULTILINE).match(content)
60
+ assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_real" double precision,.*\)', Regexp::MULTILINE)
61
+ .match(content)
51
62
  end
52
63
 
53
64
  def test_basic_numerics_double
54
- assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_double" double precision,.*\)', Regexp::MULTILINE).match(content)
65
+ assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_double" double precision,.*\)', Regexp::MULTILINE)
66
+ .match(content)
55
67
  end
56
68
 
57
69
  def test_basic_numerics_float
58
- assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_float" double precision,.*\)', Regexp::MULTILINE).match(content)
70
+ assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_float" double precision,.*\)', Regexp::MULTILINE)
71
+ .match(content)
59
72
  end
60
73
 
61
74
  def test_basic_numerics_decimal
62
- assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_decimal" numeric\(10, 0\),.*\)', Regexp::MULTILINE).match(content)
75
+ assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_decimal" numeric\(10, 0\),.*\)', Regexp::MULTILINE)
76
+ .match(content)
63
77
  end
64
78
 
65
79
  def test_basic_numerics_numeric
66
- assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_numeric" numeric\(10, 0\)[\w\n]*\)', Regexp::MULTILINE).match(content)
80
+ assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_numeric" numeric\(10, 0\)[\w\n]*\)', Regexp::MULTILINE)
81
+ .match(content)
67
82
  end
68
83
  end
@@ -5,15 +5,22 @@ require File.expand_path '../test_helper', __dir__
5
5
  class ConverterTest < Test::Unit::TestCase
6
6
  class << self
7
7
  def startup
8
- seed_test_database
9
- @options = get_test_config_by_label :localmysql_to_file_convert_nothing
8
+ seed_test_database option_file: 'config_to_file'
10
9
  end
11
10
  end
12
11
 
12
+ def setup
13
+ @options = options_from_file 'config_to_file'
14
+ @options[:suppress_data] = true
15
+ @options[:suppress_ddl] = true
16
+
17
+ @destfile = get_temp_file 'mysql2postgres_test'
18
+ end
19
+
13
20
  def test_new_converter
14
21
  assert_nothing_raised do
15
22
  reader = get_test_reader @options
16
- writer = get_test_file_writer @options
23
+ writer = Mysql2postgres::PostgresFileWriter.new @destfile, @options[:destination]
17
24
  converter = Mysql2postgres::Converter.new reader, writer, @options
18
25
  assert_equal 0, converter.convert
19
26
  end
@@ -2,23 +2,26 @@
2
2
 
3
3
  require File.expand_path '../test_helper', __dir__
4
4
 
5
- class MysqlReaderBaseTest < Test::Unit::TestCase
5
+ class MysqlReaderConnectionTest < Test::Unit::TestCase
6
6
  class << self
7
7
  def startup
8
- seed_test_database
9
- @options = get_test_config_by_label :localmysql_to_file_convert_nothing
8
+ seed_test_database option_file: 'config_to_file'
10
9
  end
11
10
  end
12
11
 
12
+ def setup
13
+ @options = options_from_file 'config_to_file'
14
+ end
15
+
13
16
  def test_mysql_connection
14
17
  assert_nothing_raised do
15
- mysql2postgres::MysqlReader.new @options
18
+ Mysql2postgres::MysqlReader.new @options
16
19
  end
17
20
  end
18
21
 
19
22
  def test_mysql_reconnect
20
23
  assert_nothing_raised do
21
- reader = mysql2postgres::MysqlReader.new @options
24
+ reader = Mysql2postgres::MysqlReader.new @options
22
25
  reader.reconnect
23
26
  end
24
27
  end
@@ -27,7 +30,7 @@ class MysqlReaderBaseTest < Test::Unit::TestCase
27
30
  assert_nothing_raised do
28
31
  @options[:mysql][:port] = ''
29
32
  @options[:mysql][:socket] = ''
30
- mysql2postgres::MysqlReader.new @options
33
+ Mysql2postgres::MysqlReader.new @options
31
34
  end
32
35
  end
33
36
  end
@@ -5,12 +5,15 @@ require File.expand_path '../test_helper', __dir__
5
5
  class MysqlReaderTest < Test::Unit::TestCase
6
6
  class << self
7
7
  def startup
8
- seed_test_database
9
- @options = get_test_config_by_label :localmysql_to_file_convert_nothing
10
- @reader = get_test_reader @options
8
+ seed_test_database option_file: 'config_to_file'
11
9
  end
12
10
  end
13
11
 
12
+ def setup
13
+ @options = options_from_file 'config_to_file'
14
+ @reader = get_test_reader @options
15
+ end
16
+
14
17
  def test_db_connection
15
18
  assert_nothing_raised do
16
19
  @reader.mysql.ping
@@ -26,7 +29,7 @@ class MysqlReaderTest < Test::Unit::TestCase
26
29
  def test_paginated_read
27
30
  expected_rows = 3
28
31
  page_size = 2
29
- expected_pages = (1.0 * expected_rows / page_size).ceil
32
+ # expected_pages = (1.0 * expected_rows / page_size).ceil
30
33
 
31
34
  row_count = my_row_count = 0
32
35
  table = @reader.tables.find { |t| t.name == 'numeric_types_basics' }
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path '../test_helper', __dir__
4
+
5
+ class PostgresDbWriterTest < Test::Unit::TestCase
6
+ class << self
7
+ def startup
8
+ seed_test_database
9
+ end
10
+ end
11
+
12
+ def setup
13
+ @options = options_from_file
14
+ @options[:suppress_data] = true
15
+ @options[:suppress_ddl] = true
16
+ end
17
+
18
+ def test_pg_connection
19
+ assert_nothing_raised do
20
+ Mysql2postgres::PostgresDbWriter.new Tempfile.new('mysql2postgres_test_').path,
21
+ @options[:destination]
22
+ end
23
+ end
24
+ end
data/test/test_helper.rb CHANGED
@@ -4,47 +4,37 @@ require 'rubygems'
4
4
  require 'test/unit'
5
5
  require 'debug' if ENV.fetch('ENABLE_DEBUG', nil) == '1'
6
6
 
7
- require File.expand_path('../lib/mysql2postgres/version', __dir__)
8
- require File.expand_path('../lib/mysql2postgres/converter', __dir__)
9
- require File.expand_path('../lib/mysql2postgres/mysql_reader', __dir__)
10
- require File.expand_path('../lib/mysql2postgres/writer', __dir__)
11
- require File.expand_path('../lib/mysql2postgres/postgres_writer', __dir__)
12
- require File.expand_path('../lib/mysql2postgres/postgres_file_writer', __dir__)
13
- require File.expand_path('../lib/mysql2postgres/postgres_db_writer', __dir__)
7
+ require File.expand_path('lib/mysql2postgres')
14
8
 
15
- def seed_test_database
16
- options = get_test_config_by_label :localmysql_to_file_convert_nothing
17
- seedfilepath = "#{__dir__}/../fixtures/seed_integration_tests.sql"
18
- rc = system "mysql -u#{options[:mysql][:username]} #{options[:mysql][:database]} < #{seedfilepath}"
19
- raise StandardError unless rc
9
+ def load_yaml_file(file = 'config_all_options')
10
+ YAML.load_file "#{__dir__}/fixtures/#{file}.yml"
11
+ end
20
12
 
21
- true
22
- rescue StandardError
23
- raise 'Failed to seed integration test db. See README for setup requirements.'
13
+ def instance_from_file(file = 'config_all_options')
14
+ Mysql2postgres.new load_yaml_file(file)
24
15
  end
25
16
 
26
- def get_test_reader(options)
27
- require 'mysql2postgres/mysql_reader'
28
- mysql2postgres::MysqlReader.new options
29
- rescue StandardError
30
- raise 'Failed to initialize integration test db. See README for setup requirements.'
17
+ def options_from_file(file = 'config_all_options')
18
+ instance_from_file(file).options
31
19
  end
32
20
 
33
- def get_test_file_writer(options)
34
- require 'mysql2postgres/postgres_file_writer'
35
- mysql2postgres::PostgresFileWriter.new options[:destfile]
36
- rescue StandardError => e
37
- puts e.inspect
38
- raise "Failed to initialize file writer from #{options.inspect}. See README for setup requirements."
21
+ def seed_test_database(option_file: 'config_all_options', sql_file: 'seed_integration_tests.sql')
22
+ options = options_from_file option_file
23
+ seedfilepath = File.expand_path "test/fixtures/#{sql_file}"
24
+ system 'mysql ' \
25
+ "--host #{options[:mysql][:hostname]} " \
26
+ "--port #{options[:mysql][:port]} " \
27
+ "-u#{options[:mysql][:username]} " \
28
+ "-p#{options[:mysql][:password]} " \
29
+ "#{options[:mysql][:database]} < #{seedfilepath}", exception: true
30
+ rescue StandardError
31
+ raise 'Failed to seed integration test db. See README for setup requirements.'
39
32
  end
40
33
 
41
- def get_test_converter(options)
42
- require 'mysql2postgres/converter'
43
- reader = get_test_reader options
44
- writer = get_test_file_writer options
45
- mysql2postgres::Converter.new reader, writer, options
34
+ def get_test_reader(options)
35
+ Mysql2postgres::MysqlReader.new options
46
36
  rescue StandardError
47
- raise "Failed to initialize converter from #{options.inspect}. See README for setup requirements."
37
+ raise 'Failed to initialize integration test db. See README for setup requirements.'
48
38
  end
49
39
 
50
40
  def get_temp_file(basename)
@@ -54,38 +44,3 @@ def get_temp_file(basename)
54
44
  f.close!
55
45
  path
56
46
  end
57
-
58
- def get_new_test_config(include_tables: [], exclude_tables: [], to_file: false,
59
- suppress_data: false, suppress_ddl: false, force_truncate: false)
60
-
61
- to_filename = to_file ? get_temp_file(['mysql2postgres_tmp_output_', '.yml']) : nil
62
- configtext = Mysql2postgres::Config.template to_filename, include_tables, exclude_tables, suppress_data, suppress_ddl, force_truncate
63
- configfile = get_temp_file 'mysql2postgres_tmp_config'
64
- File.open(configfile, 'w:UTF-8') { |f| f.write(configtext) }
65
- yaml = YAML.load_file configfile
66
- Mysql2postgres::ConfigBase.new yaml
67
- rescue StandardError
68
- raise "Failed to initialize options from #{configfile}. See README for setup requirements."
69
- end
70
-
71
- def get_test_config_by_label(name)
72
- case name
73
- when :localmysql_to_file_convert_nothing
74
- get_new_test_config to_file: true,
75
- tables: ['unobtainium'],
76
- exclude_tables: ['kryptonite'],
77
- suppress_data: true,
78
- suppress_ddl: true
79
- when :localmysql_to_file_convert_all
80
- get_new_test_config to_file: true
81
- when :localmysql_to_db_convert_all
82
- get_new_test_config
83
- when :localmysql_to_db_convert_nothing
84
- get_new_test_config tables: ['unobtainium'],
85
- exclude_tables: ['kryptonite'],
86
- suppress_data: true,
87
- suppress_ddl: true
88
- else
89
- raise "Invalid label: #{name}"
90
- end
91
- end
@@ -0,0 +1,10 @@
1
+ # frozen_string_literal: true
2
+
3
+ require File.expand_path '../test_helper', __dir__
4
+
5
+ class MysqlTest < Test::Unit::TestCase
6
+ def test_mysql_charset
7
+ charset = ::Mysql::Charset.by_number 192
8
+ assert_equal 'utf8mb3', charset.name
9
+ end
10
+ end
@@ -4,14 +4,11 @@ require File.expand_path '../test_helper', __dir__
4
4
  require 'yaml'
5
5
 
6
6
  class SettingTest < Test::Unit::TestCase
7
- attr_reader :config_all_opts
8
-
9
- def setup
10
- @config_all_opts = YAML.load_file "#{__dir__}/../fixtures/config_all_options.yml"
11
- end
12
-
13
7
  def test_options_loaded
14
- instance = Mysql2postgres.new @config_all_opts
15
- assert_not_nil instance.options
8
+ options = options_from_file
9
+
10
+ assert_equal false, options[:suppress_data]
11
+ assert_equal 'postgres', options[:destination][:username]
12
+ assert_equal 'somename', options[:destination][:database]
16
13
  end
17
14
  end
@@ -15,10 +15,12 @@ class PostgresFileWriterTest < Test::Unit::TestCase
15
15
  File.delete destfile
16
16
  end
17
17
 
18
- def test_basic_write
19
- writer = Mysql2postgres::PostgresFileWriter.new destfile
18
+ def test_file_writer
19
+ destination = { filename: '/tmp/test.sql' }
20
+ writer = Mysql2postgres::PostgresFileWriter.new @destfile, destination
20
21
  writer.close
21
22
  content = File.read destfile
23
+
22
24
  assert_not_nil content.match("SET client_encoding = 'UTF8'")
23
25
  assert_nil content.match('unobtanium')
24
26
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: mysql2postgres
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.3
4
+ version: 0.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Max Lapshin <max@maxidoors.ru>
@@ -24,22 +24,8 @@ authors:
24
24
  autorequire:
25
25
  bindir: bin
26
26
  cert_chain: []
27
- date: 2022-07-29 00:00:00.000000000 Z
27
+ date: 2022-07-31 00:00:00.000000000 Z
28
28
  dependencies:
29
- - !ruby/object:Gem::Dependency
30
- name: rake
31
- requirement: !ruby/object:Gem::Requirement
32
- requirements:
33
- - - ">="
34
- - !ruby/object:Gem::Version
35
- version: '0'
36
- type: :runtime
37
- prerelease: false
38
- version_requirements: !ruby/object:Gem::Requirement
39
- requirements:
40
- - - ">="
41
- - !ruby/object:Gem::Version
42
- version: '0'
43
29
  - !ruby/object:Gem::Dependency
44
30
  name: pg
45
31
  requirement: !ruby/object:Gem::Requirement
@@ -55,19 +41,19 @@ dependencies:
55
41
  - !ruby/object:Gem::Version
56
42
  version: 1.2.2
57
43
  - !ruby/object:Gem::Dependency
58
- name: postgres-pr
44
+ name: rake
59
45
  requirement: !ruby/object:Gem::Requirement
60
46
  requirements:
61
- - - "~>"
47
+ - - ">="
62
48
  - !ruby/object:Gem::Version
63
- version: '0.7'
49
+ version: '0'
64
50
  type: :runtime
65
51
  prerelease: false
66
52
  version_requirements: !ruby/object:Gem::Requirement
67
53
  requirements:
68
- - - "~>"
54
+ - - ">="
69
55
  - !ruby/object:Gem::Version
70
- version: '0.7'
56
+ version: '0'
71
57
  - !ruby/object:Gem::Dependency
72
58
  name: ruby-mysql
73
59
  requirement: !ruby/object:Gem::Requirement
@@ -82,62 +68,6 @@ dependencies:
82
68
  - - "~>"
83
69
  - !ruby/object:Gem::Version
84
70
  version: '3.0'
85
- - !ruby/object:Gem::Dependency
86
- name: debug
87
- requirement: !ruby/object:Gem::Requirement
88
- requirements:
89
- - - ">="
90
- - !ruby/object:Gem::Version
91
- version: '0'
92
- type: :development
93
- prerelease: false
94
- version_requirements: !ruby/object:Gem::Requirement
95
- requirements:
96
- - - ">="
97
- - !ruby/object:Gem::Version
98
- version: '0'
99
- - !ruby/object:Gem::Dependency
100
- name: rubocop-minitest
101
- requirement: !ruby/object:Gem::Requirement
102
- requirements:
103
- - - ">="
104
- - !ruby/object:Gem::Version
105
- version: '0'
106
- type: :development
107
- prerelease: false
108
- version_requirements: !ruby/object:Gem::Requirement
109
- requirements:
110
- - - ">="
111
- - !ruby/object:Gem::Version
112
- version: '0'
113
- - !ruby/object:Gem::Dependency
114
- name: rubocop-performance
115
- requirement: !ruby/object:Gem::Requirement
116
- requirements:
117
- - - ">="
118
- - !ruby/object:Gem::Version
119
- version: '0'
120
- type: :development
121
- prerelease: false
122
- version_requirements: !ruby/object:Gem::Requirement
123
- requirements:
124
- - - ">="
125
- - !ruby/object:Gem::Version
126
- version: '0'
127
- - !ruby/object:Gem::Dependency
128
- name: test-unit
129
- requirement: !ruby/object:Gem::Requirement
130
- requirements:
131
- - - "~>"
132
- - !ruby/object:Gem::Version
133
- version: 3.5.3
134
- type: :development
135
- prerelease: false
136
- version_requirements: !ruby/object:Gem::Requirement
137
- requirements:
138
- - - "~>"
139
- - !ruby/object:Gem::Version
140
- version: 3.5.3
141
71
  description: Translates MySQL -> PostgreSQL
142
72
  email: a.meindl@alphanodes.com
143
73
  executables:
@@ -158,20 +88,22 @@ files:
158
88
  - lib/mysql2postgres/postgres_file_writer.rb
159
89
  - lib/mysql2postgres/postgres_writer.rb
160
90
  - lib/mysql2postgres/version.rb
161
- - lib/mysql2postgres/writer.rb
162
91
  - mysql2postgres.gemspec
163
92
  - test/fixtures/config_all_options.yml
93
+ - test/fixtures/config_min_options.yml
94
+ - test/fixtures/config_to_file.yml
164
95
  - test/fixtures/seed_integration_tests.sql
165
96
  - test/integration/convert_to_db_test.rb
166
97
  - test/integration/convert_to_file_test.rb
167
98
  - test/integration/converter_test.rb
168
- - test/integration/mysql_reader_base_test.rb
99
+ - test/integration/mysql_reader_connection_test.rb
169
100
  - test/integration/mysql_reader_test.rb
170
- - test/integration/postgres_db_writer_base_test.rb
101
+ - test/integration/postgres_db_writer_test.rb
171
102
  - test/test_helper.rb
103
+ - test/units/mysql_test.rb
172
104
  - test/units/option_test.rb
173
105
  - test/units/postgres_file_writer_test.rb
174
- homepage: https://code.alphanodes.com/alphanodes/mysql2postgres
106
+ homepage: https://github.com/AlphaNodes/mysql2postgres
175
107
  licenses:
176
108
  - MIT
177
109
  metadata:
@@ -1,9 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- class Mysql2postgres
4
- class Writer
5
- def inload
6
- raise "Method 'inload' needs to be overridden..."
7
- end
8
- end
9
- end
@@ -1,18 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require File.expand_path '../test_helper', __dir__
4
-
5
- class PostgresDbWriterBaseTest < Test::Unit::TestCase
6
- class << self
7
- def startup
8
- seed_test_database
9
- @options = get_test_config_by_label :localmysql_to_db_convert_nothing
10
- end
11
- end
12
-
13
- def test_pg_connection
14
- assert_nothing_raised do
15
- mysql2postgres::PostgresDbWriter.new Tempfile.new('mysql2postgres_test_').path, @options
16
- end
17
- end
18
- end