bulk_dependency_eraser 1.0.5 → 1.2.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.
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
|
@@ -48,7 +51,8 @@ module BulkDependencyEraser
|
|
48
51
|
'ActiveRecord::Reflection::HasAndBelongsToManyReflection'
|
49
52
|
].freeze
|
50
53
|
|
51
|
-
|
54
|
+
# write access so that these can be edited in-place by end-users who might need to manually adjust deletion order.
|
55
|
+
attr_accessor :deletion_list, :nullification_list
|
52
56
|
attr_reader :ignore_table_deletion_list, :ignore_table_nullification_list
|
53
57
|
|
54
58
|
def initialize query:, opts: {}
|
@@ -119,6 +123,10 @@ module BulkDependencyEraser
|
|
119
123
|
attr_reader :table_names_to_parsed_klass_names
|
120
124
|
attr_reader :ignore_table_name_and_dependencies, :ignore_klass_name_and_dependencies
|
121
125
|
|
126
|
+
def batch_size
|
127
|
+
opts_c.read_batch_size || opts_c.batch_size
|
128
|
+
end
|
129
|
+
|
122
130
|
def deletion_query_parser query, association_parent = nil
|
123
131
|
# necessary for "ActiveRecord::Reflection::ThroughReflection" use-case
|
124
132
|
# force_through_destroy_chains = options[:force_destroy_chain] || {}
|
@@ -164,9 +172,12 @@ module BulkDependencyEraser
|
|
164
172
|
return
|
165
173
|
end
|
166
174
|
|
167
|
-
# Pluck IDs of the current query
|
168
|
-
query_ids =
|
169
|
-
|
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
|
170
181
|
end
|
171
182
|
|
172
183
|
deletion_list[klass_name] ||= []
|
@@ -339,8 +350,11 @@ module BulkDependencyEraser
|
|
339
350
|
# - handle primary key edge cases
|
340
351
|
# - The associations might not be using the primary_key of the klass table, but we can support that here.
|
341
352
|
if specified_primary_key && specified_primary_key&.to_s != 'id'
|
342
|
-
alt_primary_ids =
|
343
|
-
|
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
|
344
358
|
end
|
345
359
|
assoc_query = assoc_query.where(specified_foreign_key.to_sym => alt_primary_ids)
|
346
360
|
else
|
@@ -363,8 +377,11 @@ module BulkDependencyEraser
|
|
363
377
|
elsif type == :nullify
|
364
378
|
# No need for recursion here.
|
365
379
|
# - we're not destroying these assocs (just nullifying foreign_key columns) so we don't need to parse their dependencies.
|
366
|
-
assoc_ids =
|
367
|
-
|
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
|
368
385
|
end
|
369
386
|
|
370
387
|
# No assoc_ids, no need to add it to the nullification list
|
@@ -408,7 +425,7 @@ module BulkDependencyEraser
|
|
408
425
|
# assoc_query = assoc_klass.unscoped
|
409
426
|
# query.in_batches
|
410
427
|
|
411
|
-
assoc_klass.in_batches(of:
|
428
|
+
assoc_klass.in_batches(of: batch_size) do |batch|
|
412
429
|
batch.each do |record|
|
413
430
|
record.send(association_name)
|
414
431
|
end
|
@@ -471,21 +488,23 @@ module BulkDependencyEraser
|
|
471
488
|
return
|
472
489
|
end
|
473
490
|
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
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
|
479
497
|
|
480
|
-
|
481
|
-
|
482
|
-
|
483
|
-
|
484
|
-
|
485
|
-
|
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}"
|
486
507
|
end
|
487
|
-
else
|
488
|
-
raise "invalid parsing type: #{type}"
|
489
508
|
end
|
490
509
|
end
|
491
510
|
|
@@ -537,28 +556,30 @@ module BulkDependencyEraser
|
|
537
556
|
return
|
538
557
|
end
|
539
558
|
|
540
|
-
|
541
|
-
|
542
|
-
|
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
|
543
564
|
end
|
544
|
-
end
|
545
565
|
|
546
|
-
|
547
|
-
# Recursively call 'deletion_query_parser' on association query, to delete any if the assoc's dependencies
|
548
|
-
foreign_ids_by_type.each do |type, ids|
|
549
|
-
assoc_klass = type.constantize
|
550
|
-
deletion_query_parser(assoc_klass.where(id: ids), assoc_klass)
|
551
|
-
end
|
552
|
-
elsif type == :restricted
|
553
|
-
if traverse_restricted_dependency_for_belongs_to_poly?(parent_class, reflection, foreign_ids_by_type)
|
566
|
+
if type == :delete
|
554
567
|
# Recursively call 'deletion_query_parser' on association query, to delete any if the assoc's dependencies
|
555
568
|
foreign_ids_by_type.each do |type, ids|
|
556
569
|
assoc_klass = type.constantize
|
557
570
|
deletion_query_parser(assoc_klass.where(id: ids), assoc_klass)
|
558
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}"
|
559
582
|
end
|
560
|
-
else
|
561
|
-
raise "invalid parsing type: #{type}"
|
562
583
|
end
|
563
584
|
end
|
564
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
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bulk_dependency_eraser
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- benjamin.dana.software.dev@gmail.com
|
@@ -148,6 +148,7 @@ files:
|
|
148
148
|
- lib/bulk_dependency_eraser/deleter.rb
|
149
149
|
- lib/bulk_dependency_eraser/manager.rb
|
150
150
|
- lib/bulk_dependency_eraser/nullifier.rb
|
151
|
+
- lib/bulk_dependency_eraser/version.rb
|
151
152
|
homepage: https://github.com/danabr75/bulk_dependency_eraser
|
152
153
|
licenses:
|
153
154
|
- LGPL-3.0-only
|