flydata 0.6.3 → 0.6.4

Sign up to get free protection for your applications and to get access to all the features.
Files changed (94) hide show
  1. checksums.yaml +4 -4
  2. data/Rakefile +2 -2
  3. data/VERSION +1 -1
  4. data/bin/fdredshift +78 -0
  5. data/circle.yml +1 -1
  6. data/ext/flydata/{parser/mysql → source_mysql/parser}/.gitignore +0 -0
  7. data/ext/flydata/{parser/mysql → source_mysql/parser}/dump_parser_ext.cpp +3 -3
  8. data/ext/flydata/source_mysql/parser/extconf.rb +3 -0
  9. data/ext/flydata/{parser/mysql → source_mysql/parser}/parser.txt +0 -0
  10. data/ext/flydata/{parser/mysql → source_mysql/parser}/sql_parser.cpp +0 -0
  11. data/ext/flydata/{parser/mysql → source_mysql/parser}/sql_parser.h +0 -0
  12. data/flydata-core/lib/flydata-core/mysql/binlog_pos.rb +34 -32
  13. data/flydata-core/lib/flydata-core/mysql/compatibility_checker.rb +20 -0
  14. data/flydata-core/lib/flydata-core/table_def/mysql_table_def.rb +12 -4
  15. data/flydata-core/lib/flydata-core/table_def/redshift_table_def.rb +60 -6
  16. data/flydata-core/spec/mysql/binlog_pos_spec.rb +474 -0
  17. data/flydata-core/spec/table_def/mysql_table_def_spec.rb +57 -0
  18. data/flydata-core/spec/table_def/mysql_to_redshift_table_def_spec.rb +174 -20
  19. data/flydata-core/spec/table_def/mysqldump_test_col_comment_with_AUTO_INCREMENT_keyword.dump +43 -0
  20. data/flydata-core/spec/table_def/mysqldump_test_col_comment_with_not_null_keyword.dump +43 -0
  21. data/flydata-core/spec/table_def/mysqldump_test_col_comment_with_unique_keyword.dump +43 -0
  22. data/flydata-core/spec/table_def/mysqldump_test_col_comment_with_unsigned_keyword.dump +43 -0
  23. data/flydata-core/spec/table_def/redshift_table_def_spec.rb +41 -8
  24. data/flydata.gemspec +0 -0
  25. data/lib/flydata/cli.rb +11 -5
  26. data/lib/flydata/command/base.rb +14 -1
  27. data/lib/flydata/command/exclusive_runnable.rb +42 -12
  28. data/lib/flydata/command/helper.rb +6 -6
  29. data/lib/flydata/command/sender.rb +4 -3
  30. data/lib/flydata/command/setup.rb +30 -381
  31. data/lib/flydata/command/stop.rb +1 -0
  32. data/lib/flydata/command/sync.rb +273 -301
  33. data/lib/flydata/compatibility_check.rb +24 -117
  34. data/lib/flydata/fluent-plugins/in_mysql_binlog_flydata.rb +3 -3
  35. data/lib/flydata/fluent-plugins/mysql/alter_table_query_handler.rb +2 -2
  36. data/lib/flydata/fluent-plugins/mysql/binlog_record_handler.rb +6 -6
  37. data/lib/flydata/fluent-plugins/mysql/truncate_table_query_handler.rb +0 -1
  38. data/lib/flydata/parser.rb +14 -0
  39. data/lib/flydata/{parser_provider.rb → parser/parser_provider.rb} +6 -4
  40. data/lib/flydata/parser/source_table.rb +33 -0
  41. data/lib/flydata/source.rb +105 -0
  42. data/lib/flydata/source/component.rb +21 -0
  43. data/lib/flydata/source/errors.rb +7 -0
  44. data/lib/flydata/source/generate_source_dump.rb +72 -0
  45. data/lib/flydata/source/parse_dump_and_send.rb +52 -0
  46. data/lib/flydata/source/setup.rb +31 -0
  47. data/lib/flydata/source/source_pos.rb +45 -0
  48. data/lib/flydata/source/sync.rb +56 -0
  49. data/lib/flydata/source/sync_generate_table_ddl.rb +43 -0
  50. data/lib/flydata/source_file/setup.rb +17 -0
  51. data/lib/flydata/source_file/sync.rb +14 -0
  52. data/lib/flydata/{command → source_mysql/command}/mysql.rb +2 -1
  53. data/lib/flydata/{command → source_mysql/command}/mysql_command_base.rb +2 -4
  54. data/lib/flydata/{command → source_mysql/command}/mysqlbinlog.rb +2 -1
  55. data/lib/flydata/{command → source_mysql/command}/mysqldump.rb +2 -1
  56. data/lib/flydata/source_mysql/generate_source_dump.rb +53 -0
  57. data/lib/flydata/source_mysql/mysql_compatibility_check.rb +114 -0
  58. data/lib/flydata/source_mysql/parse_dump_and_send.rb +28 -0
  59. data/lib/flydata/{parser/mysql → source_mysql/parser}/.gitignore +0 -0
  60. data/lib/flydata/{parser/mysql → source_mysql/parser}/dump_parser.rb +32 -67
  61. data/lib/flydata/{parser/mysql → source_mysql/parser}/mysql_alter_table.treetop +0 -0
  62. data/lib/flydata/source_mysql/setup.rb +24 -0
  63. data/lib/flydata/source_mysql/source_pos.rb +21 -0
  64. data/lib/flydata/source_mysql/sync.rb +45 -0
  65. data/lib/flydata/source_mysql/sync_generate_table_ddl.rb +40 -0
  66. data/lib/flydata/{mysql → source_mysql}/table_ddl.rb +6 -17
  67. data/lib/flydata/source_zendesk/sync_generate_table_ddl.rb +30 -0
  68. data/lib/flydata/source_zendesk/zendesk_flydata_tabledefs.rb +133 -0
  69. data/lib/flydata/sync_file_manager.rb +132 -73
  70. data/lib/flydata/table_ddl.rb +18 -0
  71. data/spec/flydata/cli_spec.rb +1 -0
  72. data/spec/flydata/command/exclusive_runnable_spec.rb +19 -8
  73. data/spec/flydata/command/sender_spec.rb +1 -1
  74. data/spec/flydata/command/setup_spec.rb +4 -4
  75. data/spec/flydata/command/sync_spec.rb +97 -134
  76. data/spec/flydata/compatibility_check_spec.rb +16 -289
  77. data/spec/flydata/fluent-plugins/mysql/alter_table_query_handler_spec.rb +3 -3
  78. data/spec/flydata/fluent-plugins/mysql/dml_record_handler_spec.rb +1 -1
  79. data/spec/flydata/fluent-plugins/mysql/shared_query_handler_context.rb +4 -2
  80. data/spec/flydata/fluent-plugins/mysql/truncate_query_handler_spec.rb +1 -1
  81. data/spec/flydata/source_mysql/generate_source_dump_spec.rb +69 -0
  82. data/spec/flydata/source_mysql/mysql_compatibility_check_spec.rb +280 -0
  83. data/spec/flydata/{parser/mysql → source_mysql/parser}/alter_table_parser_spec.rb +2 -2
  84. data/spec/flydata/{parser/mysql → source_mysql/parser}/dump_parser_spec.rb +75 -70
  85. data/spec/flydata/source_mysql/sync_generate_table_ddl_spec.rb +137 -0
  86. data/spec/flydata/{mysql → source_mysql}/table_ddl_spec.rb +2 -2
  87. data/spec/flydata/source_spec.rb +140 -0
  88. data/spec/flydata/source_zendesk/sync_generate_table_ddl_spec.rb +33 -0
  89. data/spec/flydata/sync_file_manager_spec.rb +157 -77
  90. data/tmpl/redshift_mysql_data_entry.conf.tmpl +1 -1
  91. metadata +56 -23
  92. data/ext/flydata/parser/mysql/extconf.rb +0 -3
  93. data/lib/flydata/mysql/binlog_position.rb +0 -22
  94. data/spec/flydata/mysql/binlog_position_spec.rb +0 -35
