flydata 0.2.30 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: acad4ae7202b7fc525478de91925ef4ee0a24fdd
4
- data.tar.gz: 63cf3ac658afa5be37ed7b2a85be476de280c56f
3
+ metadata.gz: 68f311d20207752e80dd5fb47b905b085e840520
4
+ data.tar.gz: 6bfa38fa63a7db7e1f4b7109324017e99c82c117
5
5
  SHA512:
6
- metadata.gz: fb7391185d4f9797817f0628ec46f5b9cce0ef1680fb843d0181f97dd18450c059d6b6614b7ef98e8ee88dfac171933561e448a2ca1b403665563b27b5d005a8
7
- data.tar.gz: 7407fd538bbd7678ae19d5ddaa9dcc5b13159555b8c7b82a788c821fb70855594f49848eb141ec7a44982eb164dd63738e63a9714ed132b5b02ff2caab948d4f
6
+ metadata.gz: 01469b9c9b268bc8dad0bda81a3dbcc3a98a55901108cac17b50a6688313485f1d7cdd8a01b26ea20cbea0d8fa6f4c096055394f55cea58ee59a949acb2963fe
7
+ data.tar.gz: cde53114405b00f034e7444fd0b9ba9df9519a2cd3979eade6a99d48e80e326615a1ba16fb0d5c014c51d23272ca5cf2257b2f318135ad6efef858f4d6d4479b
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.30
1
+ 0.3.0
@@ -8,4 +8,9 @@ require 'flydata'
8
8
 
9
9
  args = ARGV.dup
10
10
  ARGV.clear # for 'gets'
11
- Flydata::Cli.new(args).run
11
+ begin
12
+ Flydata::Cli.new(args).run
13
+ rescue Interrupt
14
+ # Suppress stacktrace upon Ctrl-C quit
15
+ puts
16
+ end
@@ -28,37 +28,37 @@ class MysqlTableDef
28
28
  end
29
29
 
