bulk_dependency_eraser 1.1.0 → 1.2.0
Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 31e61c4af0756f5f3cb2f75ee9d3247e238fd83386fd8bdeace5bd60ebf17655
|
4
|
+
data.tar.gz: c3edbcc3cdfa4d56d398616780ba81ae254cf9224f9371fa60dbfbbc25b2b343
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: '09c8931ca0720cf4a40639df42d1376745d32915167f2b78e43400280761249458e582bb872b8a4b5106d6c580ad82c88a26f2270a0227e457d045fe9490d388'
|
7
|
+
data.tar.gz: fa6224f8af00e73b0114666728547c4e64fdd2976c4026411d621ef411ffbc1bf484275e93076f8942d1ae99834600da794efa9590eab4827e1c55bcd1978912
|
@@ -13,7 +13,10 @@ module BulkDependencyEraser
|
|
13
13
|
# Won't parse any table in this list
|
14
14
|
ignore_tables_and_dependencies: [],
|
15
15
|
ignore_klass_names_and_dependencies: [],
|
16
|
-
|
16
|
+
# a general batching size
|
17
|
+
batch_size: 10_000,
|
18
|
+
# A specific batching size for this class, overrides the batch_size
|
19
|
+
read_batch_size: nil,
|
17
20
|
}.freeze
|
18
21
|
|
19
22
|
DEFAULT_DB_WRAPPER = ->(block) do
|
@@ -120,6 +123,10 @@ module BulkDependencyEraser
|
|
120
123
|
attr_reader :table_names_to_parsed_klass_names
|
121
124
|
attr_reader :ignore_table_name_and_dependencies, :ignore_klass_name_and_dependencies
|
122
125
|
|
126
|
+
def batch_size
|
127
|
+
opts_c.read_batch_size || opts_c.batch_size
|
128
|
+
end
|
129
|
+
|
123
130
|
def deletion_query_parser query, association_parent = nil
|
124
131
|
# necessary for "ActiveRecord::Reflection::ThroughReflection" use-case
|
125
132
|
# force_through_destroy_chains = options[:force_destroy_chain] || {}
|
@@ -165,9 +172,12 @@ module BulkDependencyEraser
|
|
165
172
|
return
|
166
173
|
end
|
167
174
|
|
168
|
-
# Pluck IDs of the current query
|
169
|
-
query_ids =
|
170
|
-
|
175
|
+
# Pluck IDs of the current query (batchified)
|
176
|
+
query_ids = []
|
177
|
+
query.in_batches(of: batch_size) do |batch|
|
178
|
+
read_from_db do
|
179
|
+
query_ids += batch.pluck(:id)
|
180
|
+
end
|
171
181
|
end
|
172
182
|
|
173
183
|
deletion_list[klass_name] ||= []
|
@@ -340,8 +350,11 @@ module BulkDependencyEraser
|
|
340
350
|
# - handle primary key edge cases
|
341
351
|
# - The associations might not be using the primary_key of the klass table, but we can support that here.
|
342
352
|
if specified_primary_key && specified_primary_key&.to_s != 'id'
|
343
|
-
alt_primary_ids =
|
344
|
-
|
353
|
+
alt_primary_ids = []
|
354
|
+
query.in_batches(of: batch_size) do |batch|
|
355
|
+
read_from_db do
|
356
|
+
alt_primary_ids += query.pluck(specified_primary_key)
|
357
|
+
end
|
345
358
|
end
|
346
359
|
assoc_query = assoc_query.where(specified_foreign_key.to_sym => alt_primary_ids)
|
347
360
|
else
|
@@ -364,8 +377,11 @@ module BulkDependencyEraser
|
|
364
377
|
elsif type == :nullify
|
365
378
|
# No need for recursion here.
|
366
379
|
# - we're not destroying these assocs (just nullifying foreign_key columns) so we don't need to parse their dependencies.
|
367
|
-
assoc_ids =
|
368
|
-
|
380
|
+
assoc_ids = []
|
381
|
+
assoc_query.in_batches(of: batch_size) do |batch|
|
382
|
+
read_from_db do
|
383
|
+
assoc_ids += batch.pluck(:id)
|
384
|
+
end
|
369
385
|
end
|
370
386
|
|
371
387
|
# No assoc_ids, no need to add it to the nullification list
|
@@ -409,7 +425,7 @@ module BulkDependencyEraser
|
|
409
425
|
# assoc_query = assoc_klass.unscoped
|
410
426
|
# query.in_batches
|
411
427
|
|
412
|
-
assoc_klass.in_batches(of:
|
428
|
+
assoc_klass.in_batches(of: batch_size) do |batch|
|
413
429
|
batch.each do |record|
|
414
430
|
record.send(association_name)
|
415
431
|
end
|
@@ -472,21 +488,23 @@ module BulkDependencyEraser
|
|
472
488
|
return
|
473
489
|
end
|
474
490
|
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
491
|
+
query.in_batches(of: batch_size) do |batch|
|
492
|
+
assoc_batch_query = read_from_db do
|
493
|
+
assoc_query.where(
|
494
|
+
specified_primary_key.to_sym => batch.pluck(specified_foreign_key)
|
495
|
+
)
|
496
|
+
end
|
480
497
|
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
498
|
+
if type == :delete
|
499
|
+
# Recursively call 'deletion_query_parser' on association query, to delete any if the assoc's dependencies
|
500
|
+
deletion_query_parser(assoc_batch_query, parent_class)
|
501
|
+
elsif type == :restricted
|
502
|
+
if traverse_restricted_dependency?(parent_class, reflection, assoc_batch_query)
|
503
|
+
deletion_query_parser(assoc_batch_query, parent_class)
|
504
|
+
end
|
505
|
+
else
|
506
|
+
raise "invalid parsing type: #{type}"
|
487
507
|
end
|
488
|
-
else
|
489
|
-
raise "invalid parsing type: #{type}"
|
490
508
|
end
|
491
509
|
end
|
492
510
|
|
@@ -538,28 +556,30 @@ module BulkDependencyEraser
|
|
538
556
|
return
|
539
557
|
end
|
540
558
|
|
541
|
-
|
542
|
-
|
543
|
-
|
559
|
+
query.in_batches(of: batch_size) do |batch|
|
560
|
+
foreign_ids_by_type = read_from_db do
|
561
|
+
batch.pluck(specified_foreign_key, specified_foreign_type).each_with_object({}) do |(id, type), hash|
|
562
|
+
hash.key?(type) ? hash[type] << id : hash[type] = [id]
|
563
|
+
end
|
544
564
|
end
|
545
|
-
end
|
546
565
|
|
547
|
-
|
548
|
-
# Recursively call 'deletion_query_parser' on association query, to delete any if the assoc's dependencies
|
549
|
-
foreign_ids_by_type.each do |type, ids|
|
550
|
-
assoc_klass = type.constantize
|
551
|
-
deletion_query_parser(assoc_klass.where(id: ids), assoc_klass)
|
552
|
-
end
|
553
|
-
elsif type == :restricted
|
554
|
-
if traverse_restricted_dependency_for_belongs_to_poly?(parent_class, reflection, foreign_ids_by_type)
|
566
|
+
if type == :delete
|
555
567
|
# Recursively call 'deletion_query_parser' on association query, to delete any if the assoc's dependencies
|
556
568
|
foreign_ids_by_type.each do |type, ids|
|
557
569
|
assoc_klass = type.constantize
|
558
570
|
deletion_query_parser(assoc_klass.where(id: ids), assoc_klass)
|
559
571
|
end
|
572
|
+
elsif type == :restricted
|
573
|
+
if traverse_restricted_dependency_for_belongs_to_poly?(parent_class, reflection, foreign_ids_by_type)
|
574
|
+
# Recursively call 'deletion_query_parser' on association query, to delete any if the assoc's dependencies
|
575
|
+
foreign_ids_by_type.each do |type, ids|
|
576
|
+
assoc_klass = type.constantize
|
577
|
+
deletion_query_parser(assoc_klass.where(id: ids), assoc_klass)
|
578
|
+
end
|
579
|
+
end
|
580
|
+
else
|
581
|
+
raise "invalid parsing type: #{type}"
|
560
582
|
end
|
561
|
-
else
|
562
|
-
raise "invalid parsing type: #{type}"
|
563
583
|
end
|
564
584
|
end
|
565
585
|
|
@@ -4,7 +4,11 @@ module BulkDependencyEraser
|
|
4
4
|
verbose: false,
|
5
5
|
db_delete_wrapper: self::DEFAULT_DB_WRAPPER,
|
6
6
|
# Set to true if you want 'ActiveRecord::InvalidForeignKey' errors raised during deletions
|
7
|
-
enable_invalid_foreign_key_detection: false
|
7
|
+
enable_invalid_foreign_key_detection: false,
|
8
|
+
# a general batching size
|
9
|
+
batch_size: 300,
|
10
|
+
# A specific batching size for this class, overrides the batch_size
|
11
|
+
delete_batch_size: nil,
|
8
12
|
}.freeze
|
9
13
|
|
10
14
|
DEFAULT_DB_WRAPPER = ->(block) do
|
@@ -55,15 +59,21 @@ module BulkDependencyEraser
|
|
55
59
|
|
56
60
|
protected
|
57
61
|
|
62
|
+
attr_reader :class_names_and_ids
|
63
|
+
|
64
|
+
def batch_size
|
65
|
+
opts_c.delete_batch_size || opts_c.batch_size
|
66
|
+
end
|
67
|
+
|
58
68
|
def delete_by_klass_and_ids klass, ids
|
59
69
|
puts "Deleting #{klass.name}'s IDs: #{ids}" if opts_c.verbose
|
60
|
-
|
61
|
-
|
70
|
+
ids.each_slice(batch_size) do |ids_subset|
|
71
|
+
delete_in_db do
|
72
|
+
klass.unscoped.where(id: ids_subset).delete_all
|
73
|
+
end
|
62
74
|
end
|
63
75
|
end
|
64
76
|
|
65
|
-
attr_reader :class_names_and_ids
|
66
|
-
|
67
77
|
def delete_in_db(&block)
|
68
78
|
puts "Deleting from DB..." if opts_c.verbose
|
69
79
|
opts_c.db_delete_wrapper.call(block)
|
@@ -6,7 +6,11 @@ module BulkDependencyEraser
|
|
6
6
|
# Set to true if you want 'ActiveRecord::InvalidForeignKey' errors raised during nullifications
|
7
7
|
# - I can't think of a use-case where a nullification would generate an invalid key error
|
8
8
|
# - Not hurting anything to leave it in, but might remove it in the future.
|
9
|
-
enable_invalid_foreign_key_detection: false
|
9
|
+
enable_invalid_foreign_key_detection: false,
|
10
|
+
# a general batching size
|
11
|
+
batch_size: 300,
|
12
|
+
# A specific batching size for this class, overrides the batch_size
|
13
|
+
nullify_batch_size: nil,
|
10
14
|
}.freeze
|
11
15
|
|
12
16
|
DEFAULT_DB_WRAPPER = ->(block) do
|
@@ -115,6 +119,10 @@ module BulkDependencyEraser
|
|
115
119
|
|
116
120
|
attr_reader :class_names_columns_and_ids
|
117
121
|
|
122
|
+
def batch_size
|
123
|
+
opts_c.nullify_batch_size || opts_c.batch_size
|
124
|
+
end
|
125
|
+
|
118
126
|
def nullify_by_klass_column_and_ids klass, columns, ids
|
119
127
|
nullify_columns = {}
|
120
128
|
|
@@ -127,8 +135,10 @@ module BulkDependencyEraser
|
|
127
135
|
nullify_columns[columns] = nil
|
128
136
|
end
|
129
137
|
|
130
|
-
|
131
|
-
|
138
|
+
ids.each_slice(batch_size) do |ids_subset|
|
139
|
+
nullify_in_db do
|
140
|
+
klass.unscoped.where(id: ids_subset).update_all(nullify_columns)
|
141
|
+
end
|
132
142
|
end
|
133
143
|
end
|
134
144
|
|