pseudo_cleaner 0.0.25
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.
- checksums.yaml +15 -0
- data/.gitignore +18 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +142 -0
- data/Rakefile +1 -0
- data/lib/pseudo_cleaner.rb +12 -0
- data/lib/pseudo_cleaner/configuration.rb +44 -0
- data/lib/pseudo_cleaner/cucumber.rb +44 -0
- data/lib/pseudo_cleaner/logger.rb +9 -0
- data/lib/pseudo_cleaner/master_cleaner.rb +380 -0
- data/lib/pseudo_cleaner/rspec.rb +45 -0
- data/lib/pseudo_cleaner/spinach.rb +38 -0
- data/lib/pseudo_cleaner/table_cleaner.rb +557 -0
- data/lib/pseudo_cleaner/version.rb +3 -0
- data/pseudo_cleaner.gemspec +26 -0
- metadata +116 -0
@@ -0,0 +1,45 @@
|
|
1
|
+
RSpec.configure do |config|
|
2
|
+
config.before(:suite) do
|
3
|
+
if PseudoCleaner::Configuration.current_instance.clean_database_before_tests
|
4
|
+
PseudoCleaner::MasterCleaner.reset_database
|
5
|
+
else
|
6
|
+
PseudoCleaner::MasterCleaner.start_suite
|
7
|
+
end
|
8
|
+
|
9
|
+
# We start suite in case a custom cleaner wants/needs to.
|
10
|
+
DatabaseCleaner.strategy = :transaction
|
11
|
+
end
|
12
|
+
|
13
|
+
config.after(:suite) do
|
14
|
+
# We end suite in case a custom cleaner wants/needs to.
|
15
|
+
PseudoCleaner::MasterCleaner.end_suite
|
16
|
+
end
|
17
|
+
|
18
|
+
config.before(:each) do |example|
|
19
|
+
new_strategy = nil
|
20
|
+
|
21
|
+
clean_example = example
|
22
|
+
clean_example = example.example if example.respond_to?(:example)
|
23
|
+
|
24
|
+
new_strategy = clean_example.metadata[:strategy]
|
25
|
+
|
26
|
+
if new_strategy && !PseudoCleaner::MasterCleaner::CLEANING_STRATEGIES.include?(new_strategy)
|
27
|
+
PseudoCleaner::Logger.write "*** Unknown/invalid cleaning strategy #{clean_example.metadata[:strategy]}. Using default: :transaction ***".red.on_light_white
|
28
|
+
new_strategy = :transaction
|
29
|
+
end
|
30
|
+
if clean_example.metadata[:js]
|
31
|
+
new_strategy ||= :pseudo_delete
|
32
|
+
new_strategy = :pseudo_delete if new_strategy == :transaction
|
33
|
+
end
|
34
|
+
new_strategy ||= :transaction
|
35
|
+
|
36
|
+
PseudoCleaner::MasterCleaner.start_example(clean_example, new_strategy)
|
37
|
+
end
|
38
|
+
|
39
|
+
config.after(:each) do |example|
|
40
|
+
clean_example = example
|
41
|
+
clean_example = example.example if example.respond_to?(:example)
|
42
|
+
|
43
|
+
PseudoCleaner::MasterCleaner.end_example(clean_example)
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
first_test_run = false
|
2
|
+
|
3
|
+
# I haven't tested this fully yet, but I think that this should work.
|
4
|
+
|
5
|
+
Spinach.hooks.before_scenario do |scenario, step_definitions|
|
6
|
+
unless first_test_run
|
7
|
+
first_test_run = true
|
8
|
+
# before tests run...
|
9
|
+
# We start suite in case a custom cleaner wants/needs to.
|
10
|
+
if PseudoCleaner::Configuration.current_instance.clean_database_before_tests
|
11
|
+
PseudoCleaner::MasterCleaner.reset_database
|
12
|
+
else
|
13
|
+
PseudoCleaner::MasterCleaner.start_suite
|
14
|
+
end
|
15
|
+
|
16
|
+
DatabaseCleaner.strategy = :transaction
|
17
|
+
end
|
18
|
+
|
19
|
+
strategy = if scenario.tags.include?("@none")
|
20
|
+
:none
|
21
|
+
elsif scenario.tags.include?("@truncation")
|
22
|
+
:truncation
|
23
|
+
elsif scenario.tags.include?("@deletion")
|
24
|
+
:deletion
|
25
|
+
else
|
26
|
+
:pseudo_delete
|
27
|
+
end
|
28
|
+
PseudoCleaner::MasterCleaner.start_example(scenario, strategy)
|
29
|
+
end
|
30
|
+
|
31
|
+
Spinach.hooks.after_scenario do |scenario, step_definitions|
|
32
|
+
PseudoCleaner::MasterCleaner.end_example(scenario)
|
33
|
+
end
|
34
|
+
|
35
|
+
Spinach.hooks.after_run do |status|
|
36
|
+
# We end suite in case a custom cleaner wants/needs to.
|
37
|
+
PseudoCleaner::MasterCleaner.end_suite
|
38
|
+
end
|
@@ -0,0 +1,557 @@
|
|
1
|
+
module PseudoCleaner
|
2
|
+
class TableCleaner
|
3
|
+
attr_accessor :table
|
4
|
+
|
5
|
+
@@initial_states = {}
|
6
|
+
|
7
|
+
def reset_suite
|
8
|
+
@@initial_states = {}
|
9
|
+
end
|
10
|
+
|
11
|
+
def initialize(start_method, end_method, table, options = {})
|
12
|
+
raise "You must specify a table object." unless table
|
13
|
+
unless PseudoCleaner::MasterCleaner::VALID_START_METHODS.include?(start_method)
|
14
|
+
raise "You must specify a valid start function from: #{PseudoCleaner::MasterCleaner::VALID_START_METHODS}."
|
15
|
+
end
|
16
|
+
unless PseudoCleaner::MasterCleaner::VALID_END_METHODS.include?(end_method)
|
17
|
+
raise "You must specify a valid end function from: #{PseudoCleaner::MasterCleaner::VALID_END_METHODS}."
|
18
|
+
end
|
19
|
+
|
20
|
+
@table = table
|
21
|
+
|
22
|
+
@@initial_states[@table] ||= {}
|
23
|
+
initial_state = @@initial_states[@table]
|
24
|
+
|
25
|
+
@options = options
|
26
|
+
|
27
|
+
@options[:table_start_method] ||= start_method
|
28
|
+
@options[:table_end_method] ||= end_method
|
29
|
+
@options[:output_diagnostics] ||= PseudoCleaner::Configuration.current_instance.output_diagnostics ||
|
30
|
+
PseudoCleaner::Configuration.current_instance.post_transaction_analysis
|
31
|
+
|
32
|
+
unless initial_state.has_key?(:table_is_active_record)
|
33
|
+
initial_state[:table_is_active_record] = false
|
34
|
+
|
35
|
+
if Object.const_defined?("ActiveRecord", false) && ActiveRecord.const_defined?("Base", false)
|
36
|
+
if symbol_table?
|
37
|
+
initial_state[:table_is_active_record] = true
|
38
|
+
initial_state[:table_name] = table
|
39
|
+
else
|
40
|
+
table_super_class = table.superclass
|
41
|
+
|
42
|
+
while !initial_state[:table_is_active_record] && table_super_class
|
43
|
+
initial_state[:table_is_active_record] = (table_super_class == ActiveRecord::Base)
|
44
|
+
initial_state[:table_name] = table.name if initial_state[:table_is_active_record]
|
45
|
+
table_super_class = table_super_class.superclass
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
unless initial_state.has_key?(:table_is_sequel_model)
|
52
|
+
initial_state[:table_is_sequel_model] = false
|
53
|
+
|
54
|
+
if Object.const_defined?("Sequel", false) && Sequel.const_defined?("Model", false)
|
55
|
+
if symbol_table?
|
56
|
+
initial_state[:table_is_sequel_model] = PseudoCleaner::Configuration.db_connection(:sequel)[table]
|
57
|
+
initial_state[:table_name] = table
|
58
|
+
else
|
59
|
+
table_super_class = table.superclass
|
60
|
+
|
61
|
+
while !initial_state[:table_is_sequel_model] && table_super_class
|
62
|
+
initial_state[:table_is_sequel_model] = (table_super_class == Sequel::Model)
|
63
|
+
initial_state[:table_name] = table.name if initial_state[:table_is_sequel_model]
|
64
|
+
table_super_class = table_super_class.superclass
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def test_start test_strategy
|
72
|
+
@test_strategy ||= test_strategy
|
73
|
+
save_state
|
74
|
+
end
|
75
|
+
|
76
|
+
def suite_start test_strategy
|
77
|
+
@test_strategy ||= test_strategy
|
78
|
+
save_state
|
79
|
+
end
|
80
|
+
|
81
|
+
def save_state
|
82
|
+
initial_state = @@initial_states[@table]
|
83
|
+
|
84
|
+
if @test_strategy == :pseudo_delete && !initial_state[:saved]
|
85
|
+
initial_state[:saved] = true
|
86
|
+
|
87
|
+
if @options[:output_diagnostics]
|
88
|
+
PseudoCleaner::Logger.write(" Gathering information about \"#{initial_state[:table_name]}\"...".blue.on_light_white)
|
89
|
+
end
|
90
|
+
|
91
|
+
if initial_state[:table_is_active_record]
|
92
|
+
test_start_active_record @test_strategy
|
93
|
+
end
|
94
|
+
|
95
|
+
if initial_state[:table_is_sequel_model]
|
96
|
+
test_start_sequel_model @test_strategy
|
97
|
+
end
|
98
|
+
|
99
|
+
if PseudoCleaner::Configuration.current_instance.reset_auto_increment
|
100
|
+
reset_auto_increment !PseudoCleaner::Configuration.current_instance.clean_database_before_tests
|
101
|
+
end
|
102
|
+
|
103
|
+
if initial_state.has_key?(:count) && @options[:output_diagnostics]
|
104
|
+
PseudoCleaner::Logger.write(" *** There are no columns to track inserts and updates easily on for #{initial_state[:table_name]} ***".red.on_light_white)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
def symbol_table?
|
110
|
+
table.is_a?(String) || table.is_a?(Symbol)
|
111
|
+
end
|
112
|
+
|
113
|
+
def active_record_table
|
114
|
+
if symbol_table?
|
115
|
+
table
|
116
|
+
else
|
117
|
+
table.table_name
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
121
|
+
def test_start_active_record test_strategy
|
122
|
+
new_state = {}
|
123
|
+
|
124
|
+
table_name = active_record_table
|
125
|
+
if PseudoCleaner::Configuration.db_connection(:active_record).connection.columns(table_name).find { |column| column.name == "id" }
|
126
|
+
new_state[:max_id] = PseudoCleaner::Configuration.db_connection(:active_record).connection.
|
127
|
+
execute("SELECT MAX(`id`) FROM `#{table_name}`").first[0] || 0
|
128
|
+
PseudoCleaner::Logger.write(" max(id) = #{new_state[:max_id]}") if @options[:output_diagnostics]
|
129
|
+
end
|
130
|
+
|
131
|
+
[:created, :updated].each do |date_name|
|
132
|
+
[:at, :on].each do |verb_name|
|
133
|
+
date_column_name = "#{date_name}_#{verb_name}"
|
134
|
+
|
135
|
+
if PseudoCleaner::Configuration.db_connection(:active_record).connection.
|
136
|
+
columns(table_name).find { |column| column.name == date_column_name }
|
137
|
+
new_state[date_name] = {
|
138
|
+
column_name: date_column_name,
|
139
|
+
value: PseudoCleaner::Configuration.db_connection(:active_record).connection.
|
140
|
+
execute("SELECT MAX(`#{date_column_name}`) FROM `#{table_name}`").first[0] ||
|
141
|
+
Time.now - 1.second
|
142
|
+
}
|
143
|
+
if @options[:output_diagnostics]
|
144
|
+
PseudoCleaner::Logger.write(" max(#{new_state[date_name][:column_name]}) = #{new_state[date_name][:value]}")
|
145
|
+
end
|
146
|
+
|
147
|
+
break
|
148
|
+
end
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
new_state[:blank] = new_state.blank?
|
153
|
+
new_state[:count] = PseudoCleaner::Configuration.db_connection(:active_record).connection.
|
154
|
+
execute("SELECT COUNT(*) FROM `#{table_name}`").first[0]
|
155
|
+
|
156
|
+
@@initial_states[@table] = @@initial_states[@table].merge new_state
|
157
|
+
end
|
158
|
+
|
159
|
+
def test_start_sequel_model test_strategy
|
160
|
+
new_state = {}
|
161
|
+
access_table = sequel_model_table
|
162
|
+
|
163
|
+
if access_table.columns.include?(:id)
|
164
|
+
new_state[:max_id] = access_table.unfiltered.max(:id) || 0
|
165
|
+
PseudoCleaner::Logger.write(" max(id) = #{new_state[:max_id]}") if @options[:output_diagnostics]
|
166
|
+
end
|
167
|
+
|
168
|
+
[:created, :updated].each do |date_name|
|
169
|
+
[:at, :on].each do |verb_name|
|
170
|
+
date_column_name = "#{date_name}_#{verb_name}".to_sym
|
171
|
+
|
172
|
+
if access_table.columns.include?(date_column_name)
|
173
|
+
new_state[date_name] = {
|
174
|
+
column_name: date_column_name,
|
175
|
+
value: access_table.unfiltered.max(date_column_name) || Time.now - 1.second
|
176
|
+
}
|
177
|
+
if @options[:output_diagnostics]
|
178
|
+
PseudoCleaner::Logger.write(" max(#{new_state[date_name][:column_name]}) = #{new_state[date_name][:value]}")
|
179
|
+
end
|
180
|
+
|
181
|
+
break
|
182
|
+
end
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
186
|
+
new_state[:blank] = new_state.blank?
|
187
|
+
new_state[:count] = access_table.unfiltered.count
|
188
|
+
|
189
|
+
@@initial_states[@table] = @@initial_states[@table].merge new_state
|
190
|
+
end
|
191
|
+
|
192
|
+
def test_end test_strategy
|
193
|
+
reset_table test_strategy
|
194
|
+
end
|
195
|
+
|
196
|
+
def suite_end test_strategy
|
197
|
+
reset_table test_strategy
|
198
|
+
end
|
199
|
+
|
200
|
+
def reset_table test_strategy
|
201
|
+
if @test_strategy != test_strategy && !PseudoCleaner::Configuration.current_instance.single_cleaner_set
|
202
|
+
if @options[:output_diagnostics]
|
203
|
+
PseudoCleaner::Logger.write(" *** The ending strategy for \"#{initial_state[:table_name]}\" changed! ***".red.on_light_white)
|
204
|
+
end
|
205
|
+
end
|
206
|
+
|
207
|
+
if test_strategy == :pseudo_delete || PseudoCleaner::Configuration.current_instance.post_transaction_analysis
|
208
|
+
initial_state = @@initial_states[@table]
|
209
|
+
|
210
|
+
# we should check the relationships for any records which still refer to
|
211
|
+
# a now deleted record. (i.e. if we updated a record to refer to a record)
|
212
|
+
# we deleted...
|
213
|
+
#
|
214
|
+
# Which is why this is not a common or particularly good solution.
|
215
|
+
#
|
216
|
+
# I'm using it because it is faster than reseeding each test...
|
217
|
+
# And, I can be responsible for worrying about referential integrity in the test
|
218
|
+
# if I want to...
|
219
|
+
PseudoCleaner::Logger.write(" Resetting table \"#{initial_state[:table_name]}\"...") if @options[:output_diagnostics]
|
220
|
+
|
221
|
+
if initial_state[:table_is_active_record]
|
222
|
+
test_end_active_record test_strategy
|
223
|
+
end
|
224
|
+
|
225
|
+
if initial_state[:table_is_sequel_model]
|
226
|
+
test_end_sequel_model test_strategy
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
230
|
+
|
231
|
+
def test_end_active_record test_strategy
|
232
|
+
initial_state = @@initial_states[@table]
|
233
|
+
cleaned_table = false
|
234
|
+
|
235
|
+
table_name = active_record_table
|
236
|
+
if initial_state[:max_id]
|
237
|
+
the_max = initial_state[:max_id] || 0
|
238
|
+
|
239
|
+
PseudoCleaner::Configuration.db_connection(:active_record).connection.
|
240
|
+
execute("DELETE FROM `#{table_name}` WHERE id > #{the_max}")
|
241
|
+
num_deleted = PseudoCleaner::Configuration.db_connection(:active_record).connection.raw_connection.affected_rows
|
242
|
+
|
243
|
+
if num_deleted > 0
|
244
|
+
cleaned_table = true
|
245
|
+
|
246
|
+
output_delete_record(test_strategy, " Deleted #{num_deleted} records by ID.")
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
if initial_state[:created]
|
251
|
+
PseudoCleaner::Configuration.db_connection(:active_record).connection.
|
252
|
+
execute("DELETE FROM `#{table_name}` WHERE #{initial_state[:created][:column_name]} > '#{initial_state[:created][:value]}'")
|
253
|
+
num_deleted = PseudoCleaner::Configuration.db_connection(:active_record).connection.raw_connection.affected_rows
|
254
|
+
|
255
|
+
if num_deleted > 0
|
256
|
+
cleaned_table = true
|
257
|
+
|
258
|
+
output_delete_record(test_strategy, " Deleted #{num_deleted} records by #{initial_state[:created][:column_name]}.")
|
259
|
+
end
|
260
|
+
end
|
261
|
+
|
262
|
+
if initial_state[:updated]
|
263
|
+
dirty_count = PseudoCleaner::Configuration.db_connection(:active_record).connection.
|
264
|
+
execute("SELECT COUNT(*) FROM `#{table_name}` WHERE #{initial_state[:updated][:column_name]} > '#{initial_state[:updated][:value]}'").first[0]
|
265
|
+
|
266
|
+
if @options[:output_diagnostics] && dirty_count > 0
|
267
|
+
# cleaned_table = true
|
268
|
+
|
269
|
+
initial_state[:updated][:value] = PseudoCleaner::Configuration.db_connection(:active_record).connection.
|
270
|
+
execute("SELECT MAX(#{initial_state[:updated][:column_name]}) FROM `#{table_name}`").first[0]
|
271
|
+
|
272
|
+
PseudoCleaner::Logger.write(" Resetting table \"#{initial_state[:table_name]}\"...") unless @options[:output_diagnostics]
|
273
|
+
output_delete_record(test_strategy, " *** There are #{dirty_count} records which have been updated and may be dirty remaining after cleaning \"#{initial_state[:table_name]}\"... ***".red.on_light_white)
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
final_count = PseudoCleaner::Configuration.db_connection(:active_record).connection.
|
278
|
+
execute("SELECT COUNT(*) FROM `#{table_name}`").first[0]
|
279
|
+
if initial_state[:count] == 0
|
280
|
+
if initial_state[:blank]
|
281
|
+
cleaned_table = true
|
282
|
+
|
283
|
+
DatabaseCleaner[:active_record, connection: PseudoCleaner::Configuration.db_connection(:active_record)].
|
284
|
+
clean_with(:truncation, only: [initial_state[:table_name]])
|
285
|
+
output_delete_record(test_strategy, " Deleted #{final_count} records by cleaning the table.") if final_count > 0
|
286
|
+
|
287
|
+
final_count = PseudoCleaner::Configuration.db_connection(:active_record).connection.
|
288
|
+
execute("SELECT COUNT(*) FROM `#{table_name}`").first[0]
|
289
|
+
end
|
290
|
+
end
|
291
|
+
|
292
|
+
if initial_state[:count] != final_count
|
293
|
+
PseudoCleaner::Logger.write(" Resetting table \"#{initial_state[:table_name]}\"...") unless @options[:output_diagnostics]
|
294
|
+
output_delete_record(test_strategy,
|
295
|
+
" *** There are #{final_count - initial_state[:count]} dirty records remaining after cleaning \"#{initial_state[:table_name]}\"... ***".red.on_light_white,
|
296
|
+
true)
|
297
|
+
|
298
|
+
initial_state[:count] = final_count
|
299
|
+
cleaned_table = true
|
300
|
+
end
|
301
|
+
|
302
|
+
if cleaned_table
|
303
|
+
reset_auto_increment true
|
304
|
+
end
|
305
|
+
end
|
306
|
+
|
307
|
+
def test_end_sequel_model test_strategy
|
308
|
+
initial_state = @@initial_states[@table]
|
309
|
+
access_table = sequel_model_table
|
310
|
+
cleaned_table = false
|
311
|
+
|
312
|
+
if access_table
|
313
|
+
if initial_state[:max_id]
|
314
|
+
the_max = initial_state[:max_id] || 0
|
315
|
+
num_deleted = access_table.unfiltered.where { id > the_max }.delete
|
316
|
+
if num_deleted > 0
|
317
|
+
cleaned_table = true
|
318
|
+
|
319
|
+
output_delete_record(test_strategy, " Deleted #{num_deleted} records by ID.")
|
320
|
+
end
|
321
|
+
end
|
322
|
+
|
323
|
+
if initial_state[:created]
|
324
|
+
num_deleted = access_table.
|
325
|
+
unfiltered.
|
326
|
+
where("`#{initial_state[:created][:column_name]}` > ?", initial_state[:created][:value]).
|
327
|
+
delete
|
328
|
+
if num_deleted > 0
|
329
|
+
cleaned_table = true
|
330
|
+
|
331
|
+
output_delete_record(test_strategy, " Deleted #{num_deleted} records by #{initial_state[:created][:column_name]}.")
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
if initial_state[:updated]
|
336
|
+
dirty_count = access_table.
|
337
|
+
unfiltered.
|
338
|
+
where("`#{initial_state[:updated][:column_name]}` > ?", initial_state[:updated][:value]).
|
339
|
+
count
|
340
|
+
|
341
|
+
if @options[:output_diagnostics] && dirty_count > 0
|
342
|
+
# cleaned_table = true
|
343
|
+
|
344
|
+
initial_state[:updated][:value] = access_table.unfiltered.max(initial_state[:updated][:column_name])
|
345
|
+
|
346
|
+
PseudoCleaner::Logger.write(" Resetting table \"#{initial_state[:table_name]}\"...") unless @options[:output_diagnostics]
|
347
|
+
output_delete_record(test_strategy, " *** There are #{dirty_count} records which have been updated and may be dirty remaining after cleaning \"#{initial_state[:table_name]}\"... ***".red.on_light_white)
|
348
|
+
end
|
349
|
+
end
|
350
|
+
|
351
|
+
final_count = access_table.unfiltered.count
|
352
|
+
if initial_state[:count] == 0
|
353
|
+
if initial_state[:blank]
|
354
|
+
cleaned_table = true
|
355
|
+
|
356
|
+
DatabaseCleaner[:sequel, connection: PseudoCleaner::Configuration.db_connection(:sequel)].
|
357
|
+
clean_with(:truncation, only: [initial_state[:table_name]])
|
358
|
+
output_delete_record(test_strategy, " Deleted #{final_count} records by cleaning the table.") if final_count > 0
|
359
|
+
|
360
|
+
final_count = access_table.unfiltered.count
|
361
|
+
end
|
362
|
+
end
|
363
|
+
|
364
|
+
if initial_state[:count] != final_count
|
365
|
+
PseudoCleaner::Logger.write(" Resetting table \"#{initial_state[:table_name]}\"...") unless @options[:output_diagnostics]
|
366
|
+
output_delete_record(test_strategy,
|
367
|
+
" *** There are #{final_count - initial_state[:count]} dirty records remaining after cleaning \"#{initial_state[:table_name]}\"... ***".red.on_light_white,
|
368
|
+
true)
|
369
|
+
|
370
|
+
initial_state[:count] = final_count
|
371
|
+
cleaned_table = true
|
372
|
+
end
|
373
|
+
|
374
|
+
if cleaned_table
|
375
|
+
reset_auto_increment true
|
376
|
+
end
|
377
|
+
end
|
378
|
+
end
|
379
|
+
|
380
|
+
def output_delete_record(test_strategy, stats_string, require_output = false)
|
381
|
+
if test_strategy == :transaction
|
382
|
+
PseudoCleaner::Logger.write(" ***** TRANSACTION FAILED!!! *****".red.on_light_white)
|
383
|
+
end
|
384
|
+
PseudoCleaner::Logger.write(stats_string) if @options[:output_diagnostics] || require_output
|
385
|
+
end
|
386
|
+
|
387
|
+
def reset_auto_increment test_start
|
388
|
+
initial_state = @@initial_states[@table]
|
389
|
+
|
390
|
+
if test_start
|
391
|
+
if initial_state[:table_is_active_record]
|
392
|
+
reset_auto_increment_active_record
|
393
|
+
end
|
394
|
+
|
395
|
+
if initial_state[:table_is_sequel_model]
|
396
|
+
reset_auto_increment_sequel_model
|
397
|
+
end
|
398
|
+
end
|
399
|
+
end
|
400
|
+
|
401
|
+
def reset_auto_increment_active_record
|
402
|
+
initial_state = @@initial_states[@table]
|
403
|
+
|
404
|
+
if initial_state[:max_id]
|
405
|
+
table_name = active_record_table
|
406
|
+
|
407
|
+
unless table_name.blank?
|
408
|
+
if @options[:output_diagnostics]
|
409
|
+
PseudoCleaner::Logger.write(" ALTER TABLE #{table_name} AUTO_INCREMENT = #{initial_state[:max_id] + 1}")
|
410
|
+
end
|
411
|
+
|
412
|
+
PseudoCleaner::Configuration.db_connection(:active_record).connection.
|
413
|
+
execute("ALTER TABLE #{table_name} AUTO_INCREMENT = #{initial_state[:max_id] + 1}")
|
414
|
+
end
|
415
|
+
end
|
416
|
+
end
|
417
|
+
|
418
|
+
def reset_auto_increment_sequel_model
|
419
|
+
initial_state = @@initial_states[@table]
|
420
|
+
|
421
|
+
if initial_state[:max_id]
|
422
|
+
table_name = sequel_model_table_name
|
423
|
+
|
424
|
+
unless table_name.blank?
|
425
|
+
if @options[:output_diagnostics]
|
426
|
+
PseudoCleaner::Logger.write(" ALTER TABLE #{table_name} AUTO_INCREMENT = #{initial_state[:max_id] + 1}")
|
427
|
+
end
|
428
|
+
|
429
|
+
PseudoCleaner::Configuration.db_connection(:sequel)["ALTER TABLE #{table_name} AUTO_INCREMENT = #{initial_state[:max_id] + 1}"].first
|
430
|
+
end
|
431
|
+
end
|
432
|
+
end
|
433
|
+
|
434
|
+
def <=>(other_object)
|
435
|
+
if (other_object.is_a?(PseudoCleaner::TableCleaner))
|
436
|
+
return 0 if other_object.table == self.table
|
437
|
+
|
438
|
+
SortedSeeder::Seeder.create_order.each do |create_table|
|
439
|
+
if create_table == self.table
|
440
|
+
return -1
|
441
|
+
elsif create_table == other_object.table
|
442
|
+
return 1
|
443
|
+
end
|
444
|
+
end
|
445
|
+
else
|
446
|
+
if other_object.respond_to?(:<=>)
|
447
|
+
comparison = (other_object <=> self)
|
448
|
+
if comparison
|
449
|
+
return -1 * comparison
|
450
|
+
end
|
451
|
+
end
|
452
|
+
end
|
453
|
+
|
454
|
+
return -1
|
455
|
+
end
|
456
|
+
|
457
|
+
def sequel_model_table
|
458
|
+
table_dataset = nil
|
459
|
+
|
460
|
+
if symbol_table?
|
461
|
+
table_dataset = PseudoCleaner::Configuration.db_connection(:sequel)[table]
|
462
|
+
else
|
463
|
+
if sequel_model_table_name
|
464
|
+
table_dataset = PseudoCleaner::Configuration.db_connection(:sequel)[sequel_model_table_name.gsub(/`([^`]+)`/, "\\1").to_sym]
|
465
|
+
end
|
466
|
+
unless table_dataset && table_dataset.is_a?(Sequel::Mysql2::Dataset)
|
467
|
+
table_dataset = table.dataset
|
468
|
+
end
|
469
|
+
end
|
470
|
+
unless table_dataset && table_dataset.is_a?(Sequel::Mysql2::Dataset)
|
471
|
+
table_dataset = nil
|
472
|
+
end
|
473
|
+
|
474
|
+
table_dataset
|
475
|
+
end
|
476
|
+
|
477
|
+
def sequel_model_table_name
|
478
|
+
if symbol_table?
|
479
|
+
"`#{table}`"
|
480
|
+
elsif table.simple_table
|
481
|
+
table.simple_table
|
482
|
+
elsif table.table_name
|
483
|
+
"`#{table.table_name}`"
|
484
|
+
else
|
485
|
+
nil
|
486
|
+
end
|
487
|
+
end
|
488
|
+
|
489
|
+
def review_rows(&block)
|
490
|
+
initial_state = @@initial_states[@table]
|
491
|
+
|
492
|
+
if initial_state[:table_is_active_record]
|
493
|
+
review_rows_active_record &block
|
494
|
+
end
|
495
|
+
|
496
|
+
if initial_state[:table_is_sequel_model]
|
497
|
+
review_rows_sequel_model &block
|
498
|
+
end
|
499
|
+
end
|
500
|
+
|
501
|
+
def review_rows_active_record(&block)
|
502
|
+
initial_state = @@initial_states[@table]
|
503
|
+
table_name = active_record_table
|
504
|
+
dataset_sequel = nil
|
505
|
+
|
506
|
+
if initial_state[:max_id]
|
507
|
+
the_max = initial_state[:max_id] || 0
|
508
|
+
|
509
|
+
dataset_sequel = "SELECT * FROM `#{table_name}` WHERE id > #{the_max}"
|
510
|
+
elsif initial_state[:created]
|
511
|
+
dataset_sequel = "SELECT * FROM `#{table_name}` WHERE #{initial_state[:created][:column_name]} > '#{initial_state[:created][:value]}'"
|
512
|
+
elsif initial_state[:updated]
|
513
|
+
dataset_sequel = "SELECT * FROM `#{table_name}` WHERE #{initial_state[:updated][:column_name]} > '#{initial_state[:updated][:value]}'"
|
514
|
+
elsif initial_state[:count]
|
515
|
+
dataset_sequel = "SELECT * FROM `#{table_name}` LIMIT 99 OFFSET #{initial_state[:count]}"
|
516
|
+
end
|
517
|
+
|
518
|
+
columns = GalaxyDbInjector::Base.connection.columns(table_name)
|
519
|
+
GalaxyDbInjector::Base.connection.execute(dataset_sequel).each do |row|
|
520
|
+
col_index = 0
|
521
|
+
data_hash = columns.reduce({}) do |hash, column_name|
|
522
|
+
hash[column_name.name] = row[col_index]
|
523
|
+
col_index += 1
|
524
|
+
|
525
|
+
hash
|
526
|
+
end
|
527
|
+
|
528
|
+
block.yield table_name, data_hash
|
529
|
+
end
|
530
|
+
end
|
531
|
+
|
532
|
+
def review_rows_sequel_model(&block)
|
533
|
+
initial_state = @@initial_states[@table]
|
534
|
+
dataset = nil
|
535
|
+
|
536
|
+
if initial_state[:max_id]
|
537
|
+
dataset = sequel_model_table.unfiltered.where { id > initial_state[:max_id] || 0 }
|
538
|
+
elsif initial_state[:created]
|
539
|
+
dataset = sequel_model_table.
|
540
|
+
unfiltered.
|
541
|
+
where("`#{initial_state[:created][:column_name]}` > ?", initial_state[:created][:value])
|
542
|
+
elsif initial_state[:updated]
|
543
|
+
dataset = sequel_model_table.
|
544
|
+
unfiltered.
|
545
|
+
where("`#{initial_state[:updated][:column_name]}` > ?", initial_state[:created][:value])
|
546
|
+
elsif initial_state[:count]
|
547
|
+
dataset = sequel_model_table.unfiltered.offset(initial_state[:count]).limit(99)
|
548
|
+
end
|
549
|
+
|
550
|
+
if dataset
|
551
|
+
dataset.each do |row|
|
552
|
+
block.yield sequel_model_table_name, row
|
553
|
+
end
|
554
|
+
end
|
555
|
+
end
|
556
|
+
end
|
557
|
+
end
|