flydata 0.5.13 → 0.5.14

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: d4b03db81cb7465b262dce0c4c8e33a14b5e290b
4
- data.tar.gz: 42c08437e1b5f0d8452f2f2504666d6ce83006a7
3
+ metadata.gz: b2ba68dee697e96ae4e45d7c4ab93da8bfdd0bd9
4
+ data.tar.gz: 5a85b888bf9151233e6163bf825ce52865b5d218
5
5
  SHA512:
6
- metadata.gz: 6de4243e12d2ec8d0c0c62a68a21fd9f1bef9f5a40caebe494687656ab5714d1d88e56ff7aa091796c52a57321e74e6c287ddab02e3968a0029e0203ff3ea47a
7
- data.tar.gz: 910e524b426859dae7e5996bf25148aedf2eebea36decbc602965b483d8cf010ff224e998707c6d35bac7f80036ff0f609ef6dfd88410bf562700d967ad30b34
6
+ metadata.gz: 2ba24a57fee86c3e979c7acf571f73a1d8f12dfc0810f7925d34dd3b7c5d63ddee4d65bc8c2299e204224b93d3a0ab3cfd013dbab3425048e7d1c232328c7658
7
+ data.tar.gz: 0cd58ad653a31e062deb6801bd682cde6940ea2d1c8e8758f72304bd527dbd9549ceaf39ec594f3893f86ca2fa49683b18928ee13bde50b6a2929391df92c6ad
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.5.13
1
+ 0.5.14
@@ -6,7 +6,7 @@ value:
6
6
  " ", "\t", "\n", "," => :value
7
7
  "'" => :first_char
8
8
  "0" => (mark), :first_zero
9
- [1-9-] => (mark), :number
9
+ [1-9-+\.] => (mark), :number
10
10
  "N" => :null_n
11
11
  ")" => (row_end_callback), :start
12
12
  else => :error
@@ -29,7 +29,7 @@ leading_zero:
29
29
  else => :error
30
30
 
31
31
  number:
32
- [0-9.] => :number
32
+ [0-9.-eE] => :number
33
33
  "," => (value_callback, :end_value)(mark reset), :value
34
34
  ")" => (value_callback, :end_value)(mark reset)(row_end_callback), :start
35
35
  else => :error
@@ -62,7 +62,7 @@ long parse_insert_query(const char* sql, long len, ParserCallbackHandler& ch)
62
62
  } else if (*current == '0') {
63
63
  mark = current; value_len = 1;//mark
64
64
  status = first_zero;
65
- } else if ( (*current >= '1' && *current <= '9') || *current == '-' ) {
65
+ } else if ( (*current >= '1' && *current <= '9') || *current == '-' || *current == '+' || *current == '.') {
66
66
  mark = current; value_len = 1;//mark
67
67
  status = number;
68
68
  } else if (*current == ',') {
@@ -127,7 +127,7 @@ long parse_insert_query(const char* sql, long len, ParserCallbackHandler& ch)
127
127
 
128
128
  case number:
129
129
  if ($DEBUG) std::cout << "number[" << *current << "]: " << std::endl << std::flush;
130
- if ((*current >= '0' && *current <= '9') || *current == '.') {
130
+ if ((*current >= '0' && *current <= '9') || *current == '.' || *current == 'e' || *current == 'E' || *current == '-') {
131
131
  status = number;
132
132
  } else if (*current == ',') {
133
133
  ch.value_callback(mark, value_len - 1, true);//value_callback :end_value
@@ -389,10 +389,12 @@ long parse_insert_query(const char* sql, long len, ParserCallbackHandler& ch)
389
389
  ch.value_callback("\x1a", 1, false);//value_callback '\Z'
390
390
  mark = 0; value_len = 0;
391
391
  status = first_char;
392
- } else if (*current == '0') {
393
- ch.value_callback("\0", 1, false);//value_callback '\0'
394
- mark = 0; value_len = 0;
395
- status = first_char;
392
+ // Disabled handling of \0 for now in order to keep it compatible with the old
393
+ // implementation.
394
+ // } else if (*current == '0') {
395
+ // ch.value_callback("\0", 1, false);//value_callback '\0'
396
+ // mark = 0; value_len = 0;
397
+ // status = first_char;
396
398
  } else {
397
399
  status = following_char;
398
400
  }
@@ -51,9 +51,10 @@ module FlydataCore
51
51
  default_option = nil if default_option == ''
52
52
 
53
53
  custom_option = option[:custom_option]
54
+ custom_option_end = option[:custom_option_end] # put in the end of the command
54
55
 
55
56
  [command, host, port, username, password, default_option,
56
- custom_option, database, tables].compact.join(' ')
57
+ custom_option, database, tables, custom_option_end].compact.join(' ')
57
58
  end
58
59
 
59
60
  # DDL_DUMP_CMD_TEMPLATE = "MYSQL_PWD=\"%s\" mysqldump --protocol=tcp -d -h %s -P %s -u %s %s %s"
@@ -114,6 +114,13 @@ module FlydataCore
114
114
  'mysql -h test-host -P 3306 -utestuser -ptestpassword --default-character-set=utf8 --protocol=tcp --skip-auto-rehash -e "SHOW GRANTS;" testdb'
115
115
  ) }
