rubyrep 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/History.txt +4 -0
- data/License.txt +20 -0
- data/Manifest.txt +137 -0
- data/README.txt +37 -0
- data/Rakefile +30 -0
- data/bin/rubyrep +8 -0
- data/config/hoe.rb +72 -0
- data/config/mysql_config.rb +25 -0
- data/config/postgres_config.rb +21 -0
- data/config/proxied_test_config.rb +14 -0
- data/config/redmine_config.rb +17 -0
- data/config/rep_config.rb +20 -0
- data/config/requirements.rb +32 -0
- data/config/test_config.rb +20 -0
- data/lib/rubyrep/base_runner.rb +195 -0
- data/lib/rubyrep/command_runner.rb +144 -0
- data/lib/rubyrep/committers/buffered_committer.rb +140 -0
- data/lib/rubyrep/committers/committers.rb +146 -0
- data/lib/rubyrep/configuration.rb +240 -0
- data/lib/rubyrep/connection_extenders/connection_extenders.rb +133 -0
- data/lib/rubyrep/connection_extenders/jdbc_extender.rb +284 -0
- data/lib/rubyrep/connection_extenders/mysql_extender.rb +168 -0
- data/lib/rubyrep/connection_extenders/postgresql_extender.rb +261 -0
- data/lib/rubyrep/database_proxy.rb +52 -0
- data/lib/rubyrep/direct_table_scan.rb +75 -0
- data/lib/rubyrep/generate_runner.rb +105 -0
- data/lib/rubyrep/initializer.rb +39 -0
- data/lib/rubyrep/logged_change.rb +326 -0
- data/lib/rubyrep/proxied_table_scan.rb +171 -0
- data/lib/rubyrep/proxy_block_cursor.rb +145 -0
- data/lib/rubyrep/proxy_connection.rb +318 -0
- data/lib/rubyrep/proxy_cursor.rb +44 -0
- data/lib/rubyrep/proxy_row_cursor.rb +43 -0
- data/lib/rubyrep/proxy_runner.rb +89 -0
- data/lib/rubyrep/replication_difference.rb +91 -0
- data/lib/rubyrep/replication_extenders/mysql_replication.rb +271 -0
- data/lib/rubyrep/replication_extenders/postgresql_replication.rb +204 -0
- data/lib/rubyrep/replication_extenders/replication_extenders.rb +26 -0
- data/lib/rubyrep/replication_helper.rb +104 -0
- data/lib/rubyrep/replication_initializer.rb +307 -0
- data/lib/rubyrep/replication_run.rb +48 -0
- data/lib/rubyrep/replication_runner.rb +138 -0
- data/lib/rubyrep/replicators/replicators.rb +37 -0
- data/lib/rubyrep/replicators/two_way_replicator.rb +334 -0
- data/lib/rubyrep/scan_progress_printers/progress_bar.rb +65 -0
- data/lib/rubyrep/scan_progress_printers/scan_progress_printers.rb +65 -0
- data/lib/rubyrep/scan_report_printers/scan_detail_reporter.rb +111 -0
- data/lib/rubyrep/scan_report_printers/scan_report_printers.rb +67 -0
- data/lib/rubyrep/scan_report_printers/scan_summary_reporter.rb +75 -0
- data/lib/rubyrep/scan_runner.rb +25 -0
- data/lib/rubyrep/session.rb +177 -0
- data/lib/rubyrep/sync_helper.rb +111 -0
- data/lib/rubyrep/sync_runner.rb +31 -0
- data/lib/rubyrep/syncers/syncers.rb +112 -0
- data/lib/rubyrep/syncers/two_way_syncer.rb +174 -0
- data/lib/rubyrep/table_scan.rb +54 -0
- data/lib/rubyrep/table_scan_helper.rb +38 -0
- data/lib/rubyrep/table_sorter.rb +70 -0
- data/lib/rubyrep/table_spec_resolver.rb +136 -0
- data/lib/rubyrep/table_sync.rb +68 -0
- data/lib/rubyrep/trigger_mode_switcher.rb +63 -0
- data/lib/rubyrep/type_casting_cursor.rb +31 -0
- data/lib/rubyrep/uninstall_runner.rb +92 -0
- data/lib/rubyrep/version.rb +9 -0
- data/lib/rubyrep.rb +68 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +74 -0
- data/setup.rb +1585 -0
- data/sims/performance/big_rep_spec.rb +100 -0
- data/sims/performance/big_scan_spec.rb +57 -0
- data/sims/performance/big_sync_spec.rb +141 -0
- data/sims/performance/performance.rake +228 -0
- data/sims/sim_helper.rb +24 -0
- data/spec/base_runner_spec.rb +218 -0
- data/spec/buffered_committer_spec.rb +271 -0
- data/spec/command_runner_spec.rb +145 -0
- data/spec/committers_spec.rb +174 -0
- data/spec/configuration_spec.rb +198 -0
- data/spec/connection_extender_interface_spec.rb +138 -0
- data/spec/connection_extenders_registration_spec.rb +129 -0
- data/spec/database_proxy_spec.rb +48 -0
- data/spec/database_rake_spec.rb +40 -0
- data/spec/db_specific_connection_extenders_spec.rb +34 -0
- data/spec/db_specific_replication_extenders_spec.rb +38 -0
- data/spec/direct_table_scan_spec.rb +61 -0
- data/spec/generate_runner_spec.rb +84 -0
- data/spec/initializer_spec.rb +46 -0
- data/spec/logged_change_spec.rb +480 -0
- data/spec/postgresql_replication_spec.rb +48 -0
- data/spec/postgresql_support_spec.rb +57 -0
- data/spec/progress_bar_spec.rb +77 -0
- data/spec/proxied_table_scan_spec.rb +151 -0
- data/spec/proxy_block_cursor_spec.rb +197 -0
- data/spec/proxy_connection_spec.rb +399 -0
- data/spec/proxy_cursor_spec.rb +56 -0
- data/spec/proxy_row_cursor_spec.rb +66 -0
- data/spec/proxy_runner_spec.rb +70 -0
- data/spec/replication_difference_spec.rb +160 -0
- data/spec/replication_extender_interface_spec.rb +365 -0
- data/spec/replication_extenders_spec.rb +32 -0
- data/spec/replication_helper_spec.rb +121 -0
- data/spec/replication_initializer_spec.rb +477 -0
- data/spec/replication_run_spec.rb +166 -0
- data/spec/replication_runner_spec.rb +213 -0
- data/spec/replicators_spec.rb +31 -0
- data/spec/rubyrep_spec.rb +8 -0
- data/spec/scan_detail_reporter_spec.rb +119 -0
- data/spec/scan_progress_printers_spec.rb +68 -0
- data/spec/scan_report_printers_spec.rb +67 -0
- data/spec/scan_runner_spec.rb +50 -0
- data/spec/scan_summary_reporter_spec.rb +61 -0
- data/spec/session_spec.rb +212 -0
- data/spec/spec.opts +1 -0
- data/spec/spec_helper.rb +295 -0
- data/spec/sync_helper_spec.rb +157 -0
- data/spec/sync_runner_spec.rb +78 -0
- data/spec/syncers_spec.rb +171 -0
- data/spec/table_scan_helper_spec.rb +29 -0
- data/spec/table_scan_spec.rb +49 -0
- data/spec/table_sorter_spec.rb +31 -0
- data/spec/table_spec_resolver_spec.rb +102 -0
- data/spec/table_sync_spec.rb +84 -0
- data/spec/trigger_mode_switcher_spec.rb +83 -0
- data/spec/two_way_replicator_spec.rb +551 -0
- data/spec/two_way_syncer_spec.rb +256 -0
- data/spec/type_casting_cursor_spec.rb +50 -0
- data/spec/uninstall_runner_spec.rb +86 -0
- data/tasks/database.rake +439 -0
- data/tasks/deployment.rake +29 -0
- data/tasks/environment.rake +9 -0
- data/tasks/java.rake +37 -0
- data/tasks/redmine_test.rake +47 -0
- data/tasks/rspec.rake +68 -0
- data/tasks/rubyrep.tailor +18 -0
- data/tasks/stats.rake +19 -0
- data/tasks/task_helper.rb +20 -0
- data.tar.gz.sig +0 -0
- metadata +243 -0
- metadata.gz.sig +0 -0
|
@@ -0,0 +1,151 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
|
2
|
+
|
|
3
|
+
include RR
|
|
4
|
+
|
|
5
|
+
describe ProxiedTableScan do
|
|
6
|
+
before(:each) do
|
|
7
|
+
Initializer.configuration = deep_copy(proxied_config)
|
|
8
|
+
|
|
9
|
+
# Small block size necessary to exercize all code paths in ProxiedTableScan
|
|
10
|
+
# even when only using tables with very small number of records.
|
|
11
|
+
Initializer.configuration.options[:proxy_block_size] = 2
|
|
12
|
+
|
|
13
|
+
ensure_proxy
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
it "initialize should raise exception if session is not proxied" do
|
|
17
|
+
session = Session.new standard_config
|
|
18
|
+
lambda { ProxiedTableScan.new session, 'dummy_table' } \
|
|
19
|
+
.should raise_error(RuntimeError, /only works with proxied sessions/)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
it "initialize should cache the primary keys" do
|
|
23
|
+
session = Session.new
|
|
24
|
+
scan = ProxiedTableScan.new session, 'scanner_records'
|
|
25
|
+
scan.primary_key_names.should == ['id']
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "initialize should raise exception if table doesn't have primary keys" do
|
|
29
|
+
session = Session.new
|
|
30
|
+
lambda {ProxiedTableScan.new session, 'extender_without_key'} \
|
|
31
|
+
.should raise_error(RuntimeError, /.*extender_without_key.*primary key/)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
it "block_size should return the :proxy_block_size value of the session options" do
|
|
35
|
+
ProxiedTableScan.new(Session.new, 'scanner_records').block_size \
|
|
36
|
+
.should == 2
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
it "block_size should return the matching table specific option if available" do
|
|
40
|
+
config = Initializer.configuration
|
|
41
|
+
old_table_specific_options = config.tables_with_options
|
|
42
|
+
begin
|
|
43
|
+
config.options = {:proxy_block_size => 2}
|
|
44
|
+
config.include_tables 'scanner_records', {:proxy_block_size => 3}
|
|
45
|
+
ProxiedTableScan.new(Session.new(config), 'scanner_records').block_size \
|
|
46
|
+
.should == 3
|
|
47
|
+
ensure
|
|
48
|
+
config.instance_eval {@tables_with_options = old_table_specific_options}
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# Creates, prepares and returns a +ProxyBlockCursor+ for the given database
|
|
53
|
+
# +connection+ and +table+.
|
|
54
|
+
# Sets the ProxyBlockCursor#max_row_cache_size as per method parameter.
|
|
55
|
+
def get_block_cursor(connection, table, max_row_cache_size = 1000000)
|
|
56
|
+
cursor = ProxyBlockCursor.new connection, table
|
|
57
|
+
cursor.max_row_cache_size = max_row_cache_size
|
|
58
|
+
cursor.prepare_fetch
|
|
59
|
+
cursor.checksum :proxy_block_size => 1000
|
|
60
|
+
cursor
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
it "compare_blocks should compare all the records in the range" do
|
|
64
|
+
session = Session.new
|
|
65
|
+
|
|
66
|
+
left_cursor = get_block_cursor session.left, 'scanner_records'
|
|
67
|
+
right_cursor = get_block_cursor session.right, 'scanner_records'
|
|
68
|
+
|
|
69
|
+
scan = ProxiedTableScan.new session, 'scanner_records'
|
|
70
|
+
diff = []
|
|
71
|
+
scan.compare_blocks(left_cursor, right_cursor) do |type, row|
|
|
72
|
+
diff.push [type, row]
|
|
73
|
+
end
|
|
74
|
+
# in this scenario the right table has the 'highest' data,
|
|
75
|
+
# so 'right-sided' data are already implicitely tested here
|
|
76
|
+
diff.should == [
|
|
77
|
+
[:conflict, [
|
|
78
|
+
{'id' => 2, 'name' => 'Bob - left database version'},
|
|
79
|
+
{'id' => 2, 'name' => 'Bob - right database version'}]],
|
|
80
|
+
[:left, {'id' => 3, 'name' => 'Charlie - exists in left database only'}],
|
|
81
|
+
[:right, {'id' => 4, 'name' => 'Dave - exists in right database only'}],
|
|
82
|
+
[:left, {'id' => 5, 'name' => 'Eve - exists in left database only'}],
|
|
83
|
+
[:right, {'id' => 6, 'name' => 'Fred - exists in right database only'}]
|
|
84
|
+
]
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
it "compare_blocks should destroy the created cursors" do
|
|
88
|
+
session = Session.new
|
|
89
|
+
|
|
90
|
+
left_cursor = get_block_cursor session.left, 'scanner_records', 0
|
|
91
|
+
right_cursor = get_block_cursor session.right, 'scanner_records', 0
|
|
92
|
+
|
|
93
|
+
scan = ProxiedTableScan.new session, 'scanner_records'
|
|
94
|
+
scan.compare_blocks(left_cursor, right_cursor) { |type, row| }
|
|
95
|
+
|
|
96
|
+
session.left.cursors.should == {}
|
|
97
|
+
session.right.cursors.should == {}
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
it "run should only call compare single rows if there are different block checksums" do
|
|
101
|
+
config = deep_copy(proxied_config)
|
|
102
|
+
config.right = config.left
|
|
103
|
+
session = Session.new config
|
|
104
|
+
scan = ProxiedTableScan.new session, 'scanner_records'
|
|
105
|
+
scan.should_not_receive(:compare_blocks)
|
|
106
|
+
diff = []
|
|
107
|
+
scan.run do |type, row|
|
|
108
|
+
diff.push [type,row]
|
|
109
|
+
end
|
|
110
|
+
diff.should == []
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
it "run should compare all the records in the table" do
|
|
114
|
+
session = Session.new
|
|
115
|
+
scan = ProxiedTableScan.new session, 'scanner_records'
|
|
116
|
+
diff = []
|
|
117
|
+
scan.run do |type, row|
|
|
118
|
+
diff.push [type, row]
|
|
119
|
+
end
|
|
120
|
+
# in this scenario the right table has the 'highest' data,
|
|
121
|
+
# so 'right-sided' data are already implicitely tested here
|
|
122
|
+
diff.should == [
|
|
123
|
+
[:conflict, [
|
|
124
|
+
{'id' => 2, 'name' => 'Bob - left database version'},
|
|
125
|
+
{'id' => 2, 'name' => 'Bob - right database version'}]],
|
|
126
|
+
[:left, {'id' => 3, 'name' => 'Charlie - exists in left database only'}],
|
|
127
|
+
[:right, {'id' => 4, 'name' => 'Dave - exists in right database only'}],
|
|
128
|
+
[:left, {'id' => 5, 'name' => 'Eve - exists in left database only'}],
|
|
129
|
+
[:right, {'id' => 6, 'name' => 'Fred - exists in right database only'}]
|
|
130
|
+
]
|
|
131
|
+
end
|
|
132
|
+
|
|
133
|
+
it "run should update the progress" do
|
|
134
|
+
session = Session.new
|
|
135
|
+
scan = ProxiedTableScan.new session, 'scanner_records'
|
|
136
|
+
number_steps = 0
|
|
137
|
+
scan.should_receive(:update_progress).any_number_of_times do |steps|
|
|
138
|
+
number_steps += steps
|
|
139
|
+
end
|
|
140
|
+
scan.run {|_, _|}
|
|
141
|
+
number_steps.should == 8
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
it "run should update the progress even if there are no records" do
|
|
145
|
+
# it should do that to ensure the progress bar is printed
|
|
146
|
+
scan = ProxiedTableScan.new Session.new, 'extender_no_record'
|
|
147
|
+
scan.should_receive(:update_progress).at_least(:once)
|
|
148
|
+
scan.run {|_, _|}
|
|
149
|
+
end
|
|
150
|
+
end
|
|
151
|
+
|
|
@@ -0,0 +1,197 @@
|
|
|
1
|
+
require File.dirname(__FILE__) + '/spec_helper.rb'
|
|
2
|
+
|
|
3
|
+
include RR
|
|
4
|
+
|
|
5
|
+
describe ProxyBlockCursor do
|
|
6
|
+
before(:each) do
|
|
7
|
+
@session = create_mock_proxy_connection 'dummy_table', ['dummy_id']
|
|
8
|
+
@cursor = ProxyBlockCursor.new @session, 'dummy_table'
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
it "initialize should super to ProxyCursor" do
|
|
12
|
+
@cursor.table.should == 'dummy_table'
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
it "next? should return true if there is an already loaded unprocessed row" do
|
|
16
|
+
@cursor.last_row = :dummy_row
|
|
17
|
+
@cursor.next?.should be_true
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
it "next? should return true if the database cursor has more rows" do
|
|
21
|
+
table_cursor = mock("DBCursor")
|
|
22
|
+
table_cursor.should_receive(:next?).and_return(true)
|
|
23
|
+
@cursor.cursor = table_cursor
|
|
24
|
+
|
|
25
|
+
@cursor.next?.should be_true
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
it "next? should return false if there are no loaded or unloaded unprocessed rows" do
|
|
29
|
+
table_cursor = mock("DBCursor")
|
|
30
|
+
table_cursor.should_receive(:next?).and_return(false)
|
|
31
|
+
@cursor.cursor = table_cursor
|
|
32
|
+
|
|
33
|
+
@cursor.next?.should be_false
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
it "next_row should return last loaded unprocessed row or nil if there is none" do
|
|
37
|
+
@cursor.last_row = :dummy_row
|
|
38
|
+
|
|
39
|
+
@cursor.next_row.should == :dummy_row
|
|
40
|
+
@cursor.last_row.should be_nil
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
it "next_row should return next row in database if there is no loaded unprocessed row available" do
|
|
44
|
+
table_cursor = mock("DBCursor")
|
|
45
|
+
table_cursor.should_receive(:next_row).and_return(:dummy_row)
|
|
46
|
+
@cursor.cursor = table_cursor
|
|
47
|
+
|
|
48
|
+
@cursor.next_row.should == :dummy_row
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
it "reset_checksum should create a new empty SHA1 digest" do
|
|
52
|
+
@cursor.digest = :dummy_digest
|
|
53
|
+
@cursor.reset_checksum
|
|
54
|
+
@cursor.digest.should be_an_instance_of(Digest::SHA1)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
it "reset_checksum should reset block variables" do
|
|
58
|
+
@cursor.reset_checksum
|
|
59
|
+
@cursor.row_checksums.should == []
|
|
60
|
+
@cursor.current_row_cache_size.should == 0
|
|
61
|
+
@cursor.row_cache.should == {}
|
|
62
|
+
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
it "update_checksum should update the existing digests" do
|
|
66
|
+
dummy_row1 = {'dummy_id' => 'dummy_value1'}
|
|
67
|
+
dummy_row2 = {'dummy_id' => 'dummy_value2'}
|
|
68
|
+
|
|
69
|
+
@cursor.reset_checksum
|
|
70
|
+
@cursor.update_checksum dummy_row1
|
|
71
|
+
@cursor.update_checksum dummy_row2
|
|
72
|
+
|
|
73
|
+
@cursor.current_checksum.should == Digest::SHA1.hexdigest(Marshal.dump(dummy_row1) + Marshal.dump(dummy_row2))
|
|
74
|
+
@cursor.row_checksums.should == [
|
|
75
|
+
{:row_keys => dummy_row1, :checksum => Digest::SHA1.hexdigest(Marshal.dump(dummy_row1))},
|
|
76
|
+
{:row_keys => dummy_row2, :checksum => Digest::SHA1.hexdigest(Marshal.dump(dummy_row2))},
|
|
77
|
+
]
|
|
78
|
+
|
|
79
|
+
@cursor.row_cache.should == {
|
|
80
|
+
Digest::SHA1.hexdigest(Marshal.dump(dummy_row1)) => Marshal.dump(dummy_row1),
|
|
81
|
+
Digest::SHA1.hexdigest(Marshal.dump(dummy_row2)) => Marshal.dump(dummy_row2)
|
|
82
|
+
}
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
it "retrieve_row_cache should retrieve the specified elements" do
|
|
86
|
+
@cursor.row_cache = {'dummy_checksum' => 'bla'}
|
|
87
|
+
@cursor.retrieve_row_cache(['non_cached_row_checksum', 'dummy_checksum']).should ==
|
|
88
|
+
{'dummy_checksum' => 'bla'}
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
it "current_checksum should return the current checksum" do
|
|
92
|
+
digest = mock("Digest")
|
|
93
|
+
digest.should_receive(:hexdigest).and_return(:dummy_checksum)
|
|
94
|
+
@cursor.digest = digest
|
|
95
|
+
|
|
96
|
+
@cursor.current_checksum.should == :dummy_checksum
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
it "checksum should reset the current digest" do
|
|
100
|
+
@cursor.reset_checksum # need to call it now so that for the call to checksum it can be mocked
|
|
101
|
+
@cursor.should_receive(:reset_checksum)
|
|
102
|
+
@cursor.should_receive(:next?).and_return(false)
|
|
103
|
+
@cursor.checksum :proxy_block_size => 1
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
it "checksum should complain if neither :proxy_block_size nor :max_row are provided" do
|
|
107
|
+
lambda {@cursor.checksum}.should raise_error(
|
|
108
|
+
RuntimeError, 'options must include either :proxy_block_size or :max_row')
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
it "checksum should verify options" do
|
|
112
|
+
lambda {@cursor.checksum}.should raise_error(
|
|
113
|
+
RuntimeError, 'options must include either :proxy_block_size or :max_row')
|
|
114
|
+
lambda {@cursor.checksum(:proxy_block_size => 0)}.should raise_error(
|
|
115
|
+
RuntimeError, ':proxy_block_size must be greater than 0')
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
it "checksum should read maximum :proxy_block_size rows" do
|
|
119
|
+
session = ProxyConnection.new proxied_config.left
|
|
120
|
+
|
|
121
|
+
cursor = ProxyBlockCursor.new session, 'scanner_records'
|
|
122
|
+
cursor.prepare_fetch
|
|
123
|
+
|
|
124
|
+
last_row, = cursor.checksum :proxy_block_size => 2
|
|
125
|
+
last_row.should == {'id' => 2}
|
|
126
|
+
|
|
127
|
+
last_row, = cursor.checksum :proxy_block_size => 1000
|
|
128
|
+
last_row.should == {'id' => 5}
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
it "checksum should read up to the specified :max_row" do
|
|
132
|
+
session = ProxyConnection.new proxied_config.left
|
|
133
|
+
|
|
134
|
+
cursor = ProxyBlockCursor.new session, 'scanner_records'
|
|
135
|
+
cursor.prepare_fetch
|
|
136
|
+
|
|
137
|
+
last_row, = cursor.checksum :max_row => {'id' => 2}
|
|
138
|
+
last_row.should == {'id' => 2}
|
|
139
|
+
last_row, = cursor.checksum :max_row => {'id' => 1000}
|
|
140
|
+
last_row.should == {'id' => 5}
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
it "checksum called with :proxy_block_size should return the correct checksum" do
|
|
144
|
+
session = ProxyConnection.new proxied_config.left
|
|
145
|
+
|
|
146
|
+
cursor = ProxyBlockCursor.new session, 'scanner_records'
|
|
147
|
+
cursor.prepare_fetch
|
|
148
|
+
|
|
149
|
+
last_row , checksum = cursor.checksum :proxy_block_size => 2
|
|
150
|
+
|
|
151
|
+
expected_checksum = Digest::SHA1.hexdigest(
|
|
152
|
+
Marshal.dump('id' => 1, 'name' => 'Alice - exists in both databases') +
|
|
153
|
+
Marshal.dump('id' => 2, 'name' => 'Bob - left database version')
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
checksum.should == expected_checksum
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
it "checksum called with :max_row should return the correct checksum" do
|
|
160
|
+
session = ProxyConnection.new proxied_config.left
|
|
161
|
+
|
|
162
|
+
cursor = ProxyBlockCursor.new session, 'scanner_records'
|
|
163
|
+
cursor.prepare_fetch
|
|
164
|
+
|
|
165
|
+
last_row , checksum = cursor.checksum :max_row => {'id' => 2}
|
|
166
|
+
|
|
167
|
+
expected_checksum = Digest::SHA1.hexdigest(
|
|
168
|
+
Marshal.dump('id' => 1, 'name' => 'Alice - exists in both databases') +
|
|
169
|
+
Marshal.dump('id' => 2, 'name' => 'Bob - left database version')
|
|
170
|
+
)
|
|
171
|
+
|
|
172
|
+
checksum.should == expected_checksum
|
|
173
|
+
end
|
|
174
|
+
|
|
175
|
+
it "checksum called with :proxy_block_size should return the correct row count" do
|
|
176
|
+
session = ProxyConnection.new proxied_config.left
|
|
177
|
+
|
|
178
|
+
cursor = ProxyBlockCursor.new session, 'scanner_records'
|
|
179
|
+
cursor.prepare_fetch
|
|
180
|
+
|
|
181
|
+
_ , _, row_count = cursor.checksum :proxy_block_size => 2
|
|
182
|
+
|
|
183
|
+
row_count.should == 2
|
|
184
|
+
end
|
|
185
|
+
|
|
186
|
+
it "checksum called with :max_row should return the correct row count" do
|
|
187
|
+
session = ProxyConnection.new proxied_config.left
|
|
188
|
+
|
|
189
|
+
cursor = ProxyBlockCursor.new session, 'scanner_records'
|
|
190
|
+
cursor.prepare_fetch
|
|
191
|
+
|
|
192
|
+
_ , _, row_count = cursor.checksum :max_row => {'id' => 2}
|
|
193
|
+
|
|
194
|
+
row_count.should == 2
|
|
195
|
+
end
|
|
196
|
+
|
|
197
|
+
end
|