xmysql2psql 0.2.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.
@@ -0,0 +1,183 @@
1
+ require 'pg'
2
+
3
+ require 'xmysql2psql/postgres_writer'
4
+
5
+ class Xmysql2psql
6
+
7
+ class PostgresDbWriter < PostgresWriter
8
+ attr_reader :conn, :hostname, :login, :password, :database, :schema, :port
9
+
10
+ def db_writer?
11
+ true
12
+ end
13
+
14
+ def initialize(options)
15
+ @hostname, @login, @password, @database, @port =
16
+ options.pghostname('localhost'), options.pgusername,
17
+ options.pgpassword, options.pgdatabase, options.pgport(5432).to_s
18
+ @database, @schema = database.split(":")
19
+ open
20
+ end
21
+
22
+ def open
23
+ @conn = PGconn.new(hostname, port, '', '', database, login, password)
24
+ @conn.exec("SET search_path TO #{PGconn.quote_ident(schema)}") if schema
25
+ @conn.exec("SET client_encoding = 'UTF8'")
26
+ @conn.exec("SET standard_conforming_strings = off") if @conn.server_version >= 80200
27
+ @conn.exec("SET check_function_bodies = false")
28
+ @conn.exec("SET client_min_messages = warning")
29
+ end
30
+
31
+ def close
32
+ @conn.close
33
+ end
34
+
35
+ def exists?(relname)
36
+ rc = @conn.exec("SELECT COUNT(*) FROM pg_class WHERE relname = '#{relname}'")
37
+ (!rc.nil?) && (rc.to_a.length==1) && (rc.first.count.to_i==1)
38
+ end
39
+
40
+ def write_table(table)
41
+ puts "Creating table #{table.name}..."
42
+ primary_keys = []
43
+ serial_key = nil
44
+ maxval = nil
45
+
46
+ columns = table.columns.map do |column|
47
+ if column[:auto_increment]
48
+ serial_key = column[:name]
49
+ maxval = column[:maxval].to_i < 1 ? 1 : column[:maxval] + 1
50
+ end
51
+ if column[:primary_key]
52
+ primary_keys << column[:name]
53
+ end
54
+ " " + column_description(column)
55
+ end.join(",\n")
56
+
57
+ if serial_key
58
+ if @conn.server_version < 80200
59
+ serial_key_seq = "#{table.name}_#{serial_key}_seq"
60
+ @conn.exec("DROP SEQUENCE #{serial_key_seq} CASCADE") if exists?(serial_key_seq)
61
+ else
62
+ @conn.exec("DROP SEQUENCE IF EXISTS #{table.name}_#{serial_key}_seq CASCADE")
63
+ end
64
+ @conn.exec <<-EOF
65
+ CREATE SEQUENCE #{table.name}_#{serial_key}_seq
66
+ INCREMENT BY 1
67
+ NO MAXVALUE
68
+ NO MINVALUE
69
+ CACHE 1
70
+ EOF
71
+
72
+ @conn.exec "SELECT pg_catalog.setval('#{table.name}_#{serial_key}_seq', #{maxval}, true)"
73
+ end
74
+
75
+ if @conn.server_version < 80200
76
+ @conn.exec "DROP TABLE #{PGconn.quote_ident(table.name)} CASCADE;" if exists?(table.name)
77
+ else
78
+ @conn.exec "DROP TABLE IF EXISTS #{PGconn.quote_ident(table.name)} CASCADE;"
79
+ end
80
+ create_sql = "CREATE TABLE #{PGconn.quote_ident(table.name)} (\n" + columns + "\n)\nWITHOUT OIDS;"
81
+ begin
82
+ @conn.exec(create_sql)
83
+ rescue Exception => e
84
+ puts "Error: \n#{create_sql}"
85
+ raise
86
+ end
87
+ puts "Created table #{table.name}"
88
+
89
+ end
90
+
91
+ def write_indexes(table)
92
+ puts "Indexing table #{table.name}..."
93
+ if primary_index = table.indexes.find {|index| index[:primary]}
94
+ @conn.exec("ALTER TABLE #{PGconn.quote_ident(table.name)} ADD CONSTRAINT \"#{table.name}_pkey\" PRIMARY KEY(#{primary_index[:columns].map {|col| PGconn.quote_ident(col)}.join(", ")})")
95
+ end
96
+
97
+ table.indexes.each do |index|
98
+ next if index[:primary]
99
+ unique = index[:unique] ? "UNIQUE " : nil
100
+
101
+ #MySQL allows an index name which could be equal to a table name, Postgres doesn't
102
+ indexname = index[:name]
103
+ if indexname.eql?(table.name)
104
+ indexnamenew = "#{indexname}_index"
105
+ puts "WARNING: index \"#{indexname}\" equals table name. This is not allowed by postgres and will be renamed to \"#{indexnamenew}\""
106
+ indexname = indexnamenew
107
+ end
108
+
109
+ if @conn.server_version < 80200
110
+ @conn.exec("DROP INDEX #{PGconn.quote_ident(indexname)} CASCADE;") if exists?(indexname)
111
+ else
112
+ @conn.exec("DROP INDEX IF EXISTS #{PGconn.quote_ident(indexname)} CASCADE;")
113
+ end
114
+ @conn.exec("CREATE #{unique}INDEX #{PGconn.quote_ident(indexname)} ON #{PGconn.quote_ident(table.name)} (#{index[:columns].map {|col| PGconn.quote_ident(col)}.join(", ")});")
115
+ end
116
+
117
+
118
+ #@conn.exec("VACUUM FULL ANALYZE #{PGconn.quote_ident(table.name)}")
119
+ puts "Indexed table #{table.name}"
120
+ rescue Exception => e
121
+ puts "Couldn't create indexes on #{table} (#{table.indexes.inspect})"
122
+ puts e
123
+ puts e.backtrace[0,3].join("\n")
124
+ end
125
+
126
+ def write_constraints(table)
127
+ table.foreign_keys.each do |key|
128
+ key_sql = "ALTER TABLE #{PGconn.quote_ident(table.name)} ADD FOREIGN KEY (#{PGconn.quote_ident(key[:column])}) REFERENCES #{PGconn.quote_ident(key[:ref_table])}(#{PGconn.quote_ident(key[:ref_column])})"
129
+ begin
130
+ @conn.exec(key_sql)
131
+ rescue Exception => e
132
+ puts "Error: \n#{key_sql}\n#{e}"
133
+ end
134
+ end
135
+ end
136
+
137
+ def format_eta (t)
138
+ t = t.to_i
139
+ sec = t % 60
140
+ min = (t / 60) % 60
141
+ hour = t / 3600
142
+ sprintf("%02dh:%02dm:%02ds", hour, min, sec)
143
+ end
144
+
145
+ def write_contents(table, reader)
146
+ _time1 = Time.now
147
+ copy_line = "COPY #{PGconn.quote_ident(table.name)} (#{table.columns.map {|column| PGconn.quote_ident(column[:name])}.join(", ")}) FROM stdin;"
148
+ @conn.exec(copy_line)
149
+ puts "Counting rows of #{table.name}... "
150
+ STDOUT.flush
151
+ rowcount = table.count_rows
152
+ puts "Rows counted"
153
+ puts "Loading #{table.name}..."
154
+ STDOUT.flush
155
+ _counter = reader.paginated_read(table, 1000) do |row, counter|
156
+ line = []
157
+ process_row(table, row)
158
+ @conn.put_copy_data(row.join("\t") + "\n")
159
+
160
+ if counter != 0 && counter % 20000 == 0
161
+ elapsedTime = Time.now - _time1
162
+ eta = elapsedTime * rowcount / counter - elapsedTime
163
+ etaf = self.format_eta(eta)
164
+ etatimef = (Time.now + eta).strftime("%Y/%m/%d %H:%M")
165
+ printf "\r#{counter} of #{rowcount} rows loaded. [ETA: #{etatimef} (#{etaf})]"
166
+ STDOUT.flush
167
+ end
168
+
169
+ if counter % 5000 == 0
170
+ @conn.put_copy_end
171
+ @conn.exec(copy_line)
172
+ end
173
+
174
+ end
175
+ _time2 = Time.now
176
+ puts "\n#{_counter} rows loaded in #{((_time2 - _time1) / 60).round}min #{((_time2 - _time1) % 60).round}s"
177
+ # @conn.putline(".\n")
178
+ @conn.put_copy_end
179
+ end
180
+
181
+ end
182
+
183
+ end
@@ -0,0 +1,146 @@
1
+ require 'xmysql2psql/postgres_writer'
2
+
3
+ class Xmysql2psql
4
+
5
+ class PostgresFileWriter < PostgresWriter
6
+ def initialize(file)
7
+ @f = File.open(file, "w+")
8
+ @f << <<-EOF
9
+ -- MySQL 2 PostgreSQL dump\n
10
+ SET client_encoding = 'UTF8';
11
+ SET standard_conforming_strings = off;
12
+ SET check_function_bodies = false;
13
+ SET client_min_messages = warning;
14
+
15
+ EOF
16
+ end
17
+
18
+ def db_writer?
19
+ false
20
+ end
21
+
22
+ def truncate(table)
23
+ serial_key = nil
24
+ maxval = nil
25
+
26
+ table.columns.map do |column|
27
+ if column[:auto_increment]
28
+ serial_key = column[:name]
29
+ maxval = column[:maxval].to_i < 1 ? 1 : column[:maxval] + 1
30
+ end
31
+ end
32
+
33
+ @f << <<-EOF
34
+ -- TRUNCATE #{table.name};
35
+ TRUNCATE #{PGconn.quote_ident(table.name)} CASCADE;
36
+
37
+ EOF
38
+ if serial_key
39
+ @f << <<-EOF
40
+ SELECT pg_catalog.setval(pg_get_serial_sequence('#{table.name}', '#{serial_key}'), #{maxval}, true);
41
+ EOF
42
+ end
43
+ end
44
+
45
+ def write_table(table)
46
+ primary_keys = []
47
+ serial_key = nil
48
+ maxval = nil
49
+
50
+ columns = table.columns.map do |column|
51
+ if column[:auto_increment]
52
+ serial_key = column[:name]
53
+ maxval = column[:maxval].to_i < 1 ? 1 : column[:maxval] + 1
54
+ end
55
+ if column[:primary_key]
56
+ primary_keys << column[:name]
57
+ end
58
+ " " + column_description(column)
59
+ end.join(",\n")
60
+
61
+ if serial_key
62
+
63
+ @f << <<-EOF
64
+ --
65
+ -- Name: #{table.name}_#{serial_key}_seq; Type: SEQUENCE; Schema: public
66
+ --
67
+
68
+ DROP SEQUENCE IF EXISTS #{table.name}_#{serial_key}_seq CASCADE;
69
+
70
+ CREATE SEQUENCE #{table.name}_#{serial_key}_seq
71
+ INCREMENT BY 1
72
+ NO MAXVALUE
73
+ NO MINVALUE
74
+ CACHE 1;
75
+
76
+
77
+ SELECT pg_catalog.setval('#{table.name}_#{serial_key}_seq', #{maxval}, true);
78
+
79
+ EOF
80
+ end
81
+
82
+ @f << <<-EOF
83
+ -- Table: #{table.name}
84
+
85
+ -- DROP TABLE #{table.name};
86
+ DROP TABLE IF EXISTS #{PGconn.quote_ident(table.name)} CASCADE;
87
+
88
+ CREATE TABLE #{PGconn.quote_ident(table.name)} (
89
+ EOF
90
+
91
+ @f << columns
92
+
93
+ if primary_index = table.indexes.find {|index| index[:primary]}
94
+ @f << ",\n CONSTRAINT #{table.name}_pkey PRIMARY KEY(#{primary_index[:columns].map {|col| PGconn.quote_ident(col)}.join(", ")})"
95
+ end
96
+
97
+ @f << <<-EOF
98
+ \n)
99
+ WITHOUT OIDS;
100
+ EOF
101
+
102
+ table.indexes.each do |index|
103
+ next if index[:primary]
104
+ unique = index[:unique] ? "UNIQUE " : nil
105
+ @f << <<-EOF
106
+ DROP INDEX IF EXISTS #{PGconn.quote_ident(index[:name])} CASCADE;
107
+ CREATE #{unique}INDEX #{PGconn.quote_ident(index[:name])} ON #{PGconn.quote_ident(table.name)} (#{index[:columns].map {|col| PGconn.quote_ident(col)}.join(", ")});
108
+ EOF
109
+ end
110
+
111
+ end
112
+
113
+ def write_indexes(table)
114
+ end
115
+
116
+ def write_constraints(table)
117
+ table.foreign_keys.each do |key|
118
+ @f << "ALTER TABLE #{PGconn.quote_ident(table.name)} ADD FOREIGN KEY (#{PGconn.quote_ident(key[:column])}) REFERENCES #{PGconn.quote_ident(key[:ref_table])}(#{PGconn.quote_ident(key[:ref_column])});\n"
119
+ end
120
+ end
121
+
122
+
123
+ def write_contents(table, reader)
124
+ @f << <<-EOF
125
+ --
126
+ -- Data for Name: #{table.name}; Type: TABLE DATA; Schema: public
127
+ --
128
+
129
+ COPY "#{table.name}" (#{table.columns.map {|column| PGconn.quote_ident(column[:name])}.join(", ")}) FROM stdin;
130
+ EOF
131
+
132
+ reader.paginated_read(table, 1000) do |row, counter|
133
+ line = []
134
+ process_row(table, row)
135
+ @f << row.join("\t") + "\n"
136
+ end
137
+ @f << "\\.\n\n"
138
+ #@f << "VACUUM FULL ANALYZE #{PGconn.quote_ident(table.name)};\n\n"
139
+ end
140
+
141
+ def close
142
+ @f.close
143
+ end
144
+ end
145
+
146
+ end
@@ -0,0 +1,154 @@
1
+ require 'pg'
2
+
3
+ require 'xmysql2psql/writer'
4
+
5
+ class Xmysql2psql
6
+
7
+ class PostgresWriter < Writer
8
+ def db_writer?
9
+ raise StandardError.new("not implemented")
10
+ end
11
+
12
+ def escape_bytea(value)
13
+ if db_writer?
14
+ self.conn.escape_bytea(value)
15
+ else
16
+ PGConn.escape_bytea(value)
17
+ end
18
+ end
19
+
20
+ def column_description(column)
21
+ "#{PGconn.quote_ident(column[:name])} #{column_type_info(column)}"
22
+ end
23
+
24
+ def column_type(column)
25
+ column_type_info(column).split(" ").first
26
+ end
27
+
28
+ def column_type_info(column)
29
+ if column[:auto_increment]
30
+ return "integer DEFAULT nextval('#{column[:table_name]}_#{column[:name]}_seq'::regclass) NOT NULL"
31
+ end
32
+
33
+ default = column[:default] ? " DEFAULT #{column[:default] == nil ? 'NULL' : "'"+PGconn.escape(column[:default])+"'"}" : nil
34
+ null = column[:null] ? "" : " NOT NULL"
35
+ type =
36
+ case column[:type]
37
+
38
+ # String types
39
+ when "char"
40
+ default = default + "::char" if default
41
+ "character(#{column[:length]})"
42
+ when "varchar"
43
+ default = default + "::character varying" if default
44
+ "character varying(#{column[:length]})"
45
+
46
+ # Integer and numeric types
47
+ when "integer"
48
+ default = " DEFAULT #{column[:default].nil? ? 'NULL' : column[:default].to_i}" if default
49
+ "integer"
50
+ when "bigint"
51
+ default = " DEFAULT #{column[:default].nil? ? 'NULL' : column[:default].to_i}" if default
52
+ "bigint"
53
+ when "tinyint"
54
+ default = " DEFAULT #{column[:default].nil? ? 'NULL' : column[:default].to_i}" if default
55
+ "smallint"
56
+
57
+ when "boolean"
58
+ default = " DEFAULT #{column[:default].to_i == 1 ? 'true' : 'false'}" if default
59
+ "boolean"
60
+ when "float"
61
+ default = " DEFAULT #{column[:default].nil? ? 'NULL' : column[:default].to_f}" if default
62
+ "real"
63
+ when "float unsigned"
64
+ default = " DEFAULT #{column[:default].nil? ? 'NULL' : column[:default].to_f}" if default
65
+ "real"
66
+ when "decimal"
67
+ default = " DEFAULT #{column[:default].nil? ? 'NULL' : column[:default]}" if default
68
+ "numeric(#{column[:length] || 10}, #{column[:decimals] || 0})"
69
+
70
+ when "double precision"
71
+ default = " DEFAULT #{column[:default].nil? ? 'NULL' : column[:default]}" if default
72
+ "double precision"
73
+
74
+ # Mysql datetime fields
75
+ when "datetime"
76
+ default = nil
77
+ "timestamp without time zone"
78
+ when "date"
79
+ default = nil
80
+ "date"
81
+ when "timestamp"
82
+ default = " DEFAULT CURRENT_TIMESTAMP" if column[:default] == "CURRENT_TIMESTAMP"
83
+ default = " DEFAULT '1970-01-01 00:00'" if column[:default] == "0000-00-00 00:00"
84
+ default = " DEFAULT '1970-01-01 00:00:00'" if column[:default] == "0000-00-00 00:00:00"
85
+ "timestamp without time zone"
86
+ when "time"
87
+ default = " DEFAULT NOW()" if default
88
+ "time without time zone"
89
+
90
+ when "tinyblob"
91
+ "bytea"
92
+ when "mediumblob"
93
+ "bytea"
94
+ when "longblob"
95
+ "bytea"
96
+ when "blob"
97
+ "bytea"
98
+ when "varbinary"
99
+ "bytea"
100
+ when "tinytext"
101
+ "text"
102
+ when "mediumtext"
103
+ "text"
104
+ when "longtext"
105
+ "text"
106
+ when "text"
107
+ "text"
108
+ when /^enum/
109
+ default = default + "::character varying" if default
110
+ enum = column[:type].gsub(/enum|\(|\)/, '')
111
+ max_enum_size = enum.split(',').map{ |check| check.size() -2}.sort[-1]
112
+ "character varying(#{max_enum_size}) check( #{column[:name]} in (#{enum}))"
113
+ else
114
+ puts "Unknown #{column.inspect}"
115
+ column[:type].inspect
116
+ return ""
117
+ end
118
+ "#{type}#{default}#{null}"
119
+ end
120
+
121
+ def process_row(table, row)
122
+ table.columns.each_with_index do |column, index|
123
+
124
+ if column[:type] == "time"
125
+ row[index] = "%02d:%02d:%02d" % [row[index].hour, row[index].minute, row[index].second]
126
+ end
127
+
128
+ if row[index].is_a?(Mysql::Time)
129
+ row[index] = row[index].to_s.gsub('0000-00-00 00:00', '1970-01-01 00:00')
130
+ row[index] = row[index].to_s.gsub('0000-00-00 00:00:00', '1970-01-01 00:00:00')
131
+ end
132
+
133
+ if column_type(column) == "boolean"
134
+ row[index] = row[index] == 1 ? 't' : row[index] == 0 ? 'f' : row[index]
135
+ end
136
+
137
+ if row[index].is_a?(String)
138
+ if column_type(column) == "bytea"
139
+ row[index] = escape_bytea(row[index])
140
+ else
141
+ row[index] = row[index].gsub(/\\/, '\\\\\\').gsub(/\n/,'\n').gsub(/\t/,'\t').gsub(/\r/,'\r').gsub(/\0/, '')
142
+ end
143
+ end
144
+
145
+ row[index] = '\N' if !row[index]
146
+ end
147
+ end
148
+
149
+ def truncate(table)
150
+ end
151
+
152
+ end
153
+
154
+ end
@@ -0,0 +1,9 @@
1
+ class Xmysql2psql
2
+ module Version
3
+ MAJOR = 0
4
+ MINOR = 4
5
+ PATCH = 2
6
+
7
+ STRING = [MAJOR, MINOR, PATCH].compact.join('.')
8
+ end
9
+ end
@@ -0,0 +1,6 @@
1
+ class Xmysql2psql
2
+
3
+ class Writer
4
+ end
5
+
6
+ end
@@ -0,0 +1,41 @@
1
+ require 'xmysql2psql/errors'
2
+ require 'xmysql2psql/version'
3
+ require 'xmysql2psql/config'
4
+ require 'xmysql2psql/converter'
5
+ require 'xmysql2psql/mysql_reader'
6
+ require 'xmysql2psql/writer'
7
+ require 'xmysql2psql/postgres_writer'
8
+ require 'xmysql2psql/postgres_db_writer.rb'
9
+ require 'xmysql2psql/postgres_file_writer.rb'
10
+
11
+
12
+ class Xmysql2psql
13
+
14
+ attr_reader :options, :reader, :writer
15
+
16
+ def initialize(args)
17
+ help if args.length==1 && args[0] =~ /^-.?|^-*he?l?p?$/i
18
+ configfile = args[0] || File.expand_path('xmysql2psql.yml')
19
+ @options = Config.new( configfile, true )
20
+ end
21
+
22
+ def convert
23
+ @reader = MysqlReader.new( options )
24
+
25
+ if options.destfile(nil)
26
+ @writer = PostgresFileWriter.new(options.destfile)
27
+ else
28
+ @writer = PostgresDbWriter.new(options)
29
+ end
30
+
31
+ Converter.new(reader, writer, options).convert
32
+ end
33
+
34
+ def help
35
+ puts <<EOS
36
+ MySQL to PostgreSQL Conversion
37
+
38
+ EOS
39
+ exit -2
40
+ end
41
+ end
@@ -0,0 +1,38 @@
1
+ mysql:
2
+ hostname: localhost
3
+ port: 3306
4
+ socket: /tmp/mysql.sock
5
+ username: somename
6
+ password: secretpassword
7
+ database: somename
8
+
9
+ destination:
10
+ # if file is given, output goes to file, else postgres
11
+ file: somefile
12
+ postgres:
13
+ hostname: localhost
14
+ port: 5432
15
+ username: somename
16
+ password: secretpassword
17
+ database: somename
18
+
19
+ # if tables is given, only the listed tables will be converted. leave empty to convert all tables.
20
+ tables:
21
+ - table1
22
+ - table2
23
+ - table3
24
+ - table4
25
+
26
+ # if exclude_tables is given, exclude the listed tables from the conversion.
27
+ exclude_tables:
28
+ - table5
29
+ - table6
30
+
31
+ # if supress_data is true, only the schema definition will be exported/migrated, and not the data
32
+ supress_data: true
33
+
34
+ # if supress_ddl is true, only the data will be exported/imported, and not the schema
35
+ supress_ddl: false
36
+
37
+ # if force_truncate is true, forces a table truncate before table loading
38
+ force_truncate: false
@@ -0,0 +1,24 @@
1
+ -- seed data for integration tests
2
+
3
+ DROP TABLE IF EXISTS numeric_types_basics;
4
+ CREATE TABLE numeric_types_basics (
5
+ id int,
6
+ f_tinyint TINYINT,
7
+ f_smallint SMALLINT,
8
+ f_mediumint MEDIUMINT,
9
+ f_int INT,
10
+ f_integer INTEGER,
11
+ f_bigint BIGINT,
12
+ f_real REAL,
13
+ f_double DOUBLE,
14
+ f_float FLOAT,
15
+ f_decimal DECIMAL,
16
+ f_numeric NUMERIC
17
+ );
18
+
19
+ INSERT INTO numeric_types_basics VALUES
20
+ (1,1,1,1,1,1,1,1,1,1,1,1),
21
+ (2,2,2,2,2,2,2,2,2,2,2,2),
22
+ (23,23,23,23,23,23,23,23,23,23,23,23);
23
+
24
+
@@ -0,0 +1,29 @@
1
+ require 'test_helper'
2
+
3
+ require 'xmysql2psql'
4
+
5
+ class ConvertToDbTest < Test::Unit::TestCase
6
+
7
+ class << self
8
+ def startup
9
+ seed_test_database
10
+ @@options=get_test_config_by_label(:localmysql_to_db_convert_all)
11
+ @@xmysql2psql = Xmysql2psql.new([@@options.filepath])
12
+ @@xmysql2psql.convert
13
+ @@xmysql2psql.writer.open
14
+ end
15
+ def shutdown
16
+ @@xmysql2psql.writer.close
17
+ delete_files_for_test_config(@@options)
18
+ end
19
+ end
20
+ def setup
21
+ end
22
+ def teardown
23
+ end
24
+
25
+ def test_table_creation
26
+ assert_true @@xmysql2psql.writer.exists?('numeric_types_basics')
27
+ end
28
+
29
+ end
@@ -0,0 +1,66 @@
1
+ require 'test_helper'
2
+
3
+ require 'xmysql2psql'
4
+
5
+ class ConvertToFileTest < Test::Unit::TestCase
6
+
7
+ class << self
8
+ def startup
9
+ seed_test_database
10
+ @@options=get_test_config_by_label(:localmysql_to_file_convert_all)
11
+ @@xmysql2psql = Xmysql2psql.new([@@options.filepath])
12
+ @@xmysql2psql.convert
13
+ @@content = IO.read(@@xmysql2psql.options.destfile)
14
+ end
15
+ def shutdown
16
+ delete_files_for_test_config(@@options)
17
+ end
18
+ end
19
+ def setup
20
+ end
21
+ def teardown
22
+ end
23
+ def content
24
+ @@content
25
+ end
26
+
27
+ def test_table_creation
28
+ assert_not_nil content.match('DROP TABLE IF EXISTS "numeric_types_basics" CASCADE')
29
+ assert_not_nil content.match(/CREATE TABLE "numeric_types_basics"/)
30
+ end
31
+
32
+ def test_basic_numerics_tinyint
33
+ assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_tinyint" smallint,.*\)', Regexp::MULTILINE).match( content )
34
+ end
35
+ def test_basic_numerics_smallint
36
+ assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_smallint" integer,.*\)', Regexp::MULTILINE).match( content )
37
+ end
38
+ def test_basic_numerics_mediumint
39
+ assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_mediumint" integer,.*\)', Regexp::MULTILINE).match( content )
40
+ end
41
+ def test_basic_numerics_int
42
+ assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_int" integer,.*\)', Regexp::MULTILINE).match( content )
43
+ end
44
+ def test_basic_numerics_integer
45
+ assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_integer" integer,.*\)', Regexp::MULTILINE).match( content )
46
+ end
47
+ def test_basic_numerics_bigint
48
+ assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_bigint" bigint,.*\)', Regexp::MULTILINE).match( content )
49
+ end
50
+ def test_basic_numerics_real
51
+ assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_real" double precision,.*\)', Regexp::MULTILINE).match( content )
52
+ end
53
+ def test_basic_numerics_double
54
+ assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_double" double precision,.*\)', Regexp::MULTILINE).match( content )
55
+ end
56
+ def test_basic_numerics_float
57
+ assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_float" numeric\(20, 0\),.*\)', Regexp::MULTILINE).match( content )
58
+ end
59
+ def test_basic_numerics_decimal
60
+ assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_decimal" numeric\(10, 0\),.*\)', Regexp::MULTILINE).match( content )
61
+ end
62
+ def test_basic_numerics_numeric
63
+ assert_not_nil Regexp.new('CREATE TABLE "numeric_types_basics".*"f_numeric" numeric\(10, 0\)[\w\n]*\)', Regexp::MULTILINE).match( content )
64
+ end
65
+
66
+ end