30
30
  TYPE_MAP_M2F = {
31
- 'bigint' => {type: 'int8'},
32
- 'binary' => {type: 'binary', override: PROC_override_varbinary},
33
- 'bit' => {type: 'bit'},
31
+ 'bigint' => {type: 'int8', def_width: '20'},
32
+ 'binary' => {type: 'binary', def_width: '1', override: PROC_override_varbinary},
33
+ 'bit' => {type: 'bit', def_width: '1'},
34
34
  'blob' => {type: 'varbinary(65535)'},
35
- 'bool' => {type: 'int1'},
36
- 'boolean' => {type: 'int1'},
37
- 'char' => {type: 'varchar', override: PROC_override_varchar},
35
+ 'bool' => {type: 'int1', def_width: '1'},
36
+ 'boolean' => {type: 'int1', def_width: '1'},
37
+ 'char' => {type: 'varchar', def_width: '1', override: PROC_override_varchar},
38
38
  'date' => {type: 'date'},
39
39
  'datetime' => {type: 'datetime'},
40
- 'dec' => {type: 'numeric'},
41
- 'decimal' => {type: 'numeric'},
40
+ 'dec' => {type: 'numeric', def_width: '10,0'},
41
+ 'decimal' => {type: 'numeric', def_width: '10,0'},
42
42
  'double' => {type: 'float8'},
43
43
  'double precision' => {type: 'float8'},
44
44
  'enum' => {type: 'enum'},
45
- 'fixed' => {type: 'numeric'},
45
+ 'fixed' => {type: 'numeric', def_width: '10,0'},
46
46
  'float' => {type: 'float4'},
47
- 'int' => {type: 'int4'},
48
- 'integer' => {type: 'int4'},
47
+ 'int' => {type: 'int4', def_width: '11'},
48
+ 'integer' => {type: 'int4', def_width: '11'},
49
49
  'longblob' => {type: 'varbinary(4294967295)'},
50
50
  'longtext' => {type: 'text'},
51
51
  'mediumblob' => {type: 'varbinary(16777215)'},
52
- 'mediumint' => {type: 'int3'},
52
+ 'mediumint' => {type: 'int3', def_width: '9'},
53
53
  'mediumtext' => {type: 'text'},
54
- 'numeric' => {type: 'numeric'},
54
+ 'numeric' => {type: 'numeric', def_width: '10,0'},
55
55
  'set' => {type: 'set'},
56
- 'smallint' => {type: 'int2'},
56
+ 'smallint' => {type: 'int2', def_width: '6'},
57
57
  'text' => {type: 'text'},
58
58
  'time' => {type: 'time'},
59
59
  'timestamp' => {type: 'datetime'},
60
60
  'tinyblob' => {type: 'varbinary(255)'},
61
- 'tinyint' => {type: 'int1'},
61
+ 'tinyint' => {type: 'int1', def_width: '4'},
62
62
  'tinytext' => {type: 'text'},
63
63
  'varbinary' => {type: 'varbinary', override: PROC_override_varbinary},
64
64
  'varchar' => {type: 'varchar', override: PROC_override_varchar},
@@ -69,6 +69,9 @@ class MysqlTableDef
69
69
  flydata_type = type_hash[:type]
70
70
  if /^#{mysql_type}\(|^#{mysql_type}$/.match(type)
71
71
  ret_type = type.gsub(/^#{mysql_type}/, flydata_type)
72
+ if type_hash.has_key?(:def_width) && !/\(.+\)/.match(ret_type)
73
+ ret_type += "(#{type_hash[:def_width]})"
74
+ end
72
75
  if type_hash[:override]
73
76
  ret_type = type_hash[:override].call(ret_type, mysql_type, flydata_type)
74
77
  end
@@ -199,6 +199,138 @@ describe MysqlTableDef do
199
199
  end
200
200
  end
201
201
  end
202
+
203
+ describe '.convert_to_flydata_type' do
204
+ subject { described_class.convert_to_flydata_type(mysql_type) }
205
+ shared_examples "converting the mysql data type to the expected flydata type" do
206
+ # Use the context description as the value of "mysql_type"
207
+ # RSpec.current_example.meatadata[:example_group] => the shared_examples "converting the mysql data type to the expected flydata type"
208
+ # [:parent_example_group] => the context including the shared examples (e.g. context "bigint")
209
+ # [:description] => the name of the example group (e.g. "bigint")
210
+ let(:mysql_type) { RSpec.current_example.metadata[:example_group][:parent_example_group][:description] }
211
+ it do
212
+ expect(subject).to eq flydata_type
213
+ end
214
+ end
215
+ context "with no-width mysql data type" do
216
+ context "bigint" do
217
+ let(:flydata_type) { 'int8(20)' }
218
+ it_behaves_like "converting the mysql data type to the expected flydata type"
219
+ end
220
+ context "binary" do
221
+ let(:flydata_type) { 'binary(4)' }
222
+ it_behaves_like "converting the mysql data type to the expected flydata type"
223
+ end
224
+ context "bit" do
225
+ let(:flydata_type) { 'bit(1)' }
226
+ it_behaves_like "converting the mysql data type to the expected flydata type"
227
+ end
228
+ context "blob" do
229
+ let(:flydata_type) { 'varbinary(65535)' }
230
+ it_behaves_like "converting the mysql data type to the expected flydata type"
231
+ end
232
+ context "bool" do
233
+ let(:flydata_type) { 'int1(1)' }
234
+ it_behaves_like "converting the mysql data type to the expected flydata type"
235
+ end
236
+ context "boolean" do
237
+ let(:flydata_type) { 'int1(1)' }
238
+ it_behaves_like "converting the mysql data type to the expected flydata type"
239
+ end
240
+ context "char" do
241
+ let(:flydata_type) { 'varchar(3)' }
242
+ it_behaves_like "converting the mysql data type to the expected flydata type"
243
+ end
244
+ context "date" do
245
+ let(:flydata_type) { 'date' }
246
+ it_behaves_like "converting the mysql data type to the expected flydata type"
247
+ end
248
+ context "datetime" do
249
+ let(:flydata_type) { 'datetime' }
250
+ it_behaves_like "converting the mysql data type to the expected flydata type"
251
+ end
252
+ context "dec" do
253
+ let(:flydata_type) { 'numeric(10,0)' }
254
+ it_behaves_like "converting the mysql data type to the expected flydata type"
255
+ end
256
+ context "decimal" do
257
+ let(:flydata_type) { 'numeric(10,0)' }
258
+ it_behaves_like "converting the mysql data type to the expected flydata type"
259
+ end
260
+ context "double" do
261
+ let(:flydata_type) { 'float8' }
262
+ it_behaves_like "converting the mysql data type to the expected flydata type"
263
+ end
264
+ context "fixed" do
265
+ let(:flydata_type) { 'numeric(10,0)' }
266
+ it_behaves_like "converting the mysql data type to the expected flydata type"
267
+ end
268
+ context "float" do
269
+ let(:flydata_type) { 'float4' }
270
+ it_behaves_like "converting the mysql data type to the expected flydata type"
271
+ end
272
+ context "int" do
273
+ let(:flydata_type) { 'int4(11)' }
274
+ it_behaves_like "converting the mysql data type to the expected flydata type"
275
+ end
276
+ context "integer" do
277
+ let(:flydata_type) { 'int4(11)' }
278
+ it_behaves_like "converting the mysql data type to the expected flydata type"
279
+ end
280
+ context "longblob" do
281
+ let(:flydata_type) { 'varbinary(4294967295)' }
282
+ it_behaves_like "converting the mysql data type to the expected flydata type"
283
+ end
284
+ context "longtext" do
285
+ let(:flydata_type) { 'text' }
286
+ it_behaves_like "converting the mysql data type to the expected flydata type"
287
+ end
288
+ context "mediumblob" do
289
+ let(:flydata_type) { 'varbinary(16777215)' }
290
+ it_behaves_like "converting the mysql data type to the expected flydata type"
291
+ end
292
+ context "mediumint" do
293
+ let(:flydata_type) { 'int3(9)' }
294
+ it_behaves_like "converting the mysql data type to the expected flydata type"
295
+ end
296
+ context "mediumtext" do
297
+ let(:flydata_type) { 'text' }
298
+ it_behaves_like "converting the mysql data type to the expected flydata type"
299
+ end
300
+ context "numeric" do
301
+ let(:flydata_type) { 'numeric(10,0)' }
302
+ it_behaves_like "converting the mysql data type to the expected flydata type"
303
+ end
304
+ context "smallint" do
305
+ let(:flydata_type) { 'int2(6)' }
306
+ it_behaves_like "converting the mysql data type to the expected flydata type"
307
+ end
308
+ context "text" do
309
+ let(:flydata_type) { 'text' }
310
+ it_behaves_like "converting the mysql data type to the expected flydata type"
311
+ end
312
+ context "time" do
313
+ let(:flydata_type) { 'time' }
314
+ it_behaves_like "converting the mysql data type to the expected flydata type"
315
+ end
316
+ context "timestamp" do
317
+ let(:flydata_type) { 'datetime' }
318
+ it_behaves_like "converting the mysql data type to the expected flydata type"
319
+ end
320
+ context "tinyblob" do
321
+ let(:flydata_type) { 'varbinary(255)' }
322
+ it_behaves_like "converting the mysql data type to the expected flydata type"
323
+ end
324
+ context "tinyint" do
325
+ let(:flydata_type) { 'int1(4)' }
326
+ it_behaves_like "converting the mysql data type to the expected flydata type"
327
+ end
328
+ context "tinytext" do
329
+ let(:flydata_type) { 'text' }
330
+ it_behaves_like "converting the mysql data type to the expected flydata type"
331
+ end
332
+ end
333
+ end
202
334
  end
203
335
 
204
336
  end
@@ -2,16 +2,16 @@
2
2
  # DO NOT EDIT THIS FILE DIRECTLY
3
3
  # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
4
  # -*- encoding: utf-8 -*-
5
- # stub: flydata 0.2.30 ruby lib
5
+ # stub: flydata 0.3.0 ruby lib
6
6
 
7
7
  Gem::Specification.new do |s|
8
8
  s.name = "flydata"
9
- s.version = "0.2.30"
9
+ s.version = "0.3.0"
10
10
 
11
11
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
12
  s.require_paths = ["lib"]
13
13
  s.authors = ["Koichi Fujikawa", "Masashi Miyazaki", "Matthew Luu", "Mak Inada", "Sriram NS"]
14
- s.date = "2015-01-26"
14
+ s.date = "2015-02-11"
15
15
  s.description = "FlyData Agent"
16
16
  s.email = "sysadmin@flydata.com"
17
17
  s.executables = ["fdmysqldump", "flydata", "serverinfo"]
@@ -93,6 +93,7 @@ Gem::Specification.new do |s|
93
93
  "lib/flydata/compatibility_check.rb",
94
94
  "lib/flydata/credentials.rb",
95
95
  "lib/flydata/cron.rb",
96
+ "lib/flydata/errors.rb",
96
97
  "lib/flydata/fluent-plugins/idle_event_detector.rb",
97
98
  "lib/flydata/fluent-plugins/in_mysql_binlog_flydata.rb",
98
99
  "lib/flydata/fluent-plugins/mysql/alter_table_query_handler.rb",
@@ -149,7 +150,7 @@ Gem::Specification.new do |s|
149
150
  ]
150
151
  s.homepage = "http://flydata.com/"
151
152
  s.licenses = ["All right reserved."]
152
- s.rubygems_version = "2.2.2"
153
+ s.rubygems_version = "2.4.3"
153
154
  s.summary = "FlyData Agent"
154
155
 
155
156
  if s.respond_to? :specification_version then
@@ -1,5 +1,6 @@
1
1
  require 'slop'
2
2
  require_relative 'command_logger'
3
+ require_relative 'errors'
3
4
 
4
5
  module Flydata
5
6
  class Cli
@@ -42,15 +43,16 @@ module Flydata
42
43
  cmd_obj = cmd_cls.new(options)
43
44
  sub_cmd ? cmd_obj.send(sub_cmd,*@args) : cmd_obj.run(*@args)
44
45
  else
45
- $stderr.puts usage_text(false)
46
+ $stderr.puts usage_text
46
47
  return
47
48
  end
48
49
  rescue => e
49
50
  #raise e
50
- $stderr.puts "! #{e.to_s}"
51
51
  $stderr.puts
52
52
  $stderr.puts
53
- $stderr.puts usage_text
53
+ $stderr.puts "!! #{e.to_s}"
54
+ $stderr.puts
55
+ $stderr.puts e.respond_to?(:description) ? e.description : AgentError.description
54
56
  log_error_with_backtrace('Error occured during command.', {error: e, args: @args})
55
57
  raise e if FLYDATA_DEBUG
56
58
  exit 1
@@ -93,8 +93,13 @@ What's next?
93
93
  elsif has_registered_redshift_mysql_data_entries?
94
94
  de = retrieve_data_entries.first
95
95
  if File.exists?(Flydata::FileUtil::SyncFileManager.new(de).binlog_path)
96
- Flydata::Command::Sender.new.stop(quiet: true)
97
- true
96
+ sender = Flydata::Command::Sender.new
97
+ if sender.process_exist?
98
+ sender.stop(quiet: true)
99
+ true
100
+ else
101
+ false
102
+ end
98
103
  else
99
104
  last_message = INITIAL_SYNC_MESSAGE_TEMPLATE
100
105
  false
@@ -13,9 +13,11 @@ require 'flydata-core/table_def'
13
13
 
14
14
  module Flydata
15
15
  module Command
16
+
16
17
  class Sync < Base
17
18
  include Helpers
18
19
  INSERT_PROGRESS_INTERVAL = 1000
20
+ SERVER_DATA_PROCESSING_TIMEOUT = 600 # seconds
19
21
 
20
22
  # for dump.pos file
21
23
  STATUS_PARSING = 'PARSING'
@@ -102,8 +104,21 @@ module Flydata
102
104
  de = retrieve_sync_data_entry unless de
103
105
  de = load_sync_info(de,tables)
104
106
  validate_initial_sync_status(de, tables)
105
- flush_buffer_and_stop unless @initial_sync
106
- sync_mysql_to_redshift(de)
107
+ begin
108
+ flush_buffer_and_stop unless @initial_sync
109
+ sync_mysql_to_redshift(de)
110
+ rescue ServerDataProcessingTimeout => e
111
+ ee = ServerDataProcessingTimeout.new("Delayed Data Processing")
112
+ ee.description = <<EOS
113
+ Data processing is taking more than expected. Please contact support@flydata.com to check the system status.
114
+ Once checked, you can resume sync with the following command.
115
+
116
+ flydata start
117
+
118
+ EOS
119
+ ee.set_backtrace e.backtrace
120
+ raise ee
121
+ end
107
122
  complete
108
123
  end
109
124
 
@@ -114,7 +129,17 @@ module Flydata
114
129
  end
115
130
 
116
131
  def flush
117
- flush_buffer_and_stop
132
+ begin
133
+ flush_buffer_and_stop
134
+ rescue ServerDataProcessingTimeout => e
135
+ ee = ServerDataProcessingTimeout.new("Delayed Data Processing")
136
+ ee.description = <<EOS
137
+ Data processing is taking more than expected. Please contact support@flydata.com to check the system status.
138
+
139
+ EOS
140
+ ee.set_backtrace e.backtrace
141
+ raise ee
142
+ end
118
143
  log_info_stdout("Buffers have been flushed and the sender process has been stopped.")
119
144
  end
120
145
 
@@ -136,7 +161,20 @@ module Flydata
136
161
  all_tables = de['mysql_data_entry_preference']['tables']
137
162
  verify_input_tables(tables, all_tables)
138
163
 
139
- wait_for_server_buffer
164
+ begin
165
+ wait_for_server_buffer(SERVER_DATA_PROCESSING_TIMEOUT)
166
+ rescue ServerDataProcessingTimeout => e
167
+ ee = ServerDataProcessingTimeout.new("Delayed Data Processing")
168
+ ee.description = <<EOS
169
+ Data processing is taking more than expected. Please contact support@flydata.com to check the system status.
170
+ Once checked, you can continue sync reset with the following command
171
+
172
+ flydata sync:reset #{tables.empty? ? '' : tables.join(" ")}
173
+
174
+ EOS
175
+ ee.set_backtrace e.backtrace
176
+ raise ee
177
+ end
140
178
  cleanup_sync_server(de, tables) unless opts.client?
141
179
  sync_fm = Flydata::FileUtil::SyncFileManager.new(de)
142
180
  delete_files = [
@@ -158,25 +196,41 @@ module Flydata
158
196
  log_info_stdout("Reset completed successfully.")
159
197
  end
160
198
 
161
- def wait_for_server_buffer
199
+ def wait_for_server_buffer(timeout = 0)
200
+ start_time = Time.now
162
201
  log_info_stdout("Waiting for the server buffer to get empty.")
202
+ prev_message =nil
163
203
  while (status = check) && (status['state'] == 'processing')
204
+ prev_message = status['message']
205
+ if timeout > 0 && Time.now - start_time > timeout
206
+ raise ServerDataProcessingTimeout.new
207
+ end
164
208
  print_progress(status)
165
209
  sleep 10
166
210
  end
167
211
  end
168
212
 
169
- def wait_for_server_data_processing
213
+ def wait_for_server_data_processing(timeout = 0)
170
214
  state = :PROCESS
215
+ start_time = Time.now
171
216
  log_info_stdout("Uploading data to Redshift...")
172
217
  sleep 10
173
218
  status = nil
219
+ prev_message =nil
174
220
  while (status = check)
175
221
  if state == :PROCESS && status['state'] == 'uploading'
176
222
  log_info_stdout(" -> Done")
177
223
  state = :UPLOAD
178
224
  log_info_stdout("Finishing data upload...")
179
225
  end
226
+ if status['message'] != prev_message
227
+ # making some progress. Reset timer
228
+ start_time = Time.now
229
+ end
230
+ prev_message = status['message']
231
+ if timeout > 0 && Time.now - start_time > timeout
232
+ raise ServerDataProcessingTimeout.new
233
+ end
180
234
  print_progress(status)
181
235
  sleep 10
182
236
  end
@@ -606,7 +660,7 @@ EOM
606
660
  return unless dump_pos_info[:status] == STATUS_WAITING
607
661
  binlog_pos = dump_pos_info[:binlog_pos]
608
662
 
609
- wait_for_server_data_processing
663
+ wait_for_server_data_processing(SERVER_DATA_PROCESSING_TIMEOUT)
610
664
  tables = de['mysql_data_entry_preference']['tables']
611
665
  sync_fm.save_table_binlog_pos(tables, binlog_pos)
612
666
  sync_fm.save_dump_pos(STATUS_COMPLETE, '', -1, binlog_pos)
@@ -670,7 +724,7 @@ Thank you for using FlyData!
670
724
  def flush_buffer_and_stop
671
725
  sender = Flydata::Command::Sender.new
672
726
  sender.flush_client_buffer
673
- wait_for_server_data_processing
727
+ wait_for_server_data_processing(SERVER_DATA_PROCESSING_TIMEOUT)
674
728
  sender.stop(quiet: true)
675
729
  end
676
730
  end
@@ -137,8 +137,8 @@ module Flydata
137
137
  end
138
138
  end
139
139
 
140
- def check_mysql_row_mode_compat
141
- sys_var_to_check = {'@@binlog_format'=>'ROW', '@@binlog_checksum'=>'NONE', '@@log_bin_use_v1_row_events'=>1}
140
+ def check_mysql_parameters_compat
141
+ sys_var_to_check = {'@@binlog_format'=>'ROW', '@@binlog_checksum'=>'NONE', '@@log_bin_use_v1_row_events'=>1, '@@log_slave_updates'=>1}
142
142
  errors={}
143
143
 
144
144
  client = Mysql2::Client.new(@db_opts)
@@ -0,0 +1,34 @@
1
+ module Flydata
2
+
3
+ class AgentError < StandardError
4
+ def self.description
5
+ text = <<-EOM
6
+ Fix the issue and try again. If the problem continues, please contact support@flydata.com
7
+
8
+ EOM
9
+
10
+ flydata_log = File.join(FLYDATA_HOME, 'flydata.log')
11
+ if File.exists?(flydata_log)
12
+ text += <<-EOM
13
+ Also check the Agent log.
14
+ Log path: #{flydata_log}
15
+ EOM
16
+ end
17
+ text
18
+ end
19
+
20
+ def description
21
+ if instance_variable_defined?(:@description) && @description
22
+ @description
23
+ else
24
+ self.class.description
25
+ end
26
+ end
27
+
28
+ attr_writer :description
29
+ end
30
+
31
+ class ServerDataProcessingTimeout < AgentError
32
+ end
33
+
34
+ end
@@ -3,6 +3,7 @@ require_relative 'binlog_record_handler'
3
3
  module Mysql
4
4
  class DmlRecordHandler < BinlogRecordHandler
5
5
  ROW = :row
6
+ OLD = :old
6
7
  INTEGER_TYPES = {'TINY' => 1,
7
8
  'SHORT' => 2,
8
9
  'INT24' => 3,
@@ -36,7 +37,8 @@ module Mysql
36
37
 
37
38
  def emit_update(record)
38
39
  emit_rows(:update, record) do |row|
39
- row.last # For update, row has two arrays (old and new values) Use new values
40
+ # For update, row has two arrays (old and new values)
41
+ { OLD => row.first, ROW => row.last }
40
42
  end
41
43
  end
42
44
 
@@ -44,10 +46,13 @@ module Mysql
44
46
  emit_record(type, record) do |opt|
45
47
  table_name = record['table_name']
46
48
  records = record["rows"].collect do |row|
47
- row = yield(row) if block_given? # Give the caller a chance to generate the correct row
48
- { ROW => convert_to_flydata_row_format(table_name, row) }
49
+ row_values = { ROW => row }
50
+ row_values = yield(row) if block_given? # Give the caller a chance to generate the correct row values
51
+ row_types = row_values.keys
52
+ row_kinds = row_types.inject({}) {|m, k| m[k] = convert_to_flydata_row_format(table_name, row_values[k]); m}
53
+ encode_signless_integer(row_kinds, record["columns"], row_types)
54
+ row_kinds
49
55
  end
50
- encode_signless_integer(records, record["columns"])
51
56
  records
52
57
  end
53
58
  end
@@ -70,19 +75,19 @@ module Mysql
70
75
  end
71
76
  end
72
77
 
73
- def encode_signless_integer(records, column_types)
74
- records.each do |record|
75
- record[ROW].keys.each do |position|
78
+ def encode_signless_integer(record, column_types, row_types)
79
+ row_types.each do |row_type|
80
+ record[row_type].keys.each do |position|
76
81
  index = position.to_i - 1
77
82
  column_type = column_types[index]
78
83
  if INTEGER_TYPES.keys.include?(column_type)
79
84
  # It's a signless integer.
80
- intval = record[ROW][position]
85
+ intval = record[row_type][position]
81
86
  next unless (intval.kind_of?(Numeric) || intval =~ /^-?[\d]+$/)
82
87
  width = INTEGER_TYPES[column_type] * 2 # * 2 because a single byte requires two characters (e.g. ff)
83
88
  signless_val = SIGNLESS_INTEGER_PREFIX
84
89
  signless_val += sprintf("%0#{width}x", intval).gsub(/\.\.f/, 'f' * width).slice(-width..-1)
85
- record[ROW][position] = signless_val
90
+ record[row_type][position] = signless_val
86
91
  end
87
92
  end
88
93
  end
@@ -12,25 +12,9 @@ module Flydata
12
12
  [klass, method]
13
13
  end
14
14
 
15
- def usage_text(err = true)
15
+ def usage_text
16
16
  text = ""
17
17
 
18
- if err
19
- text += <<-EOM
20
- Fix the issue and try again. If the problem continues, please contact support@flydata.com
21
-
22
- EOM
23
-
24
- flydata_log = File.join(FLYDATA_HOME, 'flydata.log')
25
- if File.exists?(flydata_log)
26
- text += <<-EOM
27
- Also check the Agent log.
28
- Log path: #{flydata_log}
29
- EOM
30
- end
31
- end
32
-
33
- text += ""
34
18
  text += '-' * 64
35
19
  text += "\n"
36
20
  text += <<-EOM
@@ -27,7 +27,7 @@ module Flydata
27
27
  context 'with options' do
28
28
  let(:options) { %w(-a --host-name localhost) }
29
29
  it 'returns with an error' do
30
- expect($stderr).to receive(:puts).with('! Unknown options -a, --host-name').once
30
+ expect($stderr).to receive(:puts).with('!! Unknown options -a, --host-name').once
31
31
  allow($stderr).to receive(:puts)
32
32
 
33
33
  expect{ subject.run }.to terminate.with_code(1)
@@ -62,7 +62,7 @@ module Flydata
62
62
  context 'with optionss' do
63
63
  let(:options) { %w(-a --host-name localhost) }
64
64
  it 'returns an error' do
65
- expect($stderr).to receive(:puts).with('! Unknown options -a, --host-name').once
65
+ expect($stderr).to receive(:puts).with('!! Unknown options -a, --host-name').once
66
66
  allow($stderr).to receive(:puts)
67
67
 
68
68
  expect{ subject.run }.to terminate.with_code(1)
@@ -164,9 +164,10 @@ EOT
164
164
  rows = [rows] unless rows.kind_of?(Array)
165
165
  @seq ||= TEST_SEQUENCE_NUM
166
166
  records = rows.collect do |row|
167
+ record = row.kind_of?(Hash) && row.keys.include?(:row) ? row : { row: row }
167
168
  @seq += 1
168
- { :type=>type, :table_name=>table, :respect_order=>true, :seq=>@seq,
169
- :src_pos=>"#{binlog_file}\t#{position}", :table_rev=>1, :row=>row }
169
+ record.merge({ :type=>type, :table_name=>table, :respect_order=>true,
170
+ :seq=>@seq, :src_pos=>"#{binlog_file}\t#{position}", :table_rev=>1 })
170
171
  end
171
172
  expect_emitted_records(event, records)
172
173
  end
@@ -289,21 +290,30 @@ EOT
289
290
  context 'when received update event' do
290
291
  it do
291
292
  expect_emitted_records_with_rows(update_event, :update, TEST_TABLE, 2528, "mysql-bin.000048",
292
- [{"1"=>"0SL00000001", "2"=>"wow"}, {"1"=>"0SL00000003", "2"=>"fuga"}])
293
+ [{old:{"1"=>"0SL00000001", "2"=>"foo"},
294
+ row:{"1"=>"0SL00000001", "2"=>"wow"}},
295
+ {old:{"1"=>"0SL00000003", "2"=>"hoge"},
296
+ row:{"1"=>"0SL00000003", "2"=>"fuga"}}])
293
297
  end
294
298
  end
295
299
 
296
300
  context 'when received update event with two byte utf8 chars' do
297
301
  it do
298
302
  expect_emitted_records_with_rows(update_two_byte_event, :update, TEST_TABLE, 2528, "mysql-bin.000048",
299
- [{"1"=>"0SL00000001", "2"=>"∑ø∑"}, {"1"=>"0SL00000003", "2"=>"fügå"}])
303
+ [{old:{"1"=>"0SL00000001", "2"=>"føø"},
304
+ row:{"1"=>"0SL00000001", "2"=>"∑ø∑"}},
305
+ {old:{"1"=>"0SL00000003", "2"=>"høgé"},
306
+ row:{"1"=>"0SL00000003", "2"=>"fügå"}}])
300
307
  end
301
308
  end
302
309
 
303
310
  context 'when received update event with three byte utf8 chars' do
304
311
  it do
305
312
  expect_emitted_records_with_rows(update_three_byte_event, :update, TEST_TABLE, 2528, "mysql-bin.000048",
306
- [{"1"=>"0SL00000001", "2"=>"很兴奋"}, {"1"=>"0SL00000003", "2"=>"興奮虎"}])
313
+ [{old:{"1"=>"0SL00000001", "2"=>"富无无"},
314
+ row:{"1"=>"0SL00000001", "2"=>"很兴奋"}},
315
+ {old:{"1"=>"0SL00000003", "2"=>"切实切实"},
316
+ row:{"1"=>"0SL00000003", "2"=>"興奮虎"}}])
307
317
  end
