flydata 0.6.14 → 0.7.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/VERSION +1 -1
- data/flydata-core/Gemfile +1 -0
- data/flydata-core/Gemfile.lock +5 -0
- data/flydata-core/lib/flydata-core/errors.rb +4 -2
- data/flydata-core/lib/flydata-core/mysql/binlog_pos.rb +4 -0
- data/flydata-core/lib/flydata-core/postgresql/compatibility_checker.rb +119 -0
- data/flydata-core/lib/flydata-core/postgresql/config.rb +58 -0
- data/flydata-core/lib/flydata-core/postgresql/pg_client.rb +170 -0
- data/flydata-core/lib/flydata-core/postgresql/snapshot.rb +49 -0
- data/flydata-core/lib/flydata-core/postgresql/source_pos.rb +71 -10
- data/flydata-core/lib/flydata-core/table_def/mysql_table_def.rb +1 -1
- data/flydata-core/lib/flydata-core/table_def/postgresql_table_def.rb +76 -17
- data/flydata-core/lib/flydata-core/table_def/redshift_table_def.rb +59 -10
- data/flydata-core/spec/mysql/binlog_pos_spec.rb +10 -2
- data/flydata-core/spec/postgresql/compatibility_checker_spec.rb +148 -0
- data/flydata-core/spec/postgresql/config_spec.rb +85 -0
- data/flydata-core/spec/postgresql/pg_client_spec.rb +195 -0
- data/flydata-core/spec/postgresql/snapshot_spec.rb +55 -0
- data/flydata-core/spec/postgresql/source_pos_spec.rb +70 -8
- data/flydata-core/spec/table_def/postgresql_table_def_spec.rb +80 -19
- data/flydata-core/spec/table_def/redshift_table_def_spec.rb +211 -14
- data/flydata.gemspec +0 -0
- data/lib/flydata.rb +1 -0
- data/lib/flydata/command/sender.rb +10 -7
- data/lib/flydata/command/sync.rb +4 -1
- data/lib/flydata/fluent-plugins/flydata_plugin_ext/base.rb +1 -0
- data/lib/flydata/fluent-plugins/flydata_plugin_ext/fluent_log_ext.rb +73 -0
- data/lib/flydata/fluent-plugins/flydata_plugin_ext/flydata_sync.rb +35 -10
- data/lib/flydata/fluent-plugins/flydata_plugin_ext/flydata_sync_diff_based.rb +29 -0
- data/lib/flydata/fluent-plugins/flydata_plugin_ext/flydata_sync_query_based.rb +26 -0
- data/lib/flydata/fluent-plugins/flydata_plugin_ext/preference.rb +29 -13
- data/lib/flydata/fluent-plugins/in_mysql_binlog_flydata.rb +10 -18
- data/lib/flydata/fluent-plugins/in_postgresql_query_based_flydata.rb +64 -0
- data/lib/flydata/helpers.rb +1 -3
- data/lib/flydata/plugin_support/context.rb +14 -2
- data/lib/flydata/plugin_support/source_position_file.rb +35 -0
- data/lib/flydata/plugin_support/sync_record_emittable.rb +2 -1
- data/lib/flydata/query_based_sync/client.rb +101 -0
- data/lib/flydata/query_based_sync/record_size_estimator.rb +39 -0
- data/lib/flydata/query_based_sync/resource_requester.rb +70 -0
- data/lib/flydata/query_based_sync/response.rb +122 -0
- data/lib/flydata/query_based_sync/response_handler.rb +30 -0
- data/lib/flydata/source/sync_generate_table_ddl.rb +1 -1
- data/lib/flydata/source_mysql/plugin_support/binlog_record_dispatcher.rb +2 -2
- data/lib/flydata/source_mysql/plugin_support/binlog_record_handler.rb +3 -9
- data/lib/flydata/source_mysql/plugin_support/context.rb +26 -2
- data/lib/flydata/source_mysql/plugin_support/source_position_file.rb +14 -0
- data/lib/flydata/source_mysql/table_ddl.rb +3 -3
- data/lib/flydata/source_mysql/{plugin_support/table_meta.rb → table_meta.rb} +3 -10
- data/lib/flydata/source_postgresql/generate_source_dump.rb +44 -63
- data/lib/flydata/source_postgresql/parse_dump_and_send.rb +2 -0
- data/lib/flydata/source_postgresql/plugin_support/context.rb +13 -0
- data/lib/flydata/source_postgresql/plugin_support/source_position_file.rb +14 -0
- data/lib/flydata/source_postgresql/query_based_sync/client.rb +16 -0
- data/lib/flydata/source_postgresql/query_based_sync/diff_query_generator.rb +135 -0
- data/lib/flydata/source_postgresql/query_based_sync/resource_requester.rb +86 -0
- data/lib/flydata/source_postgresql/query_based_sync/response.rb +12 -0
- data/lib/flydata/source_postgresql/query_based_sync/response_handler.rb +12 -0
- data/lib/flydata/source_postgresql/sync_generate_table_ddl.rb +25 -79
- data/lib/flydata/source_postgresql/table_meta.rb +168 -0
- data/lib/flydata/sync_file_manager.rb +5 -5
- data/lib/flydata/table_meta.rb +19 -0
- data/spec/flydata/fluent-plugins/flydata_plugin_ext/flydata_sync_context.rb +85 -0
- data/spec/flydata/fluent-plugins/flydata_plugin_ext/flydata_sync_diff_based_shared_examples.rb +36 -0
- data/spec/flydata/fluent-plugins/flydata_plugin_ext/flydata_sync_query_based_shared_examples.rb +37 -0
- data/spec/flydata/fluent-plugins/flydata_plugin_ext/flydata_sync_shared_examples.rb +67 -0
- data/spec/flydata/fluent-plugins/in_mysql_binlog_flydata_spec.rb +119 -96
- data/spec/flydata/fluent-plugins/in_postgresql_query_based_flydata_spec.rb +82 -0
- data/spec/flydata/fluent-plugins/sync_source_plugin_context.rb +29 -0
- data/spec/flydata/plugin_support/context_spec.rb +37 -3
- data/spec/flydata/query_based_sync/client_spec.rb +79 -0
- data/spec/flydata/query_based_sync/query_based_sync_context.rb +116 -0
- data/spec/flydata/query_based_sync/record_size_estimator_spec.rb +54 -0
- data/spec/flydata/query_based_sync/resource_requester_spec.rb +58 -0
- data/spec/flydata/query_based_sync/response_handler_spec.rb +36 -0
- data/spec/flydata/query_based_sync/response_spec.rb +157 -0
- data/spec/flydata/source_mysql/plugin_support/context_spec.rb +7 -1
- data/spec/flydata/source_mysql/plugin_support/dml_record_handler_spec.rb +2 -15
- data/spec/flydata/source_mysql/plugin_support/drop_database_query_handler_spec.rb +1 -1
- data/spec/flydata/source_mysql/plugin_support/shared_query_handler_context.rb +12 -11
- data/spec/flydata/source_mysql/plugin_support/source_position_file_spec.rb +53 -0
- data/spec/flydata/source_mysql/plugin_support/truncate_query_handler_spec.rb +1 -1
- data/spec/flydata/source_mysql/table_ddl_spec.rb +5 -5
- data/spec/flydata/source_mysql/{plugin_support/table_meta_spec.rb → table_meta_spec.rb} +6 -7
- data/spec/flydata/source_postgresql/generate_source_dump_spec.rb +165 -77
- data/spec/flydata/source_postgresql/query_based_sync/diff_query_generator_spec.rb +213 -0
- data/spec/flydata/source_postgresql/query_based_sync/query_based_sync_postgresql_context.rb +76 -0
- data/spec/flydata/source_postgresql/query_based_sync/resource_requester_spec.rb +70 -0
- data/spec/flydata/source_postgresql/table_meta_spec.rb +77 -0
- metadata +49 -6
- data/lib/flydata/source_mysql/plugin_support/binlog_position_file.rb +0 -23
- data/lib/flydata/source_postgresql/pg_client.rb +0 -43
@@ -0,0 +1,19 @@
|
|
1
|
+
module Flydata
|
2
|
+
class TableMeta
|
3
|
+
def initialize(opts)
|
4
|
+
@table_meta = {}
|
5
|
+
end
|
6
|
+
|
7
|
+
# Override
|
8
|
+
# Reload table meta info
|
9
|
+
#def reload(db_client)
|
10
|
+
#end
|
11
|
+
|
12
|
+
# Return table meta
|
13
|
+
# :character_set_name
|
14
|
+
def [](table_name)
|
15
|
+
@table_meta[table_name.to_sym]
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
@@ -0,0 +1,85 @@
|
|
1
|
+
require 'timecop'
|
2
|
+
require 'fileutils'
|
3
|
+
|
4
|
+
module Fluent
|
5
|
+
FLYDATA_HOME = Flydata::FLYDATA_HOME
|
6
|
+
TABLE_POSITIONS_DIR = Flydata::FLYDATA_TABLE_POSITIONS_DIR
|
7
|
+
TEST_TAG = "test_tag"
|
8
|
+
TEST_DB = "test_db"
|
9
|
+
TEST_TABLE = "test_table"
|
10
|
+
TEST_SEQUENCE_FILE = File.join(FLYDATA_HOME, "positions/#{TEST_TABLE}.pos")
|
11
|
+
TEST_SEQUENCE_NUM = 1
|
12
|
+
TEST_TABLE_BINLOG_POS = File.join(FLYDATA_HOME, "positions/#{TEST_TABLE}.binlog.pos")
|
13
|
+
TEST_TABLES = "#{TEST_TABLE},test_table_1,test_table_2,test_table_3"
|
14
|
+
TEST_POSITION_FILE = "test_position.binlog.pos"
|
15
|
+
TEST_SENT_POSITION_FILE = "test_position.binlog.sent.pos"
|
16
|
+
TEST_REVISION_FILE = File.join(FLYDATA_HOME, "positions/#{TEST_TABLE}.rev")
|
17
|
+
TEST_TIMESTAMP = 1389214083
|
18
|
+
TEST_TABLE_APPEND_ONLY = "test_table_4"
|
19
|
+
TEST_SEQUENCE_FILE_1 = File.join(FLYDATA_HOME, "positions/#{TEST_TABLE_APPEND_ONLY}.pos")
|
20
|
+
|
21
|
+
shared_context 'flydata sync context' do
|
22
|
+
def create_file(file_path, content)
|
23
|
+
File.open(file_path, 'w') {|f| f.write(content)}
|
24
|
+
end
|
25
|
+
|
26
|
+
def delete_file(file_path)
|
27
|
+
FileUtils.rm(file_path) if File.exists?(file_path)
|
28
|
+
end
|
29
|
+
|
30
|
+
def create_binlog_pos_file(content = '')
|
31
|
+
create_file(TEST_POSITION_FILE, content)
|
32
|
+
end
|
33
|
+
|
34
|
+
def create_table_pos_file(tables, content = '')
|
35
|
+
create_table_file(tables, 'pos', content)
|
36
|
+
end
|
37
|
+
|
38
|
+
def create_table_rev_file(tables, content = '')
|
39
|
+
create_table_file(tables, 'rev', content)
|
40
|
+
end
|
41
|
+
|
42
|
+
def create_table_file(tables, ext, content = '')
|
43
|
+
tables = Array(tables)
|
44
|
+
tables.each do |table|
|
45
|
+
create_file(File.join(FLYDATA_HOME, 'positions', "#{table}.#{ext}"), content)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
def config_value(variable_name, a_plugin = plugin)
|
50
|
+
a_plugin.instance_variable_get(variable_name.to_s)
|
51
|
+
end
|
52
|
+
|
53
|
+
def replace_conf(conf_str, conf_name, new_value)
|
54
|
+
if conf_str.include?(conf_name)
|
55
|
+
conf_str.gsub(/#{conf_name} .*$/, "#{conf_name} #{new_value}")
|
56
|
+
else
|
57
|
+
conf_str += "\n #{conf_name} #{new_value}\n"
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def setup_initial_flydata_dirs
|
62
|
+
%w(positions dump conf).each{|f| FileUtils.mkdir_p(File.join(FLYDATA_HOME, f))}
|
63
|
+
end
|
64
|
+
|
65
|
+
def cleanup_flydata_dirs
|
66
|
+
%w(positions dump conf).each{|f| FileUtils.rm_rf(File.join(FLYDATA_HOME, f))}
|
67
|
+
end
|
68
|
+
|
69
|
+
before do
|
70
|
+
cleanup_flydata_dirs
|
71
|
+
setup_initial_flydata_dirs
|
72
|
+
|
73
|
+
@current_dir_path = Dir::pwd
|
74
|
+
Dir.chdir(FLYDATA_HOME)
|
75
|
+
create_file(TEST_POSITION_FILE, '')
|
76
|
+
end
|
77
|
+
|
78
|
+
after do
|
79
|
+
delete_file(TEST_POSITION_FILE)
|
80
|
+
Dir.chdir(@current_dir_path)
|
81
|
+
|
82
|
+
cleanup_flydata_dirs
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
data/spec/flydata/fluent-plugins/flydata_plugin_ext/flydata_sync_diff_based_shared_examples.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'flydata/fluent-plugins/flydata_plugin_ext/flydata_sync_shared_examples'
|
2
|
+
|
3
|
+
|
4
|
+
module Fluent
|
5
|
+
|
6
|
+
shared_examples 'flydata sync diff based shared examples' do
|
7
|
+
include_examples 'flydata sync shared examples'
|
8
|
+
|
9
|
+
describe '#configure' do
|
10
|
+
let(:config) do
|
11
|
+
c = default_config
|
12
|
+
c = replace_conf(c, 'tables', 'table_1')
|
13
|
+
c = replace_conf(c, 'fetch_interval', '10m')
|
14
|
+
c = replace_conf(c, 'retry_interval', '5m')
|
15
|
+
c = replace_conf(c, 'emit_chunk_limit', '32m')
|
16
|
+
c
|
17
|
+
end
|
18
|
+
|
19
|
+
subject { Test.configure_plugin(plugin, config) }
|
20
|
+
|
21
|
+
before do
|
22
|
+
create_table_pos_file('table_1')
|
23
|
+
subject
|
24
|
+
end
|
25
|
+
|
26
|
+
it { expect(config_value(:@fetch_interval)).to eq(10 * 60) }
|
27
|
+
it { expect(config_value(:@retry_interval)).to eq(5 * 60) }
|
28
|
+
it { expect(config_value(:@emit_chunk_limit)).to eq(32 * 1024**2) }
|
29
|
+
it do
|
30
|
+
expect(config_value(:@table_src_pos_files).size).to eq(1)
|
31
|
+
expect(config_value(:@table_src_pos_files)[:table_1]).to be_kind_of(described_class::SOURCE_POSITION_FILE_CLASS)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
end
|
data/spec/flydata/fluent-plugins/flydata_plugin_ext/flydata_sync_query_based_shared_examples.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'flydata/fluent-plugins/flydata_plugin_ext/flydata_sync_diff_based_shared_examples'
|
2
|
+
|
3
|
+
|
4
|
+
module Fluent
|
5
|
+
|
6
|
+
shared_examples 'flydata sync query based shared examples' do
|
7
|
+
include_examples 'flydata sync diff based shared examples'
|
8
|
+
|
9
|
+
describe '#configure' do
|
10
|
+
let(:config) do
|
11
|
+
c = default_config
|
12
|
+
c = replace_conf(c, 'host', 'test-host')
|
13
|
+
c = replace_conf(c, 'port', '5555')
|
14
|
+
c = replace_conf(c, 'username', 'test-user')
|
15
|
+
c = replace_conf(c, 'password', 'test-pass')
|
16
|
+
c = replace_conf(c, 'database', 'test-db')
|
17
|
+
c = replace_conf(c, 'schema', 'test-schema')
|
18
|
+
c
|
19
|
+
end
|
20
|
+
|
21
|
+
subject { Test.configure_plugin(plugin, config) }
|
22
|
+
|
23
|
+
before do
|
24
|
+
subject
|
25
|
+
end
|
26
|
+
|
27
|
+
it { expect(config_value(:@host)).to eq('test-host') }
|
28
|
+
it { expect(config_value(:@port)).to eq(5555) }
|
29
|
+
it { expect(config_value(:@username)).to eq('test-user') }
|
30
|
+
it { expect(config_value(:@password)).to eq('test-pass') }
|
31
|
+
it { expect(config_value(:@database)).to eq('test-db') }
|
32
|
+
it { expect(config_value(:@schema)).to eq('test-schema') }
|
33
|
+
end
|
34
|
+
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
require 'timecop'
|
2
|
+
require 'fileutils'
|
3
|
+
require 'flydata/fluent-plugins/flydata_plugin_ext/flydata_sync_context'
|
4
|
+
|
5
|
+
module Fluent
|
6
|
+
|
7
|
+
# plugin and config is required
|
8
|
+
shared_examples 'flydata sync shared examples' do
|
9
|
+
include_context 'flydata sync context'
|
10
|
+
|
11
|
+
describe '#configure' do
|
12
|
+
let(:config) do
|
13
|
+
c = default_config
|
14
|
+
c = replace_conf(c, 'tables', 'table_1,table_2')
|
15
|
+
c = replace_conf(c, 'tables_append_only', 'table_3,table_4')
|
16
|
+
c
|
17
|
+
end
|
18
|
+
|
19
|
+
subject { Test.configure_plugin(plugin, config) }
|
20
|
+
|
21
|
+
before do
|
22
|
+
create_table_pos_file(%w(table_1 table_2 table_3))
|
23
|
+
create_table_rev_file('table_1', '2')
|
24
|
+
subject
|
25
|
+
end
|
26
|
+
|
27
|
+
it { expect(config_value(:@data_entry_name)).to be_kind_of(String) }
|
28
|
+
it { expect(config_value(:@data_entry_type)).to be_kind_of(String) }
|
29
|
+
it { expect(config_value(:@tag)).to be_kind_of(String) }
|
30
|
+
it { expect(config_value(:@position_file)).to be_kind_of(String) }
|
31
|
+
|
32
|
+
it 'sets @source_position_file' do
|
33
|
+
expect(config_value(:@source_position_file)).
|
34
|
+
to be_kind_of(described_class::SOURCE_POSITION_FILE_CLASS)
|
35
|
+
end
|
36
|
+
|
37
|
+
it 'sets @sent_position_file' do
|
38
|
+
expect(config_value(:@sent_position_file)).
|
39
|
+
to be_kind_of(described_class::SOURCE_POSITION_FILE_CLASS)
|
40
|
+
end
|
41
|
+
|
42
|
+
it { expect(config_value(:@data_entry)).to have_key('name') }
|
43
|
+
it { expect(config_value(:@data_entry)).to have_key('type') }
|
44
|
+
it { expect(config_value(:@tables)).to be_kind_of(Array) }
|
45
|
+
|
46
|
+
it do
|
47
|
+
expect(config_value(:@tables)).to eq(%w(table_1 table_2 table_3))
|
48
|
+
end
|
49
|
+
|
50
|
+
it do
|
51
|
+
expect(config_value(:@omit_events)).to eq(
|
52
|
+
'table_3' => [:delete, :truncate_table],
|
53
|
+
'table_4' => [:delete, :truncate_table],
|
54
|
+
)
|
55
|
+
end
|
56
|
+
|
57
|
+
it do
|
58
|
+
expect(config_value(:@table_revs)).to eq(
|
59
|
+
'table_1' => 2,
|
60
|
+
'table_2' => 1,
|
61
|
+
'table_3' => 1,
|
62
|
+
)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
@@ -2,40 +2,49 @@
|
|
2
2
|
|
3
3
|
require 'fluent_plugins_spec_helper'
|
4
4
|
require 'in_mysql_binlog_flydata'
|
5
|
-
|
5
|
+
|
6
|
+
require 'flydata/fluent-plugins/flydata_plugin_ext/flydata_sync_shared_examples'
|
6
7
|
|
7
8
|
module Fluent
|
8
9
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
TEST_POSITION_FILE
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
10
|
+
describe MysqlBinlogFlydataInput do
|
11
|
+
let(:plugin) { described_class.new }
|
12
|
+
let(:default_config) { <<EOT
|
13
|
+
data_entry_name test_name
|
14
|
+
data_entry_type RedshiftMysqlDataEntry
|
15
|
+
tag #{TEST_TAG}
|
16
|
+
database #{TEST_DB}
|
17
|
+
tables test_table,test_table_1,test_table_2
|
18
|
+
tables_append_only test_table_3
|
19
|
+
position_file #{TEST_POSITION_FILE}
|
20
|
+
host localhost
|
21
|
+
port 3306
|
22
|
+
username test_admin
|
23
|
+
password test_password
|
24
|
+
database test_db
|
25
|
+
ssl_ca_content
|
26
|
+
ssl_cipher
|
27
|
+
EOT
|
28
|
+
}
|
29
|
+
include_examples 'flydata sync shared examples'
|
30
|
+
|
31
|
+
TEST_CONFIG = <<EOT
|
32
|
+
data_entry_name test_name
|
33
|
+
data_entry_type RedshiftMysqlDataEntry
|
25
34
|
tag #{TEST_TAG}
|
26
35
|
database #{TEST_DB}
|
27
36
|
tables #{TEST_TABLES}
|
28
37
|
tables_append_only
|
29
38
|
position_file #{TEST_POSITION_FILE}
|
30
39
|
EOT
|
31
|
-
|
40
|
+
TEST_TABLES_APPEND_ONLY_CONFIG = <<EOT
|
32
41
|
tag #{TEST_TAG}
|
33
42
|
database #{TEST_DB}
|
34
43
|
tables #{TEST_TABLES}
|
35
44
|
tables_append_only #{TEST_TABLE_APPEND_ONLY}
|
36
45
|
position_file #{TEST_POSITION_FILE}
|
37
46
|
EOT
|
38
|
-
|
47
|
+
TEST_TABLES_DUPLICATE_CONFIG = <<EOT
|
39
48
|
tag #{TEST_TAG}
|
40
49
|
database #{TEST_DB}
|
41
50
|
tables #{TEST_TABLES},#{TEST_TABLE_APPEND_ONLY}
|
@@ -43,105 +52,104 @@ EOT
|
|
43
52
|
position_file #{TEST_POSITION_FILE}
|
44
53
|
EOT
|
45
54
|
|
46
|
-
|
47
|
-
|
55
|
+
# mysqlbinlog event
|
56
|
+
# http://dev.mysql.com/doc/refman/5.7/en/mysqlbinlog-hexdump.html
|
48
57
|
|
49
|
-
|
50
|
-
|
51
|
-
|
58
|
+
# Supported events
|
59
|
+
# - 17 WRITE_ROWS_EVENT
|
60
|
+
TEST_EVENT_INSERT=<<EOT
|
52
61
|
{"marker"=>0, "timestamp"=>#{TEST_TIMESTAMP}, "type_code"=>23, "server_id"=>1, "event_length"=>39, "next_position"=>667, "flags"=>1, "event_type"=>"Write_rows", "table_id"=>163, "db_name"=>"#{TEST_DB}", "table_name"=>"#{TEST_TABLE}", "columns"=>["LONG", "BLOB"], "columns_len"=>2, "null_bits_len"=>1, "raw_columns_before_image"=>[], "raw_used_columns"=>[255], "raw_row"=>[252, 3, 0, 0, 0, 3, 0, 102, 111, 111], "rows"=>[["1", "foo"],["2","var"],["3","hoge"]]}
|
53
62
|
EOT
|
54
|
-
|
63
|
+
TEST_EVENT_TWO_BYTE_INSERT=<<EOT
|
55
64
|
{"marker"=>0, "timestamp"=>#{TEST_TIMESTAMP}, "type_code"=>23, "server_id"=>1, "event_length"=>39, "next_position"=>667, "flags"=>1, "event_type"=>"Write_rows", "table_id"=>163, "db_name"=>"#{TEST_DB}", "table_name"=>"#{TEST_TABLE}", "columns"=>["LONG", "BLOB"], "columns_len"=>2, "null_bits_len"=>1, "raw_columns_before_image"=>[], "raw_used_columns"=>[255], "raw_row"=>[252, 3, 0, 0, 0, 3, 0, 102, 111, 111], "rows"=>[["1", "føø"],["2","vår"],["3","høgé"]]}
|
56
65
|
EOT
|
57
|
-
|
66
|
+
TEST_EVENT_THREE_BYTE_INSERT=<<EOT
|
58
67
|
{"marker"=>0, "timestamp"=>#{TEST_TIMESTAMP}, "type_code"=>23, "server_id"=>1, "event_length"=>39, "next_position"=>667, "flags"=>1, "event_type"=>"Write_rows", "table_id"=>163, "db_name"=>"#{TEST_DB}", "table_name"=>"#{TEST_TABLE}", "columns"=>["LONG", "BLOB"], "columns_len"=>2, "null_bits_len"=>1, "raw_columns_before_image"=>[], "raw_used_columns"=>[255], "raw_row"=>[252, 3, 0, 0, 0, 3, 0, 102, 111, 111], "rows"=>[["1", "富无无"],["2","易变的"],["3","切实切实"]]}
|
59
68
|
EOT
|
60
|
-
|
61
|
-
|
69
|
+
# - 18 UPDATE_ROWS_EVENT
|
70
|
+
TEST_EVENT_UPDATE = <<EOT
|
62
71
|
{"marker"=>0, "timestamp"=>#{TEST_TIMESTAMP}, "type_code"=>24, "server_id"=>1, "event_length"=>78, "next_position"=>2606, "flags"=>1, "event_type"=>"Update_rows", "table_id"=>163, "db_name"=>"#{TEST_DB}", "table_name"=>"#{TEST_TABLE}", "columns"=>["LONG", "BLOB"], "columns_len"=>2, "null_bits_len"=>1, "raw_columns_before_image"=>[255], "raw_used_columns"=>[255], "raw_row"=>[252, 6, 0, 0, 0, 1, 0, 97, 252, 6, 0, 0, 0, 1, 0, 100, 252, 6, 0, 0, 0, 1, 0, 98, 252, 6, 0, 0, 0, 1, 0, 100, 252, 6, 0, 0, 0, 1, 0, 99, 252, 6, 0, 0, 0, 1, 0, 100], "rows"=>[[["1", "foo"], ["1", "wow"]],[["3", "hoge"], ["3", "fuga"]]]}
|
63
72
|
EOT
|
64
|
-
|
73
|
+
TEST_EVENT_TWO_BYTE_UPDATE = <<EOT
|
65
74
|
{"marker"=>0, "timestamp"=>#{TEST_TIMESTAMP}, "type_code"=>24, "server_id"=>1, "event_length"=>78, "next_position"=>2606, "flags"=>1, "event_type"=>"Update_rows", "table_id"=>163, "db_name"=>"#{TEST_DB}", "table_name"=>"#{TEST_TABLE}", "columns"=>["LONG", "BLOB"], "columns_len"=>2, "null_bits_len"=>1, "raw_columns_before_image"=>[255], "raw_used_columns"=>[255], "raw_row"=>[252, 6, 0, 0, 0, 1, 0, 97, 252, 6, 0, 0, 0, 1, 0, 100, 252, 6, 0, 0, 0, 1, 0, 98, 252, 6, 0, 0, 0, 1, 0, 100, 252, 6, 0, 0, 0, 1, 0, 99, 252, 6, 0, 0, 0, 1, 0, 100], "rows"=>[[["1", "føø"], ["1", "∑ø∑"]],[["3", "høgé"], ["3", "fügå"]]]}
|
66
75
|
EOT
|
67
|
-
|
76
|
+
TEST_EVENT_THREE_BYTE_UPDATE = <<EOT
|
68
77
|
{"marker"=>0, "timestamp"=>#{TEST_TIMESTAMP}, "type_code"=>24, "server_id"=>1, "event_length"=>78, "next_position"=>2606, "flags"=>1, "event_type"=>"Update_rows", "table_id"=>163, "db_name"=>"#{TEST_DB}", "table_name"=>"#{TEST_TABLE}", "columns"=>["LONG", "BLOB"], "columns_len"=>2, "null_bits_len"=>1, "raw_columns_before_image"=>[255], "raw_used_columns"=>[255], "raw_row"=>[252, 6, 0, 0, 0, 1, 0, 97, 252, 6, 0, 0, 0, 1, 0, 100, 252, 6, 0, 0, 0, 1, 0, 98, 252, 6, 0, 0, 0, 1, 0, 100, 252, 6, 0, 0, 0, 1, 0, 99, 252, 6, 0, 0, 0, 1, 0, 100], "rows"=>[[["1", "富无无"], ["1", "很兴奋"]],[["3", "切实切实"], ["3", "興奮虎"]]]}
|
69
78
|
EOT
|
70
|
-
|
71
|
-
|
79
|
+
# - 19 DELETE_ROWS_EVENT
|
80
|
+
TEST_EVENT_DELETE = <<EOT
|
72
81
|
{"marker"=>0, "timestamp"=>#{TEST_TIMESTAMP}, "type_code"=>25, "server_id"=>1, "event_length"=>41, "next_position"=>5365, "flags"=>1, "event_type"=>"Delete_rows", "table_id"=>170, "db_name"=>"#{TEST_DB}", "table_name"=>"#{TEST_TABLE}", "columns"=>["LONG", "BLOB"], "columns_len"=>2, "null_bits_len"=>1, "raw_columns_before_image"=>[], "raw_used_columns"=>[255], "raw_row"=>[252, 2, 0, 0, 0, 5, 0, 104, 111, 104, 111, 103], "rows"=>[["2", "var"],["3","hoge"]]}
|
73
82
|
EOT
|
74
|
-
|
83
|
+
TEST_EVENT_TWO_BYTE_DELETE = <<EOT
|
75
84
|
{"marker"=>0, "timestamp"=>#{TEST_TIMESTAMP}, "type_code"=>25, "server_id"=>1, "event_length"=>41, "next_position"=>5365, "flags"=>1, "event_type"=>"Delete_rows", "table_id"=>170, "db_name"=>"#{TEST_DB}", "table_name"=>"#{TEST_TABLE}", "columns"=>["LONG", "BLOB"], "columns_len"=>2, "null_bits_len"=>1, "raw_columns_before_image"=>[], "raw_used_columns"=>[255], "raw_row"=>[252, 2, 0, 0, 0, 5, 0, 104, 111, 104, 111, 103], "rows"=>[["2", "vår"],["3","høgé"]]}
|
76
85
|
EOT
|
77
|
-
|
86
|
+
TEST_EVENT_THREE_BYTE_DELETE = <<EOT
|
78
87
|
{"marker"=>0, "timestamp"=>#{TEST_TIMESTAMP}, "type_code"=>25, "server_id"=>1, "event_length"=>41, "next_position"=>5365, "flags"=>1, "event_type"=>"Delete_rows", "table_id"=>170, "db_name"=>"#{TEST_DB}", "table_name"=>"#{TEST_TABLE}", "columns"=>["LONG", "BLOB"], "columns_len"=>2, "null_bits_len"=>1, "raw_columns_before_image"=>[], "raw_used_columns"=>[255], "raw_row"=>[252, 2, 0, 0, 0, 5, 0, 104, 111, 104, 111, 103], "rows"=>[["2", "易变的"],["3","切实切实"]]}
|
79
88
|
EOT
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
89
|
+
# Unsupported event
|
90
|
+
# - 02 QUERY_EVENT
|
91
|
+
# QUERY: BEGIN
|
92
|
+
TEST_EVENT_QUERY_BEGIN = <<EOT
|
84
93
|
{"marker"=>0, "timestamp"=>#{TEST_TIMESTAMP}, "type_code"=>2, "server_id"=>1, "event_length"=>73, "next_position"=>2472, "flags"=>8, "event_type"=>"Query", "thread_id"=>71, "exec_time"=>0, "error_code"=>0, "variables"=>[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3, 115, 116, 100, 4, 33, 0, 33, 0, 8, 0], "db_name"=>"#{TEST_DB}", "query"=>"BEGIN"}
|
85
94
|
EOT
|
86
|
-
|
87
|
-
|
95
|
+
# QUERY: create database
|
96
|
+
TEST_EVENT_QUERY_CREATE_DATABSE = <<EOT
|
88
97
|
{"marker"=>0, "timestamp"=>1389309478, "type_code"=>2, "server_id"=>1, "event_length"=>89, "next_position"=>196, "flags"=>8, "event_type"=>"Query", "thread_id"=>39, "exec_time"=>0, "error_code"=>0, "variables"=>[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3, 115, 116, 100, 4, 33, 0, 33, 0, 8, 0], "db_name"=>"test_db", "query"=>"create database test_db"}
|
89
98
|
EOT
|
90
|
-
|
91
|
-
|
99
|
+
# QUERY: create table
|
100
|
+
TEST_EVENT_QUERY_CREATE_TABLE = <<EOT
|
92
101
|
{"marker"=>0, "timestamp"=>#{TEST_TIMESTAMP}, "type_code"=>2, "server_id"=>1, "event_length"=>121, "next_position"=>317, "flags"=>0, "event_type"=>"Query", "thread_id"=>42, "exec_time"=>0, "error_code"=>0, "variables"=>[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3, 115, 116, 100, 4, 33, 0, 33, 0, 8, 0], "db_name"=>"test_db", "query"=>"create table test_table(id int primary key, value text)"}
|
93
102
|
EOT
|
94
|
-
|
95
|
-
|
103
|
+
# QUERY: drop table
|
104
|
+
TEST_EVENT_QUERY_DROP_TABLE = <<EOT
|
96
105
|
{"marker"=>0, "timestamp"=>#{TEST_TIMESTAMP}, "type_code"=>2, "server_id"=>1, "event_length"=>115, "next_position"=>568, "flags"=>0, "event_type"=>"Query", "thread_id"=>42, "exec_time"=>0, "error_code"=>0, "variables"=>[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3, 115, 116, 100, 4, 33, 0, 33, 0, 8, 0], "db_name"=>"test_db", "query"=>"DROP TABLE `test_table` /* generated by server */"}
|
97
106
|
EOT
|
98
|
-
|
99
|
-
|
107
|
+
# QUERY: alter table add column
|
108
|
+
TEST_EVENT_QUERY_ALTER_TABLE_ADD_COLUMN = <<EOT
|
100
109
|
{"marker"=>0, "timestamp"=>#{TEST_TIMESTAMP}, "type_code"=>2, "server_id"=>1, "event_length"=>111, "next_position"=>800, "flags"=>0, "event_type"=>"Query", "thread_id"=>42, "exec_time"=>0, "error_code"=>0, "variables"=>[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3, 115, 116, 100, 4, 33, 0, 33, 0, 8, 0], "db_name"=>"test_db", "query"=>"alter table test_table add column sum integer"}
|
101
110
|
EOT
|
102
|
-
|
103
|
-
|
111
|
+
# QUERY: alter table drop column
|
112
|
+
TEST_EVENT_QUERY_ALTER_TABLE_DROP_COLUMN = <<EOT
|
104
113
|
{"marker"=>0, "timestamp"=>#{TEST_TIMESTAMP}, "type_code"=>2, "server_id"=>1, "event_length"=>104, "next_position"=>904, "flags"=>0, "event_type"=>"Query", "thread_id"=>42, "exec_time"=>0, "error_code"=>0, "variables"=>[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3, 115, 116, 100, 4, 33, 0, 33, 0, 8, 0], "db_name"=>"test_db", "query"=>"alter table test_table drop column sum"}
|
105
114
|
EOT
|
106
|
-
|
107
|
-
|
115
|
+
# QUERY: alter table modify column
|
116
|
+
TEST_EVENT_QUERY_ALTER_TABLE_MODIFY_COLUMN = <<EOT
|
108
117
|
{"marker"=>0, "timestamp"=>#{TEST_TIMESTAMP}, "type_code"=>2, "server_id"=>1, "event_length"=>112, "next_position"=>1352, "flags"=>0, "event_type"=>"Query", "thread_id"=>48, "exec_time"=>0, "error_code"=>0, "variables"=>[0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 6, 3, 115, 116, 100, 4, 33, 0, 33, 0, 8, 0], "db_name"=>"test_db", "query"=>"alter table test_table modify column sum float"}
|
109
118
|
EOT
|
110
|
-
|
111
|
-
|
119
|
+
# QUERY: alter table add index
|
120
|
+
TEST_EVENT_QUERY_ALTER_TABLE_ADD_INDEX = <<EOT
|
112
121
|
{"marker"=>0, "timestamp"=>#{TEST_TIMESTAMP}, "type_code"=>2, "server_id"=>1, "event_length"=>217, "next_position"=>337, "flags"=>0, "event_type"=>"Query", "thread_id"=>10097, "exec_time"=>0, "error_code"=>0, "variables"=>[0, 0, 0, 0, 0, 1, 0, 0, 0, 64, 0, 0, 0, 0, 6, 3, 115, 116, 100, 4, 33, 0, 33, 0, 8, 0, 12, 1, 109, 97, 107, 95, 100, 101, 118, 101, 108, 111, 112, 109, 101, 110, 116, 0], "db_name"=>"test_db", "query"=>"ALTER TABLE `test_db`.`test_table` \nADD INDEX `my_index` USING HASH (`extra` ASC) COMMENT 'How does this look in binlog?'"}
|
113
122
|
EOT
|
114
|
-
|
115
|
-
|
123
|
+
# - 03 STOP_EVENT
|
124
|
+
TEST_EVENT_STOP = <<EOT
|
116
125
|
{"marker"=>0, "timestamp"=>#{TEST_TIMESTAMP}, "type_code"=>3, "server_id"=>1, "event_length"=>19, "next_position"=>2929, "flags"=>0, "event_type"=>"Stop"}
|
117
126
|
EOT
|
118
|
-
|
119
|
-
|
127
|
+
# - 04 ROTATE_EVENT
|
128
|
+
TEST_EVENT_ROTATE = <<EOT
|
120
129
|
{"marker"=>0, "timestamp"=>0, "type_code"=>4, "server_id"=>1, "event_length"=>43, "next_position"=>0, "flags"=>32, "event_type"=>"Rotate", "binlog_file"=>"mysql-bin.000048", "binlog_pos"=>2883}
|
121
130
|
EOT
|
122
|
-
|
123
|
-
|
131
|
+
# - 0f FORMAT_DESCRIPTION_EVENT
|
132
|
+
TEST_EVENT_FORMAT_DESC = <<EOT
|
124
133
|
{"marker"=>0, "timestamp"=>1389292075, "type_code"=>15, "server_id"=>1, "event_length"=>103, "next_position"=>0, "flags"=>0, "event_type"=>"Format_desc", "binlog_version"=>0, "created_ts"=>2560145104, "log_header_len"=>71}
|
125
134
|
EOT
|
126
|
-
|
127
|
-
|
135
|
+
# - 10 XID_EVENT
|
136
|
+
TEST_EVENT_XID = <<EOT
|
128
137
|
{"marker"=>0, "timestamp"=>#{TEST_TIMESTAMP}, "type_code"=>16, "server_id"=>1, "event_length"=>27, "next_position"=>2633, "flags"=>0, "event_type"=>"Xid", "xid_id"=>129345}
|
129
138
|
EOT
|
130
139
|
|
131
|
-
|
132
|
-
|
140
|
+
# - 13 TABLE_MAP_EVENT
|
141
|
+
TEST_EVENT_TABLE_MAP = <<EOT
|
133
142
|
{"marker"=>0, "timestamp"=>#{TEST_TIMESTAMP}, "type_code"=>19, "server_id"=>1, "event_length"=>56, "next_position"=>2528, "flags"=>1, "event_type"=>"Table_map", "table_id"=>163, "db_name"=>"#{TEST_DB}", "table_name"=>"#{TEST_TABLE}", "raw_columns"=>[3, 252], "columns"=>["LONG", "BLOB"], "metadata"=>[2], "null_bits"=>[3]}
|
134
143
|
EOT
|
135
|
-
|
136
|
-
|
144
|
+
# la
|
145
|
+
TEST_EVENT_INCIDENT = <<EOT
|
137
146
|
{"marker"=>0, "timestamp"=>0, "type_code"=>26, "server_id"=>1, "event_length"=>40, "next_position"=>2883, "flags"=>32, "event_type"=>"Incident", "incident_type"=>175, "message"=>"Operation canceled"}
|
138
147
|
EOT
|
139
|
-
|
140
|
-
|
148
|
+
# - 04 ROTATE_EVENT
|
149
|
+
TEST_EVENT_ROTATE_MISSING_BINLOG_FILE = <<EOT
|
141
150
|
{"marker"=>0, "timestamp"=>0, "type_code"=>4, "server_id"=>1, "event_length"=>43, "next_position"=>0, "flags"=>32, "event_type"=>"Rotate", "binlog_pos"=>2883}
|
142
151
|
EOT
|
143
152
|
|
144
|
-
describe MysqlBinlogFlydataInput do
|
145
153
|
def create_event(event_str)
|
146
154
|
event = eval(event_str)
|
147
155
|
allow(event).to receive(:event_type).and_return(event["event_type"])
|
@@ -173,7 +181,6 @@ EOT
|
|
173
181
|
expect_emitted_records(event, records)
|
174
182
|
end
|
175
183
|
|
176
|
-
let(:plugin) { MysqlBinlogFlydataInput.new }
|
177
184
|
let(:insert_event) { create_event(TEST_EVENT_INSERT) }
|
178
185
|
let(:insert_two_byte_event) { create_event(TEST_EVENT_TWO_BYTE_INSERT) }
|
179
186
|
let(:insert_three_byte_event) { create_event(TEST_EVENT_THREE_BYTE_INSERT) }
|
@@ -196,58 +203,74 @@ EOT
|
|
196
203
|
let(:now) { Time.now }
|
197
204
|
let(:flydata_record_version) { 2 }
|
198
205
|
|
199
|
-
let(:
|
200
|
-
f = double('
|
206
|
+
let(:source_position_file) do
|
207
|
+
f = double('source_position_file')
|
201
208
|
allow(f).to receive(:exists?).and_return(true)
|
202
209
|
allow(f).to receive(:read).and_return('test_position')
|
203
210
|
f
|
204
211
|
end
|
205
212
|
|
206
|
-
|
207
|
-
f = double('sent_position_file')
|
208
|
-
allow(f).to receive(:exists?).and_return(true)
|
209
|
-
allow(f).to receive(:read).and_return('test_sent_position')
|
210
|
-
f
|
211
|
-
end
|
212
|
-
|
213
|
-
def create_file(file_path, content)
|
214
|
-
File.open(file_path, 'w') {|f| f.write(content)}
|
215
|
-
end
|
216
|
-
|
217
|
-
def delete_file(file_path)
|
218
|
-
FileUtils.rm(file_path) if File.exists?(file_path)
|
219
|
-
end
|
220
|
-
|
221
|
-
def setup_initial_flydata_files
|
222
|
-
%w(positions dump conf).each{|f| FileUtils.mkdir_p(File.join(FLYDATA_HOME, f))}
|
213
|
+
def setup_pos_files
|
223
214
|
create_file(TEST_SEQUENCE_FILE, TEST_SEQUENCE_NUM.to_s)
|
224
215
|
create_file(TEST_SEQUENCE_FILE_1, TEST_SEQUENCE_NUM.to_s)
|
225
216
|
end
|
226
217
|
|
227
|
-
def
|
228
|
-
%w(positions dump conf).each{|f| FileUtils.rm_rf(File.join(FLYDATA_HOME, f))}
|
218
|
+
def cleanup_pos_files
|
229
219
|
delete_file(TEST_SEQUENCE_FILE)
|
230
220
|
delete_file(TEST_SEQUENCE_FILE_1)
|
231
221
|
end
|
232
222
|
|
233
223
|
before do
|
234
|
-
|
235
|
-
|
224
|
+
cleanup_pos_files
|
225
|
+
setup_pos_files
|
236
226
|
allow(MysqlBinlogInput::BinlogUtil).to receive(:to_hash) {|e| e}
|
237
|
-
allow(Flydata::SourceMysql::
|
238
|
-
allow(Flydata::SourceMysql::PluginSupport::BinLogPositionFile).to receive(:new).with(TEST_SENT_POSITION_FILE).
|
239
|
-
and_return(sent_position_file)
|
240
|
-
allow(Flydata::SourceMysql::PluginSupport::TableMeta).to receive(:update)
|
227
|
+
allow(Flydata::SourceMysql::TableMeta).to receive(:update)
|
241
228
|
allow(plugin).to receive(:`).with("mysql -V").and_return("mysql Ver 14.14 Distrib 5.5.40")
|
242
229
|
allow(plugin).to receive(:`).with(/^echo 'select version\(\);'/).and_return("version()\n5.5.40-0ubuntu0.12.04.1-log")
|
243
230
|
Timecop.freeze(now)
|
244
231
|
end
|
245
232
|
|
246
233
|
after do
|
247
|
-
|
234
|
+
cleanup_pos_files
|
248
235
|
Timecop.return
|
249
236
|
end
|
250
237
|
|
238
|
+
describe '#configure' do
|
239
|
+
let(:config) { default_config }
|
240
|
+
before do
|
241
|
+
Test.configure_plugin(plugin, config)
|
242
|
+
end
|
243
|
+
|
244
|
+
it 'sets data entry object' do
|
245
|
+
expect(plugin.instance_variable_get(:@data_entry)).to eq(
|
246
|
+
'name' => 'test_name',
|
247
|
+
'type' => 'RedshiftMysqlDataEntry',
|
248
|
+
'mysql_data_entry_preference' => {
|
249
|
+
'database' => 'test_db',
|
250
|
+
'tables' => 'test_table,test_table_1,test_table_2',
|
251
|
+
'tables_append_only' => 'test_table_3',
|
252
|
+
'host' => 'localhost',
|
253
|
+
'username' => 'test_admin',
|
254
|
+
'password' => 'test_password',
|
255
|
+
'ssl_ca_content' => '',
|
256
|
+
'ssl_cipher' => '',
|
257
|
+
}
|
258
|
+
)
|
259
|
+
end
|
260
|
+
|
261
|
+
it 'sets data tables as array' do
|
262
|
+
expect(plugin.instance_variable_get(:@tables)).to eq(%w(test_table))
|
263
|
+
end
|
264
|
+
|
265
|
+
it 'sets sync_fm' do
|
266
|
+
expect(plugin.instance_variable_get(:@sync_fm)).to be_kind_of(Flydata::SyncFileManager)
|
267
|
+
end
|
268
|
+
|
269
|
+
it 'sets omit_events' do
|
270
|
+
expect(plugin.instance_variable_get(:@omit_events)).to eq({'test_table_3' => [:delete, :truncate_table]})
|
271
|
+
end
|
272
|
+
end
|
273
|
+
|
251
274
|
describe '#event_listener' do
|
252
275
|
|
253
276
|
context 'when received rotate event' do
|