116
116
  end
117
+
118
+ context 'when custom_option_end is set' do
119
+ before { option[:custom_option_end] = 'test_table' }
120
+ it { is_expected.to eq(
121
+ 'mysqldump -h test-host -P 3306 -utestuser -ptestpassword --default-character-set=utf8 --protocol=tcp testdb test_table'
122
+ ) }
123
+ end
117
124
  end
118
125
 
119
126
  describe '.generate_mysql_ddl_dump_cmd' do
data/flydata.gemspec CHANGED
Binary file
@@ -1,38 +1,10 @@
1
- require 'open3'
2
1
  require 'flydata/command/sync'
3
- require 'flydata-core/mysql/command_generator'
2
+ require 'flydata/command/mysql_command_base'
4
3
 
5
4
  module Flydata
6
5
  module Command
7
-
8
6
  class Mysql < Sync
9
- def run
10
- de = retrieve_sync_data_entry
11
- de['mysql_data_entry_preference'].delete('tables')
12
- cmd = FlydataCore::Mysql::CommandGenerator::generate_mysql_cmd(de['mysql_data_entry_preference'])
13
- if $stdin.tty?
14
- # interactive shell
15
- system cmd
16
- else
17
- # execute queries given to $stdin
18
- Open3.popen2e(cmd) do |i, o, wt|
19
- $stdin.each_line do |line|
20
- i.print line
21
- end
22
- i.close
23
- while line = o.gets
24
- print line
25
- end
26
- end
27
- end
28
- end
29
-
30
- def flush; end
31
- def reset; end
32
- def skip; end
33
- def generate_table_ddl; end
34
- def fix_binlogpos; end
7
+ include MysqlCommandBase
35
8
  end
36
-
37
9
  end
38
10
  end