308
318
  end
309
319
 
@@ -317,7 +327,7 @@ EOT
317
327
  table_rev: 2, # increment revision
318
328
  seq: 2,
319
329
  actions: [{
320
- action: :add_column, column: "sum", :type=>'int4', :query=>'add column sum integer'}],
330
+ action: :add_column, column: "sum", :type=>'int4(11)', :query=>'add column sum integer'}],
321
331
  })
322
332
  end
323
333
  end
@@ -395,7 +405,10 @@ EOT
395
405
  it 'logs a warning and emits FET with a blank binlog file name, when it receives an update event' do
396
406
  expect($log).to receive(:warn).with("Binlog file name is empty. Rotate event not received!").once
397
407
  expect_emitted_records_with_rows(update_event, :update, TEST_TABLE, 2528, "",
398
- [{"1"=>"0SL00000001", "2"=>"wow"}, {"1"=>"0SL00000003", "2"=>"fuga"}])
408
+ [{old:{"1"=>"0SL00000001", "2"=>"foo"},
409
+ row:{"1"=>"0SL00000001", "2"=>"wow"}},
410
+ {old:{"1"=>"0SL00000003", "2"=>"hoge"},
411
+ row:{"1"=>"0SL00000003", "2"=>"fuga"}}])
399
412
  end
