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.
Files changed (140) hide show
  1. data/History.txt +4 -0
  2. data/License.txt +20 -0
  3. data/Manifest.txt +137 -0
  4. data/README.txt +37 -0
  5. data/Rakefile +30 -0
  6. data/bin/rubyrep +8 -0
  7. data/config/hoe.rb +72 -0
  8. data/config/mysql_config.rb +25 -0
  9. data/config/postgres_config.rb +21 -0
  10. data/config/proxied_test_config.rb +14 -0
  11. data/config/redmine_config.rb +17 -0
  12. data/config/rep_config.rb +20 -0
  13. data/config/requirements.rb +32 -0
  14. data/config/test_config.rb +20 -0
  15. data/lib/rubyrep/base_runner.rb +195 -0
  16. data/lib/rubyrep/command_runner.rb +144 -0
  17. data/lib/rubyrep/committers/buffered_committer.rb +140 -0
  18. data/lib/rubyrep/committers/committers.rb +146 -0
  19. data/lib/rubyrep/configuration.rb +240 -0
  20. data/lib/rubyrep/connection_extenders/connection_extenders.rb +133 -0
  21. data/lib/rubyrep/connection_extenders/jdbc_extender.rb +284 -0
  22. data/lib/rubyrep/connection_extenders/mysql_extender.rb +168 -0
  23. data/lib/rubyrep/connection_extenders/postgresql_extender.rb +261 -0
  24. data/lib/rubyrep/database_proxy.rb +52 -0
  25. data/lib/rubyrep/direct_table_scan.rb +75 -0
  26. data/lib/rubyrep/generate_runner.rb +105 -0
  27. data/lib/rubyrep/initializer.rb +39 -0
  28. data/lib/rubyrep/logged_change.rb +326 -0
  29. data/lib/rubyrep/proxied_table_scan.rb +171 -0
  30. data/lib/rubyrep/proxy_block_cursor.rb +145 -0
  31. data/lib/rubyrep/proxy_connection.rb +318 -0
  32. data/lib/rubyrep/proxy_cursor.rb +44 -0
  33. data/lib/rubyrep/proxy_row_cursor.rb +43 -0
  34. data/lib/rubyrep/proxy_runner.rb +89 -0
  35. data/lib/rubyrep/replication_difference.rb +91 -0
  36. data/lib/rubyrep/replication_extenders/mysql_replication.rb +271 -0
  37. data/lib/rubyrep/replication_extenders/postgresql_replication.rb +204 -0
  38. data/lib/rubyrep/replication_extenders/replication_extenders.rb +26 -0
  39. data/lib/rubyrep/replication_helper.rb +104 -0
  40. data/lib/rubyrep/replication_initializer.rb +307 -0
  41. data/lib/rubyrep/replication_run.rb +48 -0
  42. data/lib/rubyrep/replication_runner.rb +138 -0
  43. data/lib/rubyrep/replicators/replicators.rb +37 -0
  44. data/lib/rubyrep/replicators/two_way_replicator.rb +334 -0
  45. data/lib/rubyrep/scan_progress_printers/progress_bar.rb +65 -0
  46. data/lib/rubyrep/scan_progress_printers/scan_progress_printers.rb +65 -0
  47. data/lib/rubyrep/scan_report_printers/scan_detail_reporter.rb +111 -0
  48. data/lib/rubyrep/scan_report_printers/scan_report_printers.rb +67 -0
  49. data/lib/rubyrep/scan_report_printers/scan_summary_reporter.rb +75 -0
  50. data/lib/rubyrep/scan_runner.rb +25 -0
  51. data/lib/rubyrep/session.rb +177 -0
  52. data/lib/rubyrep/sync_helper.rb +111 -0
  53. data/lib/rubyrep/sync_runner.rb +31 -0
  54. data/lib/rubyrep/syncers/syncers.rb +112 -0
  55. data/lib/rubyrep/syncers/two_way_syncer.rb +174 -0
  56. data/lib/rubyrep/table_scan.rb +54 -0
  57. data/lib/rubyrep/table_scan_helper.rb +38 -0
  58. data/lib/rubyrep/table_sorter.rb +70 -0
  59. data/lib/rubyrep/table_spec_resolver.rb +136 -0
  60. data/lib/rubyrep/table_sync.rb +68 -0
  61. data/lib/rubyrep/trigger_mode_switcher.rb +63 -0
  62. data/lib/rubyrep/type_casting_cursor.rb +31 -0
  63. data/lib/rubyrep/uninstall_runner.rb +92 -0
  64. data/lib/rubyrep/version.rb +9 -0
  65. data/lib/rubyrep.rb +68 -0
  66. data/script/destroy +14 -0
  67. data/script/generate +14 -0
  68. data/script/txt2html +74 -0
  69. data/setup.rb +1585 -0
  70. data/sims/performance/big_rep_spec.rb +100 -0
  71. data/sims/performance/big_scan_spec.rb +57 -0
  72. data/sims/performance/big_sync_spec.rb +141 -0
  73. data/sims/performance/performance.rake +228 -0
  74. data/sims/sim_helper.rb +24 -0
  75. data/spec/base_runner_spec.rb +218 -0
  76. data/spec/buffered_committer_spec.rb +271 -0
  77. data/spec/command_runner_spec.rb +145 -0
  78. data/spec/committers_spec.rb +174 -0
  79. data/spec/configuration_spec.rb +198 -0
  80. data/spec/connection_extender_interface_spec.rb +138 -0
  81. data/spec/connection_extenders_registration_spec.rb +129 -0
  82. data/spec/database_proxy_spec.rb +48 -0
  83. data/spec/database_rake_spec.rb +40 -0
  84. data/spec/db_specific_connection_extenders_spec.rb +34 -0
  85. data/spec/db_specific_replication_extenders_spec.rb +38 -0
  86. data/spec/direct_table_scan_spec.rb +61 -0
  87. data/spec/generate_runner_spec.rb +84 -0
  88. data/spec/initializer_spec.rb +46 -0
  89. data/spec/logged_change_spec.rb +480 -0
  90. data/spec/postgresql_replication_spec.rb +48 -0
  91. data/spec/postgresql_support_spec.rb +57 -0
  92. data/spec/progress_bar_spec.rb +77 -0
  93. data/spec/proxied_table_scan_spec.rb +151 -0
  94. data/spec/proxy_block_cursor_spec.rb +197 -0
  95. data/spec/proxy_connection_spec.rb +399 -0
  96. data/spec/proxy_cursor_spec.rb +56 -0
  97. data/spec/proxy_row_cursor_spec.rb +66 -0
  98. data/spec/proxy_runner_spec.rb +70 -0
  99. data/spec/replication_difference_spec.rb +160 -0
  100. data/spec/replication_extender_interface_spec.rb +365 -0
  101. data/spec/replication_extenders_spec.rb +32 -0
  102. data/spec/replication_helper_spec.rb +121 -0
  103. data/spec/replication_initializer_spec.rb +477 -0
  104. data/spec/replication_run_spec.rb +166 -0
  105. data/spec/replication_runner_spec.rb +213 -0
  106. data/spec/replicators_spec.rb +31 -0
  107. data/spec/rubyrep_spec.rb +8 -0
  108. data/spec/scan_detail_reporter_spec.rb +119 -0
  109. data/spec/scan_progress_printers_spec.rb +68 -0
  110. data/spec/scan_report_printers_spec.rb +67 -0
  111. data/spec/scan_runner_spec.rb +50 -0
  112. data/spec/scan_summary_reporter_spec.rb +61 -0
  113. data/spec/session_spec.rb +212 -0
  114. data/spec/spec.opts +1 -0
  115. data/spec/spec_helper.rb +295 -0
  116. data/spec/sync_helper_spec.rb +157 -0
  117. data/spec/sync_runner_spec.rb +78 -0
  118. data/spec/syncers_spec.rb +171 -0
  119. data/spec/table_scan_helper_spec.rb +29 -0
  120. data/spec/table_scan_spec.rb +49 -0
  121. data/spec/table_sorter_spec.rb +31 -0
  122. data/spec/table_spec_resolver_spec.rb +102 -0
  123. data/spec/table_sync_spec.rb +84 -0
  124. data/spec/trigger_mode_switcher_spec.rb +83 -0
  125. data/spec/two_way_replicator_spec.rb +551 -0
  126. data/spec/two_way_syncer_spec.rb +256 -0
  127. data/spec/type_casting_cursor_spec.rb +50 -0
  128. data/spec/uninstall_runner_spec.rb +86 -0
  129. data/tasks/database.rake +439 -0
  130. data/tasks/deployment.rake +29 -0
  131. data/tasks/environment.rake +9 -0
  132. data/tasks/java.rake +37 -0
  133. data/tasks/redmine_test.rake +47 -0
  134. data/tasks/rspec.rake +68 -0
  135. data/tasks/rubyrep.tailor +18 -0
  136. data/tasks/stats.rake +19 -0
  137. data/tasks/task_helper.rb +20 -0
  138. data.tar.gz.sig +0 -0
  139. metadata +243 -0
  140. metadata.gz.sig +0 -0
