mysql2postgres 0.3.3 → 0.4.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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