400
413
 
401
414
  it 'logs a warning emits FET with a blank binlog file name, when it receives a delete event' do
@@ -409,7 +422,10 @@ EOT
409
422
  expect_emitted_records_with_rows(insert_event, :insert, TEST_TABLE, 628, "",
410
423
  [{"1"=>"0SL00000001", "2"=>"foo"}, {"1"=>"0SL00000002", "2"=>"var"}, {"1"=>"0SL00000003", "2"=>"hoge"}])
411
424
  expect_emitted_records_with_rows(update_event, :update, TEST_TABLE, 2528, "",
412
- [{"1"=>"0SL00000001", "2"=>"wow"}, {"1"=>"0SL00000003", "2"=>"fuga"}])
425
+ [{old:{"1"=>"0SL00000001", "2"=>"foo"},
426
+ row:{"1"=>"0SL00000001", "2"=>"wow"}},
427
+ {old:{"1"=>"0SL00000003", "2"=>"hoge"},
428
+ row:{"1"=>"0SL00000003", "2"=>"fuga"}}])
413
429
  expect_emitted_records_with_rows(insert_event, :insert, TEST_TABLE, 628, "",
414
430
  [{"1"=>"0SL00000001", "2"=>"foo"}, {"1"=>"0SL00000002", "2"=>"var"}, {"1"=>"0SL00000003", "2"=>"hoge"}])