@@ -0,0 +1,46 @@
1
+ require 'open3'
2
+ require 'flydata-core/mysql/command_generator'
3
+
4
+ module Flydata
5
+ module Command
6
+
7
+ module MysqlCommandBase
8
+ def run(*args)
9
+ de = retrieve_sync_data_entry
10
+ cmd = generate_command(de['mysql_data_entry_preference'], args)
11
+ return if cmd.to_s.empty?
12
+ $stderr.puts "command:#{cmd}" if FLYDATA_DEBUG
13
+ if $stdin.tty?
14
+ # interactive shell
15
+ system cmd
16
+ else
17
+ # execute queries given to $stdin
18
+ Open3.popen2e(cmd) do |i, o, wt|
19
+ $stdin.each_line do |line|
20
+ i.print line
21
+ end
22
+ i.close
23
+ while line = o.gets
24
+ print line
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ def generate_command(dbconf, args)
31
+ dbconf.delete('tables')
32
+ dbconf[:custom_option_end] = args.join(' ')
33
+ FlydataCore::Mysql::CommandGenerator::generate_mysql_cmd(dbconf)
34
+ end
35
+
36
+ def flush; end
37
+ def reset; end
38
+ def skip; end
39
+ def generate_table_ddl; end
40
+ def fix_binlogpos; end
41
+ end
42
+
43
+ end
44
+ end
45
+
46
+
@@ -0,0 +1,33 @@
1
+ require 'flydata/command/sync'
2
+ require 'flydata/command/mysql_command_base'
3
+
4
+ module Flydata
5
+ module Command
6
+ class Mysqlbinlog < Sync
7
+ include MysqlCommandBase
8
+
9
+ def generate_command(dbconf, args)
10
+ dbconf.delete('tables')
11
+ dbconf[:custom_option_end] = args.join(' ')
12
+ dbconf[:command] = 'mysqlbinlog'
13
+ # --default-character-set=utf8 is not supported
14
+ dbconf[:no_default_option] = true
15
+ # ssl is not supported for mysql5.6 or older mysqlbinlog command
16
+ dbconf.delete('ssl_ca')
17
+ dbconf.delete('ssl_cipher')
18
+ dbconf.delete('database')
19
+ if args.empty?
20
+ puts <<EOT
21
+ example:
22
+ 1. Dump raw binlog
23
+ flydata mysqlbinlog --raw --read-from-remote-server --result-file "binlog-" mysql-bin-changelog.xxxx
24
+ 2. Dump decoded binlog data
25
+ flydata mysqlbinlog -vv --base64-output=decode-row --hexdump --read-from-remote-server --start-position=4 --stop-position=yyyyy mysql-bin-changelog.xxxxx > mysql-bin-changelog.xxxxx
26
+ EOT
27
+ return
28
+ end
29
+ FlydataCore::Mysql::CommandGenerator::generate_mysql_cmd(dbconf)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,17 @@
1
+ require 'flydata/command/sync'
2
+ require 'flydata/command/mysql_command_base'
3
+
4
+ module Flydata
5
+ module Command
6
+ class Mysqldump < Sync
7
+ include MysqlCommandBase
8
+
9
+ def generate_command(dbconf, args)
10
+ dbconf.delete('tables')
11
+ dbconf[:custom_option_end] = args.join(' ')
12
+ dbconf[:command] = 'mysqldump'
13
+ FlydataCore::Mysql::CommandGenerator::generate_mysql_cmd(dbconf)
14
+ end
15
+ end
16
+ end
17
+ end
@@ -18,7 +18,7 @@ require 'flydata-core/table_def'
18
18
  require 'flydata-core/mysql/binlog_pos'
19
19
  require 'flydata/mysql/table_ddl'
20
20
  require 'flydata-core/mysql/command_generator'
21
- #require 'ruby-prof'
21
+ #require 'ruby-prof' # to enable profiling, also set the class' RUN_PROFILE
22
22
 
23
23
  module Flydata
24
24
  module Command
@@ -26,6 +26,8 @@ module Flydata
26
26
  class Sync < Base
27
27
  include Helpers
28
28
 
29
+ RUN_PROFILE = false
30
+
29
31
  INSERT_PROGRESS_INTERVAL = 1000
30
32
  SERVER_DATA_PROCESSING_TIMEOUT = 3600 # seconds
31
33
 
@@ -784,6 +786,7 @@ EOM
784
786
 
785
787
  begin
786
788
  threads = []
789
+ RubyProf.start if RUN_PROFILE and defined?(RubyProf) and not RubyProf.running?
787
790
  Flydata::Parser::Mysql::MysqlDumpParser.new(option).parse(
788
791
  mysqldump_io,
789
792
  # create table
@@ -792,12 +795,13 @@ EOM
792
795
  # dump mysql_table for resume
793
796
  #TODO: make it option
794
797
  sync_fm.save_mysql_table_marshal_dump(mysql_table)
798
+ mysql_table.set_value_converters(FlydataCore::TableDef::MysqlTableDef::VALUE_CONVERTERS)
795
799
  },
796
800
  # insert record
