xmysql2psql 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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