415
431
  expect_emitted_records_with_rows(delete_event, :delete, TEST_TABLE, 5324, "",
@@ -475,7 +491,7 @@ EOT
475
491
  event = update_event
476
492
  event['table_name'] = TEST_TABLE_APPEND_ONLY
477
493
  expect_emitted_records_with_rows(event, :update, TEST_TABLE_APPEND_ONLY, 2528, "mysql-bin.000048",
478
- [{"1"=>"0SL00000001", "2"=>"wow"}, {"1"=>"0SL00000003", "2"=>"fuga"}])
494
+ [{old:{"1"=>"0SL00000001", "2"=>"foo"}, row:{"1"=>"0SL00000001", "2"=>"wow"}}, {old:{"1"=>"0SL00000003", "2"=>"hoge"}, row:{"1"=>"0SL00000003", "2"=>"fuga"}}])
479
495
  end
480
496
 
481
497
  it 'emits a record when it receives a delete event for non-append only table' do
@@ -136,7 +136,7 @@ describe 'MysqlAlterTableParser' do
136
136
  },{
137
137
  action: :add_column,
138
138
  column: "value2",
139
- type: "int4",
139
+ type: "int4(11)",
140
140
  auto_increment: true,
141
141
  query: "add (value1 varchar(26) not null default 'flydata', value2 int auto_increment)"
142
142
  }]