@@ -17,7 +17,7 @@ module Mysql
17
17
  r
18
18
  end
19
19
  before do
20
- parser_class = ParserProvider.parser(:mysql, :mysql_alter_table)
20
+ parser_class = Flydata::Parser::ParserProvider.parser(:mysql, :mysql_alter_table)
21
21
  allow(parser_class).to receive(:new).and_return(parser)
22
22
  allow_any_instance_of(described_class).to receive(:check_empty_binlog)
23
23
  record.delete('table_name')
@@ -56,8 +56,8 @@ module Mysql
56
56
  end
57
57
  context "when event binlog is older than table binlog.pos" do
58
58
  it 'skip sending event' do
59
- expect(sync_fm).to receive(:get_table_binlog_pos).and_return("mysql-bin.000067\t120").once
60
- expect(ParserProvider).not_to receive(:parser)
59
+ expect(sync_fm).to receive(:get_table_source_raw_pos).and_return("mysql-bin.000067\t120").once
60
+ expect(Flydata::Parser::ParserProvider).not_to receive(:parser)
61
61
  expect(subject.process(record)).to eq(nil)
62
62
  end
63
63
  end
@@ -12,7 +12,7 @@ describe DmlRecordHandler do
12
12
  let(:tables) { ['items', 'orders'] }
13
13
  let(:sync_fm) {
14
14
  sfm = double('sync_fm')
15
- allow(sfm).to receive(:get_table_binlog_pos).and_return nil
15
+ allow(sfm).to receive(:get_table_source_raw_pos).and_return nil
16
16
  sfm
17
17
  }