797
801
  Proc.new { |mysql_table, values_set|
798
802
  mysql_table_name = mysql_table.table_name
799
803
  records = values_set.collect do |values|
800
- values = convert_to_flydata_values(mysql_table, values)
804
+ convert_to_flydata_values(mysql_table, values)
801
805
  json = JSON.generate_kv_pairs(mysql_table.column_names, values)
802
806
  {table_name: mysql_table_name, log: json}
803
807
  end
@@ -839,6 +843,14 @@ EOM
839
843
  ee.description = " Please contact support@flydata.com to report the issue."
840
844
  ee.set_backtrace e.backtrace
841
845
  raise ee
846
+ ensure
847
+ if RUN_PROFILE and defined?(RubyProf) and RubyProf.running?
848
+ result = RubyProf.stop
849
+ #printer = RubyProf::GraphPrinter.new(result)
850
+ printer = RubyProf::GraphHtmlPrinter.new(result)
851
+ #printer.print(STDOUT)
852
+ printer.print(File.new("ruby-prof-out-#{Time.now.to_i}.html", "w"), :min_percent => 3)
853
+ end
842
854
  end
843
855
  forwarder.close
844
856
  log_info_stdout(" -> Done")
@@ -985,15 +997,12 @@ EOM
985
997
  end
986
998
 
987
999
  def convert_to_flydata_values(mysql_table, values)
988
- types = mysql_table.format_types
989
- sz = types.size
990
- result = []
991
- i = 0
992
- while i < sz
993
- result << FlydataCore::TableDef::MysqlTableDef.convert_to_flydata_value(values[i], types[i])
994
- i += 1
1000
+ vc = mysql_table.value_converters
1001
+ return if vc.empty?
1002
+
1003
+ vc.each_pair do |index, converter|
1004
+ values[index] = converter.call(values[index])
995
1005
  end
996
- result
997
1006
  end
998
1007
 
999
1008
  def generate_json(column_names, values)
@@ -3,6 +3,7 @@ require 'io/wait'
3
3
  require 'mysql2'
4
4
  require 'flydata-core/mysql/config'
5
5
  require 'flydata-core/mysql/command_generator'
6
+ #require 'ruby-prof' # to enable profiling, also set the class' RUN_PROFILE
6
7
 
7
8
  module Flydata
8
9
  module Parser
@@ -33,18 +34,26 @@ module Flydata
33
34
  @table_name = table_name
34
35
  @columns = columns
35
36
  @column_names = columns.collect{|k,v| v[:column_name]}
36
- @format_types = columns.collect{|k,v| v[:format_type]}
37
37
  @primary_keys = primary_keys
38
+ @value_converters = {}
38
39
  end
39
40
 
40
- attr_accessor :table_name, :columns, :column_names, :format_types,
41
- :primary_keys
41
+ attr_accessor :table_name, :columns, :column_names, :primary_keys
42
+ attr_reader :value_converters
42
43
 
43
44
  def add_column(column)
44
45
  cn = column[:column_name]
45
46
  @columns[cn] = column
46
47
  @column_names << cn
47
- @format_types << column[:format_type]
48
+ end
49
+
50
+ def set_value_converters(converter_hash)
51
+ @columns.each_with_index do |(k, v), i|
52
+ type = v[:format_type]
53
+ if converter_hash.has_key?(type)
54
+ @value_converters[i] = converter_hash[type]
55
+ end
56
+ end
48
57
  end
49
58
  end
50
59
 
@@ -475,12 +484,14 @@ EOS
475
484
  class InsertParser
476
485
  #INSERT INTO `data_entries` VALUES (2,2,'access_log'), (2,3,'access_log2');
477
486
 
487
+ RUN_PROFILE = false
488
+
478
489
  def start_ruby_prof
479
- RubyProf.start if defined?(RubyProf) and not RubyProf.running?
490
+ RubyProf.start if RUN_PROFILE and defined?(RubyProf) and not RubyProf.running?
480
491
  end
481
492
 
482
493
  def stop_ruby_prof
483
- if defined?(RubyProf) and RubyProf.running?
494
+ if RUN_PROFILE and defined?(RubyProf) and RubyProf.running?
484
495
  result = RubyProf.stop
485
496
  #printer = RubyProf::GraphPrinter.new(result)
486
497
  printer = RubyProf::GraphHtmlPrinter.new(result)
@@ -254,6 +254,10 @@ module Flydata
254
254
  subject { subject_object.send(:convert_to_flydata_values, mysql_table, values) }
255
255
  let(:values) { [4, 'John', nil, col4_value, nil, nil] }
256
256
 
257
+ before do
258
+ mysql_table.set_value_converters(FlydataCore::TableDef::MysqlTableDef::VALUE_CONVERTERS)
259
+ end
260
+
257
261
  context 'with binary column' do
258
262
  let(:col4_type) { "binary" }
259
263
  let(:col4_width) { 5 }
@@ -263,7 +267,8 @@ module Flydata
263
267
  it 'truncates trailing "0" if the type is binary' do
264
268
  expected_values = values.dup
265
269
  expected_values[3] = truncated_binary
266
- is_expected.to eq expected_values
270
+ subject
271
+ expect(values).to eq expected_values
267
272
  end
268
273
  end
269
274
  end
@@ -818,11 +818,9 @@ EOT
818
818
  context 'with a single escape char' do
819
819
  let(:value) { %q|\\0| }
820
820
  #let(:expected_value) { %Q|\0| }
821
- #it 'returns correct chars' do
822
- # expect(subject).to eq([[expected_value]])
823
- #end
824
- it 'returns an error (for now)' do
825
- expect{subject}.to raise_error(ArgumentError)
821
+ let(:expected_value) { value } # this is compatible with the previous implementation but it's actually wrong. For now, keeping it as is because allowing the null character in a string could open a can of worms.
822
+ it 'returns correct chars' do
823
+ expect(subject).to eq([[expected_value]])
826
824
  end
827
825
  end
828
826
  context 'with an escape char followed by a regular char' do
@@ -974,6 +972,49 @@ EOT
974
972
  end
975
973
  end
976
974
 
975
+ context 'when a scientific number is given' do
976
+ let(:target_line) {"INSERT INTO `test_table` VALUES (1,#{num_str});"}
977
+ shared_examples "accepting the value as is" do
978
+ it 'should accept the value as is' do
979
+ expect(subject).to eq([['1', num_str]])
980
+ end
981
+ end
982
+ context 'capital E' do
983
+ let(:num_str) { '1.2E3' }
984
+ it_behaves_like "accepting the value as is"
985
+ end
986
+ context 'lowercase e' do
987
+ let(:num_str) { '1.2e3' }
988
+ it_behaves_like "accepting the value as is"
989
+ end
990
+ context 'negative integer' do
991
+ let(:num_str) { '-1.2e3' }
992
+ it_behaves_like "accepting the value as is"
993
+ end
994
+ context 'negative fractional' do
995
+ let(:num_str) { '1.2e-3' }
996
+ it_behaves_like "accepting the value as is"
997
+ end
998
+ context 'negative integer & fractional' do
999
+ let(:num_str) { '-1.2e-3' }
1000
+ it_behaves_like "accepting the value as is"
1001
+ end
1002
+ end
1003
+
1004
+ context 'when a number with positive sign is given' do
1005
+ let(:target_line) {"INSERT INTO `test_table` VALUES (1,+9.10);"}
1006
+ it 'should accept the value as is' do
1007
+ expect(subject).to eq([['1', '+9.10']])
1008
+ end
1009
+ end
1010
+
1011
+ context 'when a number with no leading zero is given' do
1012
+ let(:target_line) {"INSERT INTO `test_table` VALUES (1,.10);"}
1013
+ it 'should accept the value as is' do
1014
+ expect(subject).to eq([['1', '.10']])
1015
+ end
1016
+ end
1017
+
977
1018
  context 'when 0.00 is given' do
978
1019
  let(:target_line) {"INSERT INTO `test_table` VALUES (1,0.00);"}
979
1020
  it 'should not remove the leading zeros' do
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.5.13
4
+ version: 0.5.14
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-10-26 00:00:00.000000000 Z
15
+ date: 2015-10-28 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: rest-client
@@ -582,6 +582,9 @@ files:
582
582
  - lib/flydata/command/kill_all.rb
583
583
  - lib/flydata/command/login.rb
584
584
  - lib/flydata/command/mysql.rb
585
+ - lib/flydata/command/mysql_command_base.rb
586
+ - lib/flydata/command/mysqlbinlog.rb
587
+ - lib/flydata/command/mysqldump.rb
585
588
  - lib/flydata/command/restart.rb
586
589
  - lib/flydata/command/routine.rb
587
590
  - lib/flydata/command/sender.rb