@@ -160,7 +160,7 @@ describe 'MysqlAlterTableParser' do
160
160
  },{
161
161
  action: :add_column,
162
162
  column: "value2",
163
- type: "int4",
163
+ type: "int4(11)",
164
164
  auto_increment: true,
165
165
  query: "add (`value1` varchar(26) not null default 'flydata', `value2` int auto_increment)"
166
166
  }]
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: flydata
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.30
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Koichi Fujikawa
@@ -12,7 +12,7 @@ authors:
12
12
  autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2015-01-26 00:00:00.000000000 Z
15
+ date: 2015-02-11 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: rest-client
@@ -496,6 +496,7 @@ files:
496
496
  - lib/flydata/compatibility_check.rb
497
497
  - lib/flydata/credentials.rb
498
498
  - lib/flydata/cron.rb
499
+ - lib/flydata/errors.rb
499
500
  - lib/flydata/fluent-plugins/idle_event_detector.rb
500
501
  - lib/flydata/fluent-plugins/in_mysql_binlog_flydata.rb
501
502
  - lib/flydata/fluent-plugins/mysql/alter_table_query_handler.rb
@@ -569,7 +570,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
569
570
  version: '0'
570
571
  requirements: []
571
572
  rubyforge_project:
572
- rubygems_version: 2.2.2
573
+ rubygems_version: 2.4.3
573
574
  signing_key:
574
575
  specification_version: 4
575
576
  summary: FlyData Agent