@@ -0,0 +1,480 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ include RR
4
+
5
+ describe LoggedChange do
6
+ before(:each) do
7
+ Initializer.configuration = standard_config
8
+ end
9
+
10
+ it "initialize should store session and database" do
11
+ session = Session.new
12
+ change = LoggedChange.new session, :left
13
+ change.session.should == session
14
+ change.database.should == :left
15
+ end
16
+
17
+ it "load_specified should load the specified change" do
18
+ session = Session.new
19
+ session.left.begin_db_transaction
20
+ begin
21
+ session.left.insert_record 'rr_pending_changes', {
22
+ 'change_table' => 'left_table',
23
+ 'change_key' => 'id|1',
24
+ 'change_type' => 'I',
25
+ 'change_time' => Time.now
26
+ }
27
+ session.left.insert_record 'rr_pending_changes', {
28
+ 'change_table' => 'right_table',
29
+ 'change_key' => 'id|2',
30
+ 'change_new_key' => 'id|2',
31
+ 'change_type' => 'U',
32
+ 'change_time' => Time.now
33
+ }
34
+ session.left.insert_record 'rr_pending_changes', {
35
+ 'change_table' => 'left_table',
36
+ 'change_key' => 'id|2',
37
+ 'change_type' => 'I',
38
+ 'change_time' => Time.now
39
+ }
40
+ change = LoggedChange.new session, :left
41
+ change.load_specified 'left_table', {'id' => '2'}
42
+
43
+ change.table.should == 'left_table'
44
+ change.type.should == :insert
45
+ change.key.should == {'id' => '2'}
46
+ ensure
47
+ session.left.rollback_db_transaction
48
+ end
49
+ end
50
+
51
+ it "load_specified should accept a column_name => value hash as key" do
52
+ config = deep_copy(standard_config)
53
+ config.included_table_specs.clear
54
+ config.include_tables "scanner_records", :key => ['id1', 'id2']
55
+
56
+ session = Session.new config
57
+ session.left.begin_db_transaction
58
+ begin
59
+ session.left.insert_record 'rr_pending_changes', {
60
+ 'change_table' => 'scanner_records',
61
+ 'change_key' => 'id1|1|id2|2',
62
+ 'change_type' => 'I',
63
+ 'change_time' => Time.now
64
+ }
65
+ change = LoggedChange.new session, :left
66
+ change.load_specified 'scanner_records', {'id1' => 1, 'id2' => 2}
67
+
68
+ change.table.should == 'scanner_records'
69
+ change.type.should == :insert
70
+ change.key.should == {'id1' => '1', 'id2' => '2'}
71
+ ensure
72
+ session.left.rollback_db_transaction
73
+ end
74
+ end
75
+
76
+ it "load_specified should delete loaded changes from the database" do
77
+ session = Session.new
78
+ session.left.begin_db_transaction
79
+ begin
80
+ session.left.insert_record 'rr_pending_changes', {
81
+ 'change_table' => 'left_table',
82
+ 'change_key' => 'id|1',
83
+ 'change_type' => 'I',
84
+ 'change_time' => Time.now
85
+ }
86
+ change = LoggedChange.new session, :left
87
+ change.load_specified 'left_table', {'id' => 1}
88
+
89
+ session.left.
90
+ select_one("select * from rr_pending_changes where change_key = 'id|1'").
91
+ should be_nil
92
+ ensure
93
+ session.left.rollback_db_transaction
94
+ end
95
+ end
96
+
97
+ it "load_specified should set first_change_at and last_changed_at correctly" do
98
+ session = Session.new
99
+ session.left.begin_db_transaction
100
+ begin
101
+ t1 = 5.seconds.ago
102
+ t2 = 5.seconds.from_now
103
+ session.left.insert_record 'rr_pending_changes', {
104
+ 'change_table' => 'left_table',
105
+ 'change_key' => 'id|1',
106
+ 'change_type' => 'I',
107
+ 'change_time' => t1
108
+ }
109
+ session.left.insert_record 'rr_pending_changes', {
110
+ 'change_table' => 'left_table',
111
+ 'change_key' => 'id|1',
112
+ 'change_new_key' => 'id|1',
113
+ 'change_type' => 'U',
114
+ 'change_time' => t2
115
+ }
116
+ change = LoggedChange.new session, :left
117
+ change.load_specified 'left_table', {'id' => 1}
118
+
119
+ change.first_changed_at.to_s.should == t1.to_s
120
+ change.last_changed_at.to_s.should == t2.to_s
121
+ ensure
122
+ session.left.rollback_db_transaction
123
+ end
124
+ end
125
+
126
+ it "load_specified should follow primary key updates correctly" do
127
+ session = Session.new
128
+ session.left.begin_db_transaction
129
+ begin
130
+ session.left.insert_record 'rr_pending_changes', {
131
+ 'change_table' => 'left_table',
132
+ 'change_key' => 'id|1',
133
+ 'change_new_key' => 'id|2',
134
+ 'change_type' => 'U',
135
+ 'change_time' => Time.now
136
+ }
137
+ session.left.insert_record 'rr_pending_changes', {
138
+ 'change_table' => 'left_table',
139
+ 'change_key' => 'id|2',
140
+ 'change_new_key' => 'id|3',
141
+ 'change_type' => 'U',
142
+ 'change_time' => Time.now
143
+ }
144
+ change = LoggedChange.new session, :left
145
+ change.load_specified 'left_table', {'id' => 1}
146
+
147
+ change.type.should == :update
148
+ change.key.should == {'id' => 1}
149
+ change.new_key.should == {'id' => '3'}
150
+ ensure
151
+ session.left.rollback_db_transaction
152
+ end
153
+ end
154
+
155
+ it "load_specified should recognize if changes cancel each other out" do
156
+ session = Session.new
157
+ session.left.begin_db_transaction
158
+ begin
159
+ session.left.insert_record 'rr_pending_changes', {
160
+ 'change_table' => 'left_table',
161
+ 'change_key' => 'id|1',
162
+ 'change_type' => 'I',
163
+ 'change_time' => Time.now
164
+ }
165
+ session.left.insert_record 'rr_pending_changes', {
166
+ 'change_table' => 'left_table',
167
+ 'change_key' => 'id|1',
168
+ 'change_new_key' => 'id|2',
169
+ 'change_type' => 'U',
170
+ 'change_time' => Time.now
171
+ }
172
+ session.left.insert_record 'rr_pending_changes', {
173
+ 'change_table' => 'left_table',
174
+ 'change_key' => 'id|2',
175
+ 'change_type' => 'D',
176
+ 'change_time' => Time.now
177
+ }
178
+ change = LoggedChange.new session, :left
179
+ change.load_specified 'left_table', {'id' => '1'}
180
+
181
+ change.type.should == :no_change
182
+ ensure
183
+ session.left.rollback_db_transaction
184
+ end
185
+ end
186
+
187
+ it "load_specified should transist states correctly" do
188
+ session = Session.new
189
+ session.left.begin_db_transaction
190
+ begin
191
+
192
+ # first test case
193
+ session.left.insert_record 'rr_pending_changes', {
194
+ 'change_table' => 'left_table',
195
+ 'change_key' => 'id|1',
196
+ 'change_type' => 'I',
197
+ 'change_time' => Time.now
198
+ }
199
+ session.left.insert_record 'rr_pending_changes', {
200
+ 'change_table' => 'left_table',
201
+ 'change_key' => 'id|1',
202
+ 'change_type' => 'D',
203
+ 'change_time' => Time.now
204
+ }
205
+ session.left.insert_record 'rr_pending_changes', {
206
+ 'change_table' => 'left_table',
207
+ 'change_key' => 'id|1',
208
+ 'change_type' => 'I',
209
+ 'change_time' => Time.now
210
+ }
211
+ session.left.insert_record 'rr_pending_changes', {
212
+ 'change_table' => 'left_table',
213
+ 'change_key' => 'id|1',
214
+ 'change_new_key' => 'id|2',
215
+ 'change_type' => 'U',
216
+ 'change_time' => Time.now
217
+ }
218
+ change = LoggedChange.new session, :left
219
+ change.load_specified 'left_table', {'id' => '1'}
220
+ change.type.should == :insert
221
+ change.key.should == {'id' => '2'}
222
+
223
+ # second test case
224
+ session.left.insert_record 'rr_pending_changes', {
225
+ 'change_table' => 'left_table',
226
+ 'change_key' => 'id|5',
227
+ 'change_type' => 'D',
228
+ 'change_time' => Time.now
229
+ }
230
+ session.left.insert_record 'rr_pending_changes', {
231
+ 'change_table' => 'left_table',
232
+ 'change_key' => 'id|5',
233
+ 'change_type' => 'I',
234
+ 'change_time' => Time.now
235
+ }
236
+ session.reload_changes
237
+ change = LoggedChange.new session, :left
238
+ change.load_specified 'left_table', {'id' => '5'}
239
+ change.type.should == :update
240
+ change.key.should == {'id' => '5'}
241
+ change.new_key.should == {'id' => '5'}
242
+ ensure
243
+ session.left.rollback_db_transaction
244
+ end
245
+ end
246
+
247
+ it "amend should work if there were no changes" do
248
+ session = Session.new
249
+ session.left.begin_db_transaction
250
+ begin
251
+ session.left.insert_record 'rr_pending_changes', {
252
+ 'change_table' => 'scanner_records',
253
+ 'change_key' => 'id|1',
254
+ 'change_type' => 'I',
255
+ 'change_time' => Time.now
256
+ }
257
+ change = LoggedChange.new session, :left
258
+ change.load_specified 'scanner_records', {'id' => '1'}
259
+
260
+ change.table.should == 'scanner_records'
261
+ change.type.should == :insert
262
+ change.key.should == {'id' => '1'}
263
+
264
+ change.load
265
+
266
+ change.table.should == 'scanner_records'
267
+ change.type.should == :insert
268
+ change.key.should == {'id' => '1'}
269
+ ensure
270
+ session.left.rollback_db_transaction
271
+ end
272
+ end
273
+
274
+ it "amend should work if the current type is :no_change" do
275
+ session = Session.new
276
+ session.left.begin_db_transaction
277
+ begin
278
+ change = LoggedChange.new session, :left
279
+ change.load_specified 'scanner_records', {'id' => '1'}
280
+
281
+ change.table.should == 'scanner_records'
282
+ change.type.should == :no_change
283
+ change.key.should == {'id' => '1'}
284
+
285
+ change.load
286
+
287
+ change.table.should == 'scanner_records'
288
+ change.type.should == :no_change
289
+ change.key.should == {'id' => '1'}
290
+ ensure
291
+ session.left.rollback_db_transaction
292
+ end
293
+ end
294
+
295
+ it "amend should amend the change correctly" do
296
+ session = Session.new
297
+ session.left.begin_db_transaction
298
+ begin
299
+ session.left.insert_record 'left_table', {
300
+ :id => '1',
301
+ :name => 'bla'
302
+ }
303
+ session.left.insert_record 'rr_pending_changes', {
304
+ 'change_table' => 'left_table',
305
+ 'change_key' => 'id|1',
306
+ 'change_new_key' => 'id|1',
307
+ 'change_type' => 'U',
308
+ 'change_time' => Time.now
309
+ }
310
+ change = LoggedChange.new session, :left
311
+ change.load_specified 'left_table', {'id' => '1'}
312
+ session.left.insert_record 'rr_pending_changes', {
313
+ 'change_table' => 'left_table',
314
+ 'change_key' => 'id|1',
315
+ 'change_type' => 'D',
316
+ 'change_time' => Time.now
317
+ }
318
+ session.reload_changes
319
+ change.load
320
+
321
+ change.table.should == 'left_table'
322
+ change.type.should == :delete
323
+ change.key.should == {'id' => '1'}
324
+ ensure
325
+ session.left.rollback_db_transaction
326
+ end
327
+ end
328
+
329
+ it "amend should support primary key updates" do
330
+ session = Session.new
331
+ session.left.begin_db_transaction
332
+ begin
333
+ session.left.insert_record 'left_table', {
334
+ :id => '1',
335
+ :name => 'bla'
336
+ }
337
+ session.left.insert_record 'rr_pending_changes', {
338
+ 'change_table' => 'left_table',
339
+ 'change_key' => 'id|1',
340
+ 'change_new_key' => 'id|2',
341
+ 'change_type' => 'U',
342
+ 'change_time' => Time.now
343
+ }
344
+ change = LoggedChange.new session, :left
345
+ change.load_specified 'left_table', {'id' => '1'}
346
+ session.left.insert_record 'rr_pending_changes', {
347
+ 'change_table' => 'left_table',
348
+ 'change_key' => 'id|2',
349
+ 'change_new_key' => 'id|3',
350
+ 'change_type' => 'U',
351
+ 'change_time' => Time.now
352
+ }
353
+ session.reload_changes
354
+ change.load
355
+
356
+ change.table.should == 'left_table'
357
+ change.type.should == :update
358
+ change.key.should == {'id' => '1'}
359
+ change.new_key.should == {'id' => '3'}
360
+ ensure
361
+ session.left.rollback_db_transaction
362
+ end
363
+ end
364
+
365
+ it "oldest_change_time should return nil if there are no changes" do
366
+ session = Session.new
367
+ session.left.execute "delete from rr_pending_changes"
368
+ change = LoggedChange.new session, :left
369
+ change.oldest_change_time.should be_nil
370
+ end
371
+
372
+ it "oldest_change_time should return the time of the oldest change" do
373
+ session = Session.new
374
+ session.left.begin_db_transaction
375
+ begin
376
+ time = Time.now
377
+ session.left.insert_record 'rr_pending_changes', {
378
+ 'change_table' => 'left_table',
379
+ 'change_key' => 'id|1',
380
+ 'change_type' => 'I',
381
+ 'change_time' => time
382
+ }
383
+ session.left.insert_record 'rr_pending_changes', {
384
+ 'change_table' => 'left_table',
385
+ 'change_key' => 'id|2',
386
+ 'change_type' => 'I',
387
+ 'change_time' => 100.seconds.from_now
388
+ }
389
+ change = LoggedChange.new session, :left
390
+ change.oldest_change_time.should.to_s == time.to_s
391
+ ensure
392
+ session.left.rollback_db_transaction
393
+ end
394
+ end
395
+
396
+ it "key_from_raw_key should return the correct column_name => value hash for the given key" do
397
+ change = LoggedChange.new Session.new, :left
398
+ change.key_to_hash("a|1|b|2").should == {
399
+ 'a' => '1',
400
+ 'b' => '2'
401
+ }
402
+ end
403
+
404
+ it "key_from_raw_key should work with multi character key_sep strings" do
405
+ change = LoggedChange.new Session.new, :left
406
+ change.stub!(:key_sep).and_return('BLA')
407
+ change.key_to_hash("aBLA1BLAbBLA2").should == {
408
+ 'a' => '1',
409
+ 'b' => '2'
410
+ }
411
+ end
412
+
413
+ it "load_oldest should not load a change if none available" do
414
+ change = LoggedChange.new Session.new, :left
415
+ change.should_not_receive :load_specified
416
+ change.load_oldest
417
+ end
418
+
419
+ it "load_oldest should load the oldest available change" do
420
+ session = Session.new
421
+ session.left.begin_db_transaction
422
+ begin
423
+ session.left.insert_record 'rr_pending_changes', {
424
+ 'change_table' => 'left_table',
425
+ 'change_key' => 'id|1',
426
+ 'change_type' => 'I',
427
+ 'change_time' => Time.now
428
+ }
429
+ session.left.insert_record 'rr_pending_changes', {
430
+ 'change_table' => 'left_table',
431
+ 'change_key' => 'id|2',
432
+ 'change_type' => 'I',
433
+ 'change_time' => Time.now
434
+ }
435
+ change = LoggedChange.new session, :left
436
+ change.load_oldest
437
+
438
+ change.key.should == {'id' => '1'}
439
+ ensure
440
+ session.left.rollback_db_transaction
441
+ end
442
+ end
443
+
444
+ it "load_oldest should skip irrelevant changes" do
445
+ session = Session.new
446
+ session.left.begin_db_transaction
447
+ begin
448
+ session.left.insert_record 'rr_pending_changes', {
449
+ 'change_table' => 'left_table',
450
+ 'change_key' => 'id|1',
451
+ 'change_type' => 'I',
452
+ 'change_time' => Time.now
453
+ }
454
+ session.left.insert_record 'rr_pending_changes', {
455
+ 'change_table' => 'left_table',
456
+ 'change_key' => 'id|1',
457
+ 'change_type' => 'D',
458
+ 'change_time' => Time.now
459
+ }
460
+ session.left.insert_record 'rr_pending_changes', {
461
+ 'change_table' => 'left_table',
462
+ 'change_key' => 'id|2',
463
+ 'change_type' => 'I',
464
+ 'change_time' => Time.now
465
+ }
466
+ change = LoggedChange.new session, :left
467
+ change.load_oldest
468
+
469
+ change.type.should == :insert
470
+ change.key.should == {'id' => '2'}
471
+ ensure
472
+ session.left.rollback_db_transaction
473
+ end
474
+ end
475
+
476
+ it "to_yaml should blank out session" do
477
+ change = LoggedChange.new :dummy_session, :left
478
+ change.to_yaml.should_not =~ /session/
479
+ end
480
+ end
@@ -0,0 +1,48 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+ require 'yaml'
3
+ require 'config/test_config.rb'
4
+
5
+ include RR
6
+
7
+ describe "PostgreSQLReplication", :shared => true do
8
+ before(:each) do
9
+ end
10
+
11
+ it "create_replication_trigger should also work if language plpgsql does not yet exist" do
12
+ session = nil
13
+ begin
14
+ session = Session.new
15
+ session.left.begin_db_transaction
16
+ unless session.left.select_all("select lanname from pg_language where lanname = 'plpgsql'").empty?
17
+ session.left.execute "DROP LANGUAGE plpgsql"
18
+ end
19
+ params = {
20
+ :trigger_name => 'rr_trigger_test',
21
+ :table => 'trigger_test',
22
+ :keys => ['first_id', 'second_id'],
23
+ :log_table => 'rr_pending_changes',
24
+ :key_sep => '|',
25
+ :exclude_rr_activity => false,
26
+ }
27
+ session.left.create_replication_trigger params
28
+ session.left.insert_record 'trigger_test', {
29
+ 'first_id' => 1,
30
+ 'second_id' => 2,
31
+ 'name' => 'bla'
32
+ }
33
+
34
+ row = session.left.select_one("select * from rr_pending_changes")
35
+ row.delete 'id'
36
+ row.delete 'change_time'
37
+ row.should == {
38
+ 'change_table' => 'trigger_test',
39
+ 'change_key' => 'first_id|1|second_id|2',
40
+ 'change_new_key' => nil,
41
+ 'change_type' => 'I'
42
+ }
43
+
44
+ ensure
45
+ session.left.rollback_db_transaction if session
46
+ end
47
+ end
48
+ end
@@ -0,0 +1,57 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ include RR
4
+
5
+ require File.dirname(__FILE__) + "/../config/test_config.rb"
6
+
7
+ describe "PostgreSQL schema support" do
8
+ before(:each) do
9
+ Initializer.configuration = standard_config
10
+ end
11
+
12
+ after(:each) do
13
+ end
14
+
15
+ if Initializer.configuration.left[:adapter] == 'postgresql'
16
+
17
+ it "should read & write microsecond times" do
18
+ session = nil
19
+ begin
20
+ session = Session.new
21
+ session.left.begin_db_transaction
22
+ session.left.insert_record('extender_type_check',
23
+ {'id' => 2, 'timestamp' => Time.local(2009, "feb", 16, 20, 48, 1, 543)}
24
+ )
25
+
26
+ org_cursor = session.left.select_cursor(:query => "select id, timestamp from extender_type_check where id = 2")
27
+ cursor = TypeCastingCursor.new session.left, 'extender_type_check', org_cursor
28
+
29
+ row = cursor.next_row
30
+ row['timestamp'].usec.should == 543
31
+ cursor.clear
32
+ ensure
33
+ session.left.rollback_db_transaction if session
34
+ end
35
+ end
36
+
37
+ it "should not round microsecond times to incorrect value" do
38
+ session = nil
39
+ begin
40
+ session = Session.new
41
+ session.left.begin_db_transaction
42
+ session.left.insert_record('extender_type_check',
43
+ {'id' => 2, 'timestamp' => Time.local(2009, "feb", 16, 13, 37, 11, 126291)}
44
+ )
45
+
46
+ org_cursor = session.left.select_cursor(:query => "select id, timestamp from extender_type_check where id = 2")
47
+ cursor = TypeCastingCursor.new session.left, 'extender_type_check', org_cursor
48
+
49
+ row = cursor.next_row
50
+ row['timestamp'].usec.should == 126291
51
+ cursor.clear
52
+ ensure
53
+ session.left.rollback_db_transaction if session
54
+ end
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,77 @@
1
+ require File.dirname(__FILE__) + '/spec_helper.rb'
2
+
3
+ include RR
4
+ include ScanProgressPrinters
5
+
6
+ describe ProgressBar do
7
+ before(:each) do
8
+ @org_stdout = $stdout
9
+ $stdout = StringIO.new
10
+ @old_arg = ProgressBar.arg
11
+ end
12
+
13
+ after(:each) do
14
+ ProgressBar.arg = @old_arg
15
+ $stdout = @org_stdout
16
+ end
17
+
18
+ it "arg should store the command line argument and max_markers return the correct marker number" do
19
+ ProgressBar.arg = nil
20
+ ProgressBar.new(100, Session.new(standard_config), 'bla', 'blub').max_markers.should == ProgressBar::MAX_MARKERS
21
+ ProgressBar.arg = "2"
22
+ ProgressBar.new(100, Session.new(standard_config), 'bla', 'blub').max_markers.should == 2
23
+ end
24
+
25
+ it "step should use ANSI codes if options :use_ansi is set" do
26
+ session = Session.new(deep_copy(standard_config))
27
+ session.configuration.options[:use_ansi] = true
28
+ bar = ProgressBar.new(10, session, 'bla', 'blub')
29
+ bar.step 1
30
+ bar.step 1
31
+ $stdout.string.should =~ Regexp.new(Regexp.escape("\e[1"))
32
+ end
33
+
34
+ it "step should not use ANSI codes if options :use_ansi is not true" do
35
+ session = Session.new(deep_copy(standard_config))
36
+ session.configuration.options[:use_ansi] = false
37
+ bar = ProgressBar.new(10, session, 'bla', 'blub')
38
+ bar.step 1
39
+ bar.step 1
40
+ $stdout.string.should_not =~ Regexp.new(Regexp.escape("\e[1"))
41
+ end
42
+
43
+ it "should register itself with ScanRunner" do
44
+ RR::ScanProgressPrinters.printers[:progress_bar][:printer_class].
45
+ should == ProgressBar
46
+ end
47
+
48
+ it "step should print the correct progress" do
49
+ bar = ProgressBar.new(1000, Session.new(standard_config), 'bla', 'blub')
50
+ bar.step 200
51
+ bar.step 300
52
+ $stdout.string.count('.').should == ProgressBar::MAX_MARKERS / 2
53
+ bar.step 500
54
+ $stdout.string.count('.').should == ProgressBar::MAX_MARKERS
55
+ end
56
+
57
+ it "step should work around weird floating point rounding issues" do
58
+ bar = ProgressBar.new(56, Session.new(standard_config), 'bla', 'blub')
59
+ (1..56).each {bar.step 1}
60
+ $stdout.string.count('.').should == ProgressBar::MAX_MARKERS
61
+ end
62
+
63
+ it "if max_steps is 0, any step call should go to 100% progress" do
64
+ config = deep_copy(standard_config)
65
+ config.options[:use_ansi] = true
66
+ bar = ProgressBar.new(0, Session.new(config), 'bla', 'blub')
67
+ bar.step
68
+ $stdout.string.count('.').should == ProgressBar::MAX_MARKERS
69
+ $stdout.string.should =~ /100%/
70
+
71
+ # Ensure we don't go over 100%
72
+ $stdout = StringIO.new
73
+ bar.step
74
+ $stdout.string.should == ''
75
+ end
76
+
77
+ end