require 'spec_helper' require 'flydata/table_def' module Flydata module TableDef describe MysqlTableDef do # file full path which exists in same directory. def full_path(file_name) File.join(File.dirname(__FILE__), file_name) end def file_io(file_name) File.new(full_path(file_name)) end describe '.to_flydata_tabledef' do let(:dump_file_io) { raise "dump_file_io must be override on context." } subject { MysqlTableDef.create(dump_file_io).to_flydata_tabledef } context 'when dump file includes single table with all kind of format types' do let(:dump_file_io) { file_io('mysqldump_test_table_all.dump') } it 'should set correct table name' do expect(subject[:table_name]).to eq('test_table_all') end it 'should set correct table name' do expect(subject[:columns]).to eq( [ {:column=>"id", :type=>"int8(20)", :auto_increment=>true, :not_null=>true, :primary_key=>true}, {:column=>"col_binary", :type=>"binary(100)", :default=>nil}, {:column=>"col_blob", :type=>"varbinary(65535)"}, {:column=>"col_bool", :type=>"int1(1)", :default=>"0"}, {:column=>"col_char", :type=>"varchar(18)", :default=>nil}, {:column=>"col_date", :type=>"date", :default=>nil}, {:column=>"col_datetime", :type=>"datetime", :default=>nil}, {:column=>"col_decimal", :type=>"numeric(5,2)", :default=>nil}, {:column=>"col_double", :type=>"float8", :default=>nil}, {:column=>"col_float", :type=>"float4", :default=>nil}, {:column=>"col_float_4_2", :type=>"float4(4,2)", :default=>nil}, {:column=>"col_int", :type=>"int4(11)", :default=>nil}, {:column=>"col_int_6", :type=>"int4(6)", :default=>nil}, {:column=>"col_longblob", :type=>"varbinary(4294967295)"}, {:column=>"col_longtext", :type=>"text"}, {:column=>"col_mediumblob", :type=>"varbinary(16777215)"}, {:column=>"col_mediumint", :type=>"int3(9)", :default=>nil}, {:column=>"col_mediumtext", :type=>"text"}, {:column=>"col_smallint", :type=>"int2(6)", :default=>nil}, {:column=>"col_text", :type=>"text"}, {:column=>"col_time", :type=>"time", :default=>nil}, {:column=>"col_timestamp", :type=>"datetime", :not_null=>true, :default=>"CURRENT_TIMESTAMP"}, {:column=>"col_tinyblob", :type=>"varbinary(255)"}, {:column=>"col_tinyint", :type=>"int1(4)", :default=>nil}, {:column=>"col_tinytext", :type=>"text"}, {:column=>"col_varbinary", :type=>"varbinary(255)", :default=>nil}, {:column=>"col_varchar", :type=>"varchar(372)", :default=>nil} ] ) end it 'default_charset should be set' do expect(subject[:default_charset]).to eq('utf8') end it 'comment should be set' do expect(subject[:comment]).to eq('test table includes all kind of format type') end end context 'when table does not have primary key' do let(:dump_file_io) { file_io('mysqldump_test_table_no_pk.dump') } it 'should raise an error' do expect{subject}.to raise_error(Flydata::TableDefError) end end context 'when column has comment' do let(:dump_file_io) { file_io('mysqldump_test_table_column_comment.dump') } it 'comment should be set' do expect(subject[:columns]).to eq( [ {:column=>"id", :type=>"int4(11)", :not_null=>true, :default=>"0", :comment=>"this is primary key", :primary_key=>true}, {:column=>"value", :type=>"text"} ] ) end end context 'when table has multiple pk' do let(:dump_file_io) { file_io('mysqldump_test_table_multi_pk.dump') } it 'multi pk should be set' do expect(subject[:columns]).to eq( [ {:column=>"id1", :type=>"int4(11)", :not_null=>true, :default=>"0", :primary_key=>true}, {:column=>"id2", :type=>"int4(11)", :not_null=>true, :default=>"0", :primary_key=>true}, {:column=>"value", :type=>"text"} ] ) end end context 'when table has enum column' do let(:dump_file_io) { file_io('mysqldump_test_table_enum.dump') } it 'enum columns should be parsed' do expect(subject[:columns]).to eq( [ {:column=>"id", :type=>"int4(11)", :not_null=>true, :primary_key=>true}, {:column=>"enum_1", :type=>"enum('apple','orange','banana')", :default=>nil}, {:column=>"enum_2", :type=>"enum('a','b','c')", :default=>"a"}, {:column=>"enum_3", :type=>"enum('e','f','g')", :not_null=>true}, ] ) end end context 'when table has index and foreign key constraints' do let(:dump_file_io) { file_io('mysqldump_test_foreign_key.dump') } it 'should parse the dump correctly' do expect(subject[:columns]).to eq( [ {:column=>"no", :type=>"int4(11)", :auto_increment=>true, :not_null=>true, :primary_key=>true}, {:column=>"product_category", :type=>"int4(11)", :not_null=>true}, {:column=>"product_id", :type=>"int4(11)", :not_null=>true}, {:column=>"customer_id", :type=>"int4(11)", :not_null=>true}, ] ) end end context 'when table has unsigned column' do let(:dump_file_io) { file_io('mysqldump_test_unsigned.dump')} it 'should include unsigned in column type' do expect(subject[:columns]).to eq( [ {:column=>"id", :type=>"int4(11)", :auto_increment=>true, :not_null=>true, :primary_key=>true}, {:column=>"value_int", :type=>"int4(10) unsigned", :default=>nil}, {:column=>"value_float", :type=>"float4 unsigned", :default=>nil}, {:column=>"value_dec", :type=>"numeric(10,2) unsigned", :default=>nil}, {:column=>"value_double", :type=>"float8 unsigned", :default=>nil}, {:column=>"name", :type=>"varchar(768)", :default=>nil}, {:column=>"value_small_int", :type=>"int2(5) unsigned", :default=>nil} ] ) end end context 'when table has unique keys' do let(:dump_file_io) { file_io('mysqldump_test_unique_key.dump')} it 'should include unique in column def' do expect(subject[:columns]).to eq( [ {:column=>"id", :type=>"int4(11)", :auto_increment=>true, :not_null=>true, :primary_key=>true}, {:column=>"title", :type=>"varchar(768)", :unique=>true, :default=>nil}, {:column=>"name", :type=>"text"}, {:column=>"num", :type=>"int4(11)", :unique=>true, :default=>nil} ] ) end end context 'when table has an unique key with a key name different than the column name' do let(:dump_file_io) { file_io('mysqldump_test_unique_key2.dump')} it 'should include unique in column def' do expect(subject[:columns]).to eq( [ {:column=>"id", :type=>"int4(11)", :auto_increment=>true, :not_null=>true, :primary_key=>true}, {:column=>"title", :type=>"varchar(768)", :unique=>true, :default=>nil}, {:column=>"name", :type=>"text"}, {:column=>"num", :type=>"int4(11)", :unique=>true, :default=>nil} ] ) end end end end end end