18
18
  let(:context) {
@@ -4,11 +4,13 @@ module Mysql
4
4
  let(:database) { target_database }
5
5
  let(:table) { "foo" }
6
6
  let(:seq) { 200 }
7
+ let(:binlog_pos_string) { "mysql-bin.000065\t120" }
8
+ let(:binlog_pos_object) { FlydataCore::Mysql::BinlogPos.new(binlog_pos_string) }
7
9
  let(:sync_fm) do
8
10
  r = double('sync_fm')
9
- allow(r).to receive(:get_table_binlog_pos).and_return("mysql-bin.000065\t120")
11
+ allow(r).to receive(:get_table_source_raw_pos).and_return(binlog_pos_string)
10
12
  allow(r).to receive(:increment_and_save_table_position).with(table).and_yield(seq).and_return(nil)
11
- allow(r).to receive(:delete_table_binlog_pos).with(table)
13
+ allow(r).to receive(:delete_table_source_pos).with(table)
12
14
  r
13
15
  end
14
16
  let(:table_meta) { double'table_meta' }
@@ -79,7 +79,7 @@ module Mysql
79
79
  context 'when per-table binlog pos exists' do
80
80
  let(:truncate_query) { "TRUNCATE #{table}" }
81
81
  before do
82
- allow(sync_fm).to receive(:get_table_binlog_pos).and_return("mysql-bin.000067\t120")
82
+ allow(sync_fm).to receive(:get_table_source_raw_pos).and_return("mysql-bin.000067\t120")
83
83
  end
84
84
  include_examples "skip processing queries"
85
85
  end
@@ -0,0 +1,69 @@
1
+ require 'flydata/source_mysql/generate_source_dump'
2
+
3
+ module Flydata
4
+ module SourceMysql
5
+
6
+ describe GenerateSourceDump do
7
+ let(:subject_object) { described_class.new(source, dp, options) }
8
+
9
+ let(:source) { double('source') }
10
+ before do
11
+ allow(source).to receive(:de).and_return(de)
12
+ end
13
+ let(:dp) { double('dp') }
14
+ let(:options) { double('options') }
15
+
16
+ let(:de) { {
17
+ "mysql_data_entry_preference" => {
18
+ "host" => "foo",
19
+ "port" => 1234,
20
+ "tables" => all_tables,
21
+ }
22
+ } }
23
+
24
+ let(:all_tables) { %w|a b c d| + partial_tables }
25
+ let(:partial_tables) { %w|e f| }
26
+ let(:file_path) { double('file_path') }
27
+ let(:src_pos_callback) { Proc.new{} }
28
+ let(:db_size_check) { double('db_size_check') }
29
+ let(:size) { double('size') }
30
+
31
+ let(:options_with_partial_tables) {
32
+ prefs = de['mysql_data_entry_preference'].clone
33
+ prefs["tables"] = partial_tables
34
+ prefs
35
+ }
36
+
37
+ describe '#dump_size' do
38
+ subject { subject_object.dump_size(partial_tables) }
39
+
40
+ it 'creates DatabaseSizeCheck object with correct parameter' do
41
+ expect(Parser::DatabaseSizeCheck).to receive(:new).
42
+ with(options_with_partial_tables).and_return(db_size_check)
43
+ expect(db_size_check).to receive(:get_db_bytesize).and_return(size)
44
+
45
+ expect(subject).to eq size
46
+ end
47
+ end
48
+
49
+ describe '#dump' do
50
+ subject { subject_object.dump(partial_tables, file_path, &src_pos_callback) }
51
+
52
+ let(:dump_generator) { double('dump_generator') }
53
+ before do
54
+ allow(dump_generator).to receive(:dump)
55
+ end
56
+
57
+ it 'creates dump_generator with correct parameters' do
58
+ expect(Parser::MysqlDumpGeneratorNoMasterData).to receive(:new).
59
+ with(options_with_partial_tables).and_return(dump_generator)
60
+ expect(dump_generator).to receive(:dump).
61
+ with(file_path, &src_pos_callback)
62
+
63
+ subject
64
+ end
65
+ end
66
+ end
67
+
68
+ end
69
+ end
@@ -0,0 +1,280 @@
1
+ require 'spec_helper'
2
+ require 'flydata/source_mysql/mysql_compatibility_check'
3
+
4
+ module Flydata
5
+ module SourceMysql
6
+
7
+ describe MysqlCompatibilityCheck do
8
+ let(:subject_object) { described_class.new(dp_hash, de_hash, options) }
9
+
10
+ let(:dp_hash) { default_data_port }
11
+ let(:de_hash) { default_mysql_cred }
12
+ let(:options) { default_options }
13
+
14
+ let(:default_data_port) do
15
+ {
16
+ "servers"=>["sample-test-site.com"]
17
+ }
18
+ end
19
+
20
+ let(:default_mysql_cred) do
21
+ {
22
+ "host" => "test",
23
+ "port" => 1234,
24
+ "username" => "test",
25
+ "password" => "password",
26
+ "database" => "test_db"
27
+ }
28
+ end
29
+
30
+ let(:default_options) { {} }
31
+
32
+ let(:client) { double('client') }
33
+ before do
34
+ allow(Mysql2::Client).to receive(:new).and_return(client)
35
+ allow(client).to receive(:close)
36
+ end
37
+
38
+ describe "#check" do
39
+ subject { subject_object.check }
40
+
41
+ it "calls all check methods" do
42
+ %w(compatibility56_variable mysql_user_compat mysql_protocol_tcp_compat
43
+ mysql_parameters_compat rds_master_status mysql_binlog_retention
44
+ mysql_table_types writing_permissions).each do |method_name|
45
+ expect(subject_object).to receive("check_#{method_name}".to_sym)
46
+ end
47
+
48
+ subject
49
+ end
50
+ end
51
+
52
+ describe "#check_mysql_user_compat" do
53
+ subject { subject_object.check_mysql_user_compat }
54
+
55
+ context "with all privileges in all databases" do
56
+ before do
57
+ allow(client).to receive(:query).and_return([{"Grants for test"=>"GRANT ALL PRIVILEGES ON *.* TO 'test'@'host"}])
58
+ end
59
+ it do
60
+ expect{subject}.to_not raise_error
61
+ end
62
+ end
63
+ context "with missing privileges in one database" do
64
+ before do
65
+ allow(client).to receive(:query).and_return([{"Grants for test"=>"GRANT ALL PRIVILEGES ON 'mysql'.* TO 'test'@'host"},
66
+ {"Grants for test"=>"GRANT SELECT, RELOAD, REPLICATION CLIENT ON `test_db`.* TO 'test'@'host"}])
67
+ end
68
+ it do
69
+ expect{subject}.to raise_error(FlydataCore::MysqlCompatibilityError, /test_db': LOCK TABLES, REPLICATION SLAVE/)
70
+ end
71
+ end
72
+ context "with all required privileges in between all and specific databases" do
73
+ before do
74
+ allow(client).to receive(:query).and_return([{"Grants for test"=>"GRANT RELOAD, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'test'@'host"},
75
+ {"Grants for test"=>"GRANT SELECT, LOCK TABLES ON `test_db`.* TO 'test'@'host"},
76
+ {"Grants for test"=>"GRANT SELECT, LOCK TABLES ON `mysql`.* TO 'test'@'host"}])
77
+ end
78
+ it do
79
+ expect{subject}.to_not raise_error
80
+ end
81
+ end
82
+ context "with missing privileges in each database" do
83
+ before do
84
+ allow(client).to receive(:query).and_return([{"Grants for test"=>"GRANT REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'test'@'host"},
85
+ {"Grants for test"=>"GRANT SELECT, LOCK TABLES ON `test_db`.* TO 'test'@'host"},
86
+ {"Grants for test"=>"GRANT SELECT, LOCK TABLES ON `mysql`.* TO 'test'@'host"}])
87
+ end
88
+ it do
89
+ expect{subject}.to raise_error(FlydataCore::MysqlCompatibilityError, /mysql': RELOAD\n.*test_db': RELOAD/)
90
+ end
91
+ end
92
+ context "with all required privileges in all databases" do
93
+ before do
94
+ allow(client).to receive(:query).and_return([{"Grants for test"=>"GRANT SELECT, LOCK TABLES, RELOAD, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'test'@'host"}])
95
+ end
96
+ it do
97
+ expect{subject}.to_not raise_error
98
+ end
99
+ end
100
+ context "with missing privileges in all databases" do
101
+ before do
102
+ allow(client).to receive(:query).and_return([{"Grants for test"=>"GRANT RELOAD, REPLICATION SLAVE, REPLICATION CLIENT ON *.* TO 'test'@'host"}])
103
+ end
104
+ it do
105
+ expect{subject}.to raise_error(FlydataCore::MysqlCompatibilityError, /mysql': SELECT, LOCK TABLES\n.*test_db': SELECT, LOCK TABLES/)
106
+ end
107
+ end
108
+ context "with privileges for other databases only" do
109
+ before do
110
+ allow(client).to receive(:query).and_return([{"Grants for test"=>"GRANT REPLICATION CLIENT ON `test_db_01`.* TO 'test'@'host"},
111
+ {"Grants for test"=>"GRANT LOCK TABLES ON `test_db_02`.* TO 'test'@'host"},
112
+ {"Grants for test"=>"GRANT SELECT ON `text_db_03`.* TO 'test'@'host"}])
113
+ end
114
+ it do
115
+ expect{subject}.to raise_error(FlydataCore::MysqlCompatibilityError, /mysql': SELECT, RELOAD, LOCK TABLES, REPLICATION SLAVE, REPLICATION CLIENT\n.*test_db': SELECT, RELOAD, LOCK TABLES, REPLICATION SLAVE, REPLICATION CLIENT/)
116
+ end
117
+ end
118
+
119
+ end
120
+
121
+ describe "#check_mysql_binlog_retention" do
122
+ subject { subject_object.check_mysql_binlog_retention }
123
+ context "on on-premise mysql server" do
124
+ before do
125
+ allow(subject_object).to receive(:is_rds?).and_return(false)
126
+ end
127
+ context "where retention is below limit" do
128
+ before do
129
+ allow(client).to receive(:query).and_return([{"Variable_name" => "expire_logs_days", "Value" => 1}])
130
+ end
131
+ it do
132
+ expect{subject}.to raise_error(FlydataCore::MysqlCompatibilityError, /expire_logs_days/)
133
+ end
134
+ end
135
+ context "where retention is 0" do
136
+ before do
137
+ allow(client).to receive(:query).and_return([{"Variable_name" => "expire_logs_days", "Value" => 0}])
138
+ end
139
+ it do
140
+ expect{subject}.to_not raise_error
141
+ end
142
+ end
143
+ context "where retention is above limit" do
144
+ before do
145
+ allow(client).to receive(:query).and_return([{"expire_logs_days"=>11}])
146
+ allow(client).to receive(:query).and_return([{"Variable_name" => "expire_logs_days", "Value" => 11}])
147
+ end
148
+ it do
149
+ expect{subject}.to_not raise_error
150
+ end
151
+ end
152
+ end
153
+ context "on RDS" do
154
+ before do
155
+ allow(subject_object).to receive(:is_rds?).and_return(true)
156
+ end
157
+ before do
158
+ allow(client).to receive(:query).with("SELECT @@expire_logs_days").and_return([{"@@expire_logs_days"=>0}])
159
+ end
160
+
161
+
162
+ context "where retention period is nil" do
163
+ before do
164
+ allow(client).to receive(:query).with("call mysql.rds_show_configuration;").and_return([{"name"=>"binlog retention hours", "value"=>nil}])
165
+ end
166
+ it do
167
+ expect{subject}.to raise_error(FlydataCore::MysqlCompatibilityError, /rds_set_config/)
168
+ end
169
+ end
170
+ context "where retention period is too low" do
171
+ before do
172
+ allow(client).to receive(:query).with("call mysql.rds_show_configuration;").and_return([{"name"=>"binlog retention hours", "value"=>4}])
173
+ end
174
+ it do
175
+ expect{subject}.to raise_error(FlydataCore::MysqlCompatibilityError, /rds_set_config/)
176
+ end
177
+ end
178
+ context "where retention period is over recommended limit" do
179
+ before do
180
+ allow(client).to receive(:query).with("call mysql.rds_show_configuration;").and_return([{"name"=>"binlog retention hours", "value"=>120}])
181
+ end
182
+ it do
183
+ expect{subject}.to_not raise_error
184
+ end
185
+ end
186
+ context "where user has no access to rds configuration" do
187
+ before do
188
+ allow(client).to receive(:query).with("call mysql.rds_show_configuration;").and_raise(Mysql2::Error, "execute command denied to user")
189
+ end
190
+ it do
191
+ expect{subject}.to_not raise_error
192
+ end
193
+ end
194
+ end
195
+ end
196
+
197
+ describe "#check_mysql_table_types" do
198
+ subject { subject_object.check_mysql_table_types }
199
+
200
+ let(:de_hash) do
201
+ { "host" => "test",
202
+ "port" => 1234,
203
+ "username" => "test",
204
+ "password" => "password",
205
+ "database" => "test_db",
206
+ "tables"=>["normal_table", "engine_table", "view_table"] }
207
+ end
208
+ let(:normal_table) { {"table_name"=>"normal_table", "table_type"=>"BASE TABLE", "engine"=>"InnoDB"} }
209
+ let(:engine_table) { {"table_name"=>"engine_table", "table_type"=>"BASE TABLE", "engine"=>"MEMORY"} }
210
+ let(:blackhole_table) { {"table_name"=>"blackhole_table", "table_type"=>"BASE TABLE", "engine"=>"BLACKHOLE"} }
211
+ let(:view) { {"table_name"=>"view_table", "table_type"=>"VIEW", "engine"=>nil} }
212
+ let(:error) { FlydataCore::MysqlCompatibilityError }
213
+ let(:base_error_msg) { "FlyData does not support VIEW and MEMORY,BLACKHOLE STORAGE ENGINE table. Remove following tables from data entry: %s" }
214
+ before do
215
+ allow(client).to receive(:query).and_return(table_list)
216
+ allow(client).to receive(:escape).and_return("aaa")
217
+ end
218
+ context "where data entry has VIEW and MEMORY engine table" do
219
+ let(:error_msg) { base_error_msg % engine_table['table_name'] + ', ' + view['table_name'] }
220
+ let(:table_list) { [ engine_table, view ] }
221
+ it { expect{subject}.to raise_error(error, /#{error_msg}/) }
222
+ end
223
+ context "where data entry has MEMORY engine table" do
224
+ let(:error_msg) { base_error_msg % engine_table['table_name'] }
225
+ let(:table_list) { [ engine_table ] }
226
+ it { expect{subject}.to raise_error(error, /#{error_msg}/) }
227
+ end
228
+ context "where data entry has BLACKHOLE engine table" do
229
+ let(:error_msg) { base_error_msg % blackhole_table['table_name'] }
230
+ let(:table_list) { [ blackhole_table ] }
231
+ it { expect{subject}.to raise_error(error, /#{error_msg}/) }
232
+ end
233
+ context "where data entry has the VIEW" do
234
+ let(:error_msg) { base_error_msg % view['table_name'] }
235
+ let(:table_list) { [ view ] }
236
+ it { expect{subject}.to raise_error(error, /#{error_msg}/) }
237
+ end
238
+ context "where data entry does not have either VIEW and ENGINE table" do
239
+ let(:table_list) { [ normal_table ] }
240
+ it { expect{subject}.to_not raise_error }
241
+ end
242
+ end
243
+
244
+ describe "#check_rds_master_status" do
245
+ subject { subject_object.check_rds_master_status }
246
+
247
+ let(:master_status) { [] }
248
+
249
+ before do
250
+ allow(client).to receive(:query).and_return(master_status)
251
+ end
252
+
253
+ context 'when host is rds' do
254
+ before do
255
+ de_hash['host'] = 'rdrss.xxyyzz.rds.amazonaws.com'
256
+ end
257
+
258
+ context "where backup retention period is not set" do
259
+ let(:master_status) { [] }
260
+ it { expect{subject}.to raise_error(FlydataCore::MysqlCompatibilityError, /Backup Retention Period/) }
261
+ end
262
+
263
+ context "where backup retention period is set" do
264
+ let(:master_status) do
265
+ [{
266
+ 'File' => 'mysql-bin-changelog.026292',
267
+ 'Position' => '31300',
268
+ 'Binlog_Do_DB' => '',
269
+ 'Binlog_Ignore_DB' => '',
270
+ 'Executed_Gtid_Set' => '',
271
+ }]
272
+ end
273
+ it { expect{subject}.not_to raise_error }
274
+ end
275
+ end
276
+ end
277
+ end
278
+
279
+ end
280
+ end
@@ -1,10 +1,10 @@
1
1
  require 'spec_helper'
2
- require 'flydata/parser_provider'
2
+ require 'flydata/parser/parser_provider'
3
3
 
4
4
  describe 'MysqlAlterTableParser' do
5
5
  before do
6
6
  #load parser
7
- @parser_class = Mysql::ParserProvider.parser(:mysql, :mysql_alter_table)
7
+ @parser_class = Flydata::Parser::ParserProvider.parser(:mysql, :mysql_alter_table)
8
8
  end
9
9
 
10
10
  let(:query) { "" }
@@ -3,11 +3,12 @@ require 'spec_helper'
3
3
  require 'open3'
4
4
  require 'mysql2'
5
5
  require 'flydata/command/sync'
6
- require 'flydata/parser/mysql/dump_parser'
6
+ require 'flydata/source_mysql/parser/dump_parser'
7
+ require 'flydata-core/mysql/binlog_pos'
7
8
 
8
9
  module Flydata
9
- module Parser
10
- module Mysql
10
+ module SourceMysql
11
+ module Parser
11
12
  context "Test Dump Generators" do
12
13
  let(:stdin) do
13
14
  s = double(:stdin)
@@ -153,8 +154,9 @@ EOT
153
154
  content[0...content.index(string)].bytesize + string.bytesize + 1
154
155
  end
155
156
 
156
- let(:default_parser) { MysqlDumpParser.new(binlog_pos: default_binlog_pos) }
157
+ let(:default_parser) { MysqlDumpParser.new(source_pos: default_binlog_pos_object) }
157
158
  let(:default_binlog_pos) { {binfile: 'mysql-bin.000267', pos: 120 } }
159
+ let(:default_binlog_pos_object) { FlydataCore::Mysql::BinlogPos.new(default_binlog_pos) }
158
160
  let(:dump_pos_after_binlog_pos) { index_after(DUMP_HEADER, '5.6.13-log') }
159
161
 
160
162
  let(:create_table_block) { double('create_table_block') }
@@ -210,30 +212,30 @@ EOT
210
212
  }
211
213
  before { generate_dump_file(dump_content) }
212
214
  it do
213
- expect(create_table_block).to receive(:call) { |mysql_table|
214
- expect(mysql_table.table_name).to eq('users_login')
215
+ expect(create_table_block).to receive(:call) { |source_table|
216
+ expect(source_table.table_name).to eq('users_login')
215
217
  }.once
216
218
  expect(insert_record_block).to receive(:call).never
217
- expect(check_point_block).to receive(:call) { |mysql_table, last_pos, bytesize, binlog_pos, state, substate|
218
- expect(mysql_table).to be_nil
219
+ expect(check_point_block).to receive(:call) { |source_table, last_pos, bytesize, binlog_pos, state, substate|
220
+ expect(source_table).to be_nil
219
221
  expect(last_pos).to eq(dump_pos_after_binlog_pos)
220
222
  expect(binlog_pos).to eq(default_binlog_pos)
221
- expect(state).to eq(MysqlDumpParser::State::CREATE_TABLE)
223
+ expect(state).to eq(Flydata::Parser::State::CREATE_TABLE)
222
224
  expect(substate).to be_nil
223
225
  }
224
- expect(check_point_block).to receive(:call) { |mysql_table, last_pos, bytesize, binlog_pos, state, substate|
225
- expect(mysql_table.table_name).to eq('users_login')
226
- expect(mysql_table.columns.keys).to eq([col_name, 'login_count', 'create_time', 'update_time'])
226
+ expect(check_point_block).to receive(:call) { |source_table, last_pos, bytesize, binlog_pos, state, substate|
227
+ expect(source_table.table_name).to eq('users_login')
228
+ expect(source_table.columns.keys).to eq([col_name, 'login_count', 'create_time', 'update_time'])
227
229
  expect(last_pos).to eq(index_after(dump_content, 'ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT=\'\';'))
228
230
  expect(binlog_pos).to eq(default_binlog_pos)
229
- expect(state).to eq(MysqlDumpParser::State::INSERT_RECORD)
231
+ expect(state).to eq(Flydata::Parser::State::INSERT_RECORD)
230
232
  expect(substate).to be_nil
231
233
  }
232
- expect(check_point_block).to receive(:call) { |mysql_table, last_pos, bytesize, binlog_pos, state, substate|
233
- expect(mysql_table.table_name).to eq('users_login')
234
+ expect(check_point_block).to receive(:call) { |source_table, last_pos, bytesize, binlog_pos, state, substate|
235
+ expect(source_table.table_name).to eq('users_login')
234
236
  expect(last_pos).to eq(index_after(dump_content, 'UNLOCK TABLES;'))
235
237
  expect(binlog_pos).to eq(default_binlog_pos)
236
- expect(state).to eq(MysqlDumpParser::State::CREATE_TABLE)
238
+ expect(state).to eq(Flydata::Parser::State::CREATE_TABLE)
237
239
  expect(substate).to be_nil
238
240
  }
239
241
  expect(check_point_block).to receive(:call).never
@@ -302,9 +304,9 @@ EOT
302
304
  before { generate_dump_file(dump_content) }
303
305
  it do
304
306
  # create_table_block
305
- expect(create_table_block).to receive(:call) { |mysql_table|
306
- expect(mysql_table.table_name).to eq('users_login')
307
- expect(mysql_table.columns.keys).to eq(['user_id', 'login_count', 'comment', 'create_time', 'update_time'])
307
+ expect(create_table_block).to receive(:call) { |source_table|
308
+ expect(source_table.table_name).to eq('users_login')
309
+ expect(source_table.columns.keys).to eq(['user_id', 'login_count', 'comment', 'create_time', 'update_time'])
308
310
  }.once
309
311
  expect(create_table_block).to receive(:call).never
310
312
 
@@ -316,8 +318,8 @@ EOT
316
318
  [ %w(373 31 out'swearing 1979-10-07\ 08:10:08 2006-02-22\ 16:26:04),
317
319
  %w(493 8 schizophrenic 1979-07-06\ 07:34:07 1970-08-09\ 01:21:01),]
318
320
  ].each do |expected_values|
319
- expect(insert_record_block).to receive(:call) { |mysql_table, values_set|
320
- expect(mysql_table.table_name).to eq('users_login')
321
+ expect(insert_record_block).to receive(:call) { |source_table, values_set|
322
+ expect(source_table.table_name).to eq('users_login')
321
323
  expect(values_set).to eq(expected_values)
322
324
  nil
323
325
  }.once
@@ -326,13 +328,13 @@ EOT
326
328
 
327
329
  # insert_record_block
328
330
  [
329
- {state: MysqlDumpParser::State::CREATE_TABLE},
330
- {state: MysqlDumpParser::State::INSERT_RECORD},
331
- {state: MysqlDumpParser::State::CREATE_TABLE,
331
+ {state: Flydata::Parser::State::CREATE_TABLE},
332
+ {state: Flydata::Parser::State::INSERT_RECORD},
333
+ {state: Flydata::Parser::State::CREATE_TABLE,
332
334
  last_pos: index_after(dump_content, 'UNLOCK TABLES;')}
333
335
  ].each do |expected_params|
334
- expect(check_point_block).to receive(:call) { |mysql_table, last_pos, bytesize, binlog_pos, state, substate|
335
- expect(mysql_table.table_name).to eq('users_login') if mysql_table
336
+ expect(check_point_block).to receive(:call) { |source_table, last_pos, bytesize, binlog_pos, state, substate|
337
+ expect(source_table.table_name).to eq('users_login') if source_table
336
338
  expect(state).to eq(expected_params[:state])
337
339
  if expected_params[:last_pos]
338
340
  expect(last_pos).to eq(expected_params[:last_pos])
@@ -384,9 +386,9 @@ EOT
384
386
  before { generate_dump_file(dump_content) }
385
387
  it do
386
388
  # create_table_block
387
- expect(create_table_block).to receive(:call) { |mysql_table|
388
- expect(mysql_table.table_name).to eq('users_login')
389
- expect(mysql_table.columns.keys).to eq(['user_id', 'login_count', 'comment', 'create_time', 'update_time'])
389
+ expect(create_table_block).to receive(:call) { |source_table|
390
+ expect(source_table.table_name).to eq('users_login')
391
+ expect(source_table.columns.keys).to eq(['user_id', 'login_count', 'comment', 'create_time', 'update_time'])
390
392
  }.once
391
393
  expect(create_table_block).to receive(:call).never
392
394
 
@@ -396,8 +398,8 @@ EOT
396
398
  ['35', '6', nil, '1991-10-15 19:38:07', '1970-10-01 22:03:10'],
397
399
  %w(52 33 subfield 1972-08-23\ 20:16:08 1974-10-10\ 23:28:11),],
398
400
  ].each do |expected_values|
399
- expect(insert_record_block).to receive(:call) { |mysql_table, values_set|
400
- expect(mysql_table.table_name).to eq('users_login')
401
+ expect(insert_record_block).to receive(:call) { |source_table, values_set|
402
+ expect(source_table.table_name).to eq('users_login')
401
403
  expect(values_set).to eq(expected_values)
402
404
  nil
403
405
  }.once
@@ -406,13 +408,13 @@ EOT
406
408
 
407
409
  # insert_record_block
408
410
  [
409
- {state: MysqlDumpParser::State::CREATE_TABLE},
410
- {state: MysqlDumpParser::State::INSERT_RECORD},
411
- {state: MysqlDumpParser::State::CREATE_TABLE,
411
+ {state: Flydata::Parser::State::CREATE_TABLE},
412
+ {state: Flydata::Parser::State::INSERT_RECORD},
413
+ {state: Flydata::Parser::State::CREATE_TABLE,
412
414
  last_pos: index_after(dump_content, 'UNLOCK TABLES;')}
413
415
  ].each do |expected_params|
414
- expect(check_point_block).to receive(:call) { |mysql_table, last_pos, bytesize, binlog_pos, state, substate|
415
- expect(mysql_table.table_name).to eq('users_login') if mysql_table
416
+ expect(check_point_block).to receive(:call) { |source_table, last_pos, bytesize, binlog_pos, state, substate|
417
+ expect(source_table.table_name).to eq('users_login') if source_table
416
418
  expect(state).to eq(expected_params[:state])
417
419
  if expected_params[:last_pos]
418
420
  expect(last_pos).to eq(expected_params[:last_pos])
@@ -472,16 +474,16 @@ EOT
472
474
  Proc.new{
473
475
  raise "Should not be called"
474
476
  },
475
- Proc.new{ |mysql_table, last_pos, bytesize, binlog_pos, state, substate|
476
- if mysql_table
477
- @mysql_table = mysql_table
477
+ Proc.new{ |source_table, last_pos, bytesize, binlog_pos, state, substate|
478
+ if source_table
479
+ @source_table = source_table
478
480
  @option = { status: Flydata::Command::Sync::STATUS_PARSING,
479
- table_name: mysql_table.table_name,
481
+ table_name: source_table.table_name,
480
482
  last_pos: last_pos,
481
483
  binlog_pos: binlog_pos,
482
484
  state: state,
483
485
  substate: substate,
484
- mysql_table: mysql_table }
486
+ source_table: source_table }
485
487
  end
486
488
  }
487
489
  )
@@ -490,15 +492,16 @@ EOT
490
492
  table_name: 'users_login',
491
493
  last_pos: index_after(dump_content_head, 'ENGINE=InnoDB DEFAULT CHARSET=utf8;'),
492
494
  binlog_pos: default_binlog_pos,
493
- state: MysqlDumpParser::State::INSERT_RECORD,
495
+ state: Flydata::Parser::State::INSERT_RECORD,
494
496
  substate: nil,
495
- mysql_table: @mysql_table
497
+ source_table: @source_table
496
498
  })
497
499
  end
498
500
  it do
499
501
  generate_dump_file(dump_content_all)
502
+ @option.delete(:binlog_pos)
503
+ @option.merge!( {source_pos: default_binlog_pos_object} )
500
504
  parser_for_resume = MysqlDumpParser.new(@option)
501
-
502
505
  # create_table_block
503
506
  expect(create_table_block).to receive(:call).never
504
507
 
@@ -508,8 +511,8 @@ EOT
508
511
  %w(35 6 missteer 1991-10-15\ 19:38:07 1970-10-01\ 22:03:10),
509
512
  %w(52 33 subfield 1972-08-23\ 20:16:08 1974-10-10\ 23:28:11),],
510
513
  ].each do |expected_values|
511
- expect(insert_record_block).to receive(:call) { |mysql_table, values|
512
- expect(mysql_table.table_name).to eq('users_login')
514
+ expect(insert_record_block).to receive(:call) { |source_table, values|
515
+ expect(source_table.table_name).to eq('users_login')
513
516
  expect(values).to eq(expected_values)
514
517
  nil
515
518
  }.once
@@ -518,11 +521,11 @@ EOT
518
521
 
519
522
  # check_point_block
520
523
  [
521
- {state: MysqlDumpParser::State::CREATE_TABLE,
524
+ {state: Flydata::Parser::State::CREATE_TABLE,
522
525
  last_pos: index_after(dump_content_all, 'UNLOCK TABLES;')}
523
526
  ].each do |expected_params|
524
- expect(check_point_block).to receive(:call) { |mysql_table, last_pos, bytesize, binlog_pos, state, substate|
525
- expect(mysql_table.table_name).to eq('users_login') if mysql_table
527
+ expect(check_point_block).to receive(:call) { |source_table, last_pos, bytesize, binlog_pos, state, substate|
528
+ expect(source_table.table_name).to eq('users_login') if source_table
526
529
  expect(state).to eq(expected_params[:state])
527
530
  if expected_params[:last_pos]
528
531
  expect(last_pos).to eq(expected_params[:last_pos])
@@ -582,16 +585,16 @@ EOT
582
585
  dump_io,
583
586
  Proc.new{},
584
587
  insert_record_block_for_resume,
585
- Proc.new{ |mysql_table, last_pos, bytesize, binlog_pos, state, substate|
588
+ Proc.new{ |source_table, last_pos, bytesize, binlog_pos, state, substate|
586
589
  if last_pos == index_after(dump_content, "'1972-08-23 20:16:08','1974-10-10 23:28:11');")
587
- @mysql_table = mysql_table
590
+ @source_table = source_table
588
591
  @option = { status: Flydata::Command::Sync::STATUS_PARSING,
589
- table_name: mysql_table.table_name,
592
+ table_name: source_table.table_name,
590
593
  last_pos: last_pos,
591
594
  binlog_pos: binlog_pos,
592
595
  state: state,
593
596
  substate: substate,
594
- mysql_table: mysql_table }
597
+ source_table: source_table }
595
598
  end
596
599
  }
597
600
  )
@@ -600,13 +603,15 @@ EOT
600
603
  table_name: 'users_login',
601
604
  last_pos: index_after(dump_content, "'1972-08-23 20:16:08','1974-10-10 23:28:11');"),
602
605
  binlog_pos: default_binlog_pos,
603
- state: MysqlDumpParser::State::INSERT_RECORD,
606
+ state: Flydata::Parser::State::INSERT_RECORD,
604
607
  substate: nil,
605
- mysql_table: @mysql_table
608
+ source_table: @source_table
606
609
  })
607
610
  end
608
611
  it do
609
612
  generate_dump_file(dump_content)
613
+ @option.delete(:binlog_pos)
614
+ @option.merge!({source_pos: default_binlog_pos_object})
610
615
  parser_for_resume = MysqlDumpParser.new(@option)
611
616
 
612
617
  # create_table_block
@@ -617,8 +622,8 @@ EOT
617
622
  [ %w(194 11 pandemonium 2008-01-22\ 22:15:10 1991-04-04\ 17:30:05),
618
623
  %w(230 7 cloudburst 2010-12-28\ 11:46:11 1971-06-22\ 13:08:01),],
619
624
  ].each do |expected_values|
620
- expect(insert_record_block).to receive(:call) { |mysql_table, values_set|
621
- expect(mysql_table.table_name).to eq('users_login')
625
+ expect(insert_record_block).to receive(:call) { |source_table, values_set|
626
+ expect(source_table.table_name).to eq('users_login')
622
627
  expect(values_set).to eq(expected_values)
623
628
  nil
624
629
  }.once
@@ -627,11 +632,11 @@ EOT
627
632
 
628
633
  # check_point_block
629
634
  [
630
- {state: MysqlDumpParser::State::CREATE_TABLE,
635
+ {state: Flydata::Parser::State::CREATE_TABLE,
631
636
  last_pos: index_after(dump_content, 'UNLOCK TABLES;')}
632
637
  ].each do |expected_params|
633
- expect(check_point_block).to receive(:call) { |mysql_table, last_pos, bytesize, binlog_pos, state, substate|
634
- expect(mysql_table.table_name).to eq('users_login') if mysql_table
638
+ expect(check_point_block).to receive(:call) { |source_table, last_pos, bytesize, binlog_pos, state, substate|
639
+ expect(source_table.table_name).to eq('users_login') if source_table
635
640
  expect(state).to eq(expected_params[:state])
636
641
  if expected_params[:last_pos]
637
642
  expect(last_pos).to eq(expected_params[:last_pos])
@@ -684,9 +689,9 @@ EOT
684
689
  before { generate_dump_file(dump_content) }
685
690
  it do
686
691
  # create_table_block
687
- expect(create_table_block).to receive(:call) { |mysql_table|
688
- expect(mysql_table.table_name).to eq('users_login')
689
- expect(mysql_table.columns.keys).to eq(['user_id', 'login_count', 'comment', 'create_time', 'update_time'])
692
+ expect(create_table_block).to receive(:call) { |source_table|
693
+ expect(source_table.table_name).to eq('users_login')
694
+ expect(source_table.columns.keys).to eq(['user_id', 'login_count', 'comment', 'create_time', 'update_time'])
690
695
  }.once
691
696
  expect(create_table_block).to receive(:call).never
692
697
 
@@ -698,8 +703,8 @@ EOT
698
703
  [ ['373','31',"outs\nwearing",'1979-10-07 08:10:08','2006-02-22 16:26:04'],
699
704
  ['493','8',"schiz\tophrenic",'1979-07-06 07:34:07\'),','1970-08-09,01:21:01,\')'] ]
700
705
  ].each do |expected_values|
701
- expect(insert_record_block).to receive(:call) { |mysql_table, values_set|
702
- expect(mysql_table.table_name).to eq('users_login')
706
+ expect(insert_record_block).to receive(:call) { |source_table, values_set|
707
+ expect(source_table.table_name).to eq('users_login')
703
708
  expect(values_set).to eq(expected_values)
704
709
  nil
705
710
  }.once
@@ -708,13 +713,13 @@ EOT
708
713
 
709
714
  # insert_record_block
710
715
  [
711
- {state: MysqlDumpParser::State::CREATE_TABLE},
712
- {state: MysqlDumpParser::State::INSERT_RECORD},
713
- {state: MysqlDumpParser::State::CREATE_TABLE,
716
+ {state: Flydata::Parser::State::CREATE_TABLE},
717
+ {state: Flydata::Parser::State::INSERT_RECORD},
718
+ {state: Flydata::Parser::State::CREATE_TABLE,
714
719
  last_pos: index_after(dump_content, 'UNLOCK TABLES;')}
715
720
  ].each do |expected_params|
716
- expect(check_point_block).to receive(:call) { |mysql_table, last_pos, bytesize, binlog_pos, state, substate|
717
- expect(mysql_table.table_name).to eq('users_login') if mysql_table
721
+ expect(check_point_block).to receive(:call) { |source_table, last_pos, bytesize, binlog_pos, state, substate|
722
+ expect(source_table.table_name).to eq('users_login') if source_table
718
723
  expect(state).to eq(expected_params[:state])
719
724
  if expected_params[:last_pos]
720
725
  expect(last_pos).to eq(expected_params[:last_pos])