nandi 0.8.0 → 0.11.1
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 +4 -4
- data/README.md +8 -9
- data/exe/nandi-enforce +1 -1
- data/lib/generators/nandi/foreign_key/foreign_key_generator.rb +3 -3
- data/lib/generators/nandi/foreign_key/templates/add_reference.rb +2 -2
- data/lib/nandi/formatting.rb +1 -1
- data/lib/nandi/instructions/add_index.rb +8 -3
- data/lib/nandi/instructions/add_reference.rb +2 -1
- data/lib/nandi/lockfile.rb +21 -1
- data/lib/nandi/migration.rb +2 -1
- data/lib/nandi/validation/add_reference_validator.rb +17 -5
- data/lib/nandi/version.rb +5 -0
- metadata +28 -20
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 6e1e64259650cb225c127f8a89c899464864a9d5ca76fb4abd58d48c6930e624
|
4
|
+
data.tar.gz: 41ef391e7da05c3997a13adf87ff5aa032fd6a46762d4cc7263c691d179ed237
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1672112e9464d5f8cefd75477cd7cdbae2d05822b0544d9f9240140b55121171e8f7e4183b09a5fcb2ab0d240e701aa891faebb5e99bafd5e4e764e2079e4f9d
|
7
|
+
data.tar.gz: 490135828100e636745efc67dfece39f04506ce18b135ab7487041b0929302b59973ae2848b7eef899dbd347050767c0f20fb3e1bdca73d0228d4e19c84e1279
|
data/README.md
CHANGED
@@ -4,7 +4,7 @@ Friendly Postgres migrations for people who don't want to take down their databa
|
|
4
4
|
|
5
5
|
## Supported
|
6
6
|
|
7
|
-
- Ruby 2.
|
7
|
+
- Ruby 2.5 or above
|
8
8
|
- Rails 5.2 or above
|
9
9
|
- Postgres 11 or above
|
10
10
|
|
@@ -161,11 +161,11 @@ We now have three new migration files:
|
|
161
161
|
|
162
162
|
class AddReferenceOnFoosToBars < Nandi::Migration
|
163
163
|
def up
|
164
|
-
|
164
|
+
add_column :foos, :bar_id, :bigint
|
165
165
|
end
|
166
166
|
|
167
167
|
def down
|
168
|
-
|
168
|
+
remove_column :foos, :bar_id
|
169
169
|
end
|
170
170
|
end
|
171
171
|
|
@@ -202,10 +202,10 @@ class AddReferenceOnFoosToBars < ActiveRecord::Migration[5.2]
|
|
202
202
|
set_statement_timeout(1_500)
|
203
203
|
|
204
204
|
def up
|
205
|
-
|
205
|
+
add_column(:foos, :bar_id, :bigint)
|
206
206
|
end
|
207
207
|
def down
|
208
|
-
|
208
|
+
remove_column(:foos, :bar_id)
|
209
209
|
end
|
210
210
|
end
|
211
211
|
|
@@ -268,10 +268,9 @@ Add a foreign key constraint. The generated SQL will include the NOT VALID param
|
|
268
268
|
### `#add_index(table, fields, **kwargs)`
|
269
269
|
Adds a new index to the database.
|
270
270
|
|
271
|
-
Nandi will
|
272
|
-
|
271
|
+
Nandi will
|
273
272
|
- add the `CONCURRENTLY` option, which means the change takes a less restrictive lock at the cost of not running in a DDL transaction
|
274
|
-
-
|
273
|
+
- default to the `BTREE` index type, as it is commonly a good fit.
|
275
274
|
|
276
275
|
Because index creation is particularly failure-prone, and because we cannot run in a transaction and therefore risk partially applied migrations that (in a Rails environment) require manual intervention, Nandi Validates that, if there is a add_index statement in the migration, it must be the only statement.
|
277
276
|
|
@@ -287,7 +286,7 @@ end
|
|
287
286
|
```
|
288
287
|
|
289
288
|
### `#add_reference(table, ref_name, **extra_args)`
|
290
|
-
Adds a new reference column. Nandi will validate that the foreign key flag is not set to true; use `add_foreign_key` and `validate_foreign_key` instead!
|
289
|
+
Adds a new reference column. Nandi will validate that the foreign key flag is not set to true; use `add_foreign_key` and `validate_foreign_key` instead! Nandi will also set the `index: false` flag, as index creation is unsafe unless done concurrently in a separate migration.
|
291
290
|
|
292
291
|
### `#remove_reference(table, ref_name, **extra_args)`
|
293
292
|
Removes a reference column.
|
data/exe/nandi-enforce
CHANGED
@@ -11,7 +11,7 @@ module Nandi
|
|
11
11
|
argument :target, type: :string
|
12
12
|
class_option :name, type: :string
|
13
13
|
class_option :column, type: :string
|
14
|
-
class_option :type, type: :string
|
14
|
+
class_option :type, type: :string, default: "bigint"
|
15
15
|
class_option :no_create_column, type: :boolean
|
16
16
|
class_option :validation_timeout, type: :numeric, default: 15 * 60 * 1000
|
17
17
|
|
@@ -61,11 +61,11 @@ module Nandi
|
|
61
61
|
private
|
62
62
|
|
63
63
|
def type
|
64
|
-
options["type"]
|
64
|
+
options["type"].to_sym
|
65
65
|
end
|
66
66
|
|
67
67
|
def reference_name
|
68
|
-
target.singularize.to_sym
|
68
|
+
"#{target.singularize}_id".to_sym
|
69
69
|
end
|
70
70
|
|
71
71
|
def base_path
|
@@ -2,10 +2,10 @@
|
|
2
2
|
|
3
3
|
class <%= add_reference_name.camelize %> < Nandi::Migration
|
4
4
|
def up
|
5
|
-
|
5
|
+
add_column <%= format_value(table) %>, <%= format_value(reference_name) %>, <%= format_value(type) %>
|
6
6
|
end
|
7
7
|
|
8
8
|
def down
|
9
|
-
|
9
|
+
remove_column <%= format_value(table) %>, <%= format_value(reference_name) %>
|
10
10
|
end
|
11
11
|
end
|
data/lib/nandi/formatting.rb
CHANGED
@@ -21,11 +21,10 @@ module Nandi
|
|
21
21
|
name: name,
|
22
22
|
|
23
23
|
# Overrides and extra options
|
24
|
-
|
24
|
+
**extra_args_with_default_index_type,
|
25
25
|
|
26
26
|
# Mandatory values
|
27
27
|
algorithm: :concurrently,
|
28
|
-
using: :btree,
|
29
28
|
}
|
30
29
|
end
|
31
30
|
|
@@ -38,13 +37,19 @@ module Nandi
|
|
38
37
|
private
|
39
38
|
|
40
39
|
def name
|
41
|
-
:"idx_#{table
|
40
|
+
:"idx_#{table}_on_#{field_names}"
|
42
41
|
end
|
43
42
|
|
44
43
|
def field_names
|
45
44
|
field_names = fields.respond_to?(:map) ? fields.map(&:to_s).join("_") : fields
|
46
45
|
field_names.to_s.scan(/\w+/).join("_")
|
47
46
|
end
|
47
|
+
|
48
|
+
def extra_args_with_default_index_type
|
49
|
+
{
|
50
|
+
using: :btree,
|
51
|
+
}.merge(@extra_args)
|
52
|
+
end
|
48
53
|
end
|
49
54
|
end
|
50
55
|
end
|
@@ -3,12 +3,13 @@
|
|
3
3
|
module Nandi
|
4
4
|
module Instructions
|
5
5
|
class AddReference
|
6
|
+
DEFAULT_EXTRA_ARGS = { index: false }.freeze
|
6
7
|
attr_reader :table, :ref_name, :extra_args
|
7
8
|
|
8
9
|
def initialize(table:, ref_name:, **kwargs)
|
9
10
|
@table = table
|
10
11
|
@ref_name = ref_name
|
11
|
-
@extra_args = kwargs
|
12
|
+
@extra_args = DEFAULT_EXTRA_ARGS.merge(kwargs)
|
12
13
|
end
|
13
14
|
|
14
15
|
def procedure
|
data/lib/nandi/lockfile.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require "active_support/core_ext/hash/indifferent_access"
|
4
|
+
require "digest"
|
4
5
|
|
5
6
|
module Nandi
|
6
7
|
class Lockfile
|
@@ -42,7 +43,26 @@ module Nandi
|
|
42
43
|
end
|
43
44
|
|
44
45
|
def persist!
|
45
|
-
|
46
|
+
# This is a somewhat ridiculous trick to avoid merge conflicts in git.
|
47
|
+
#
|
48
|
+
# Normally, new migrations are added to the bottom of the Nandi lockfile.
|
49
|
+
# This is relatively unfriendly to git's merge algorithm, and means that
|
50
|
+
# if someone merges a pull request with a completely unrelated migration,
|
51
|
+
# you'll have to rebase to get yours merged as the last line of the file
|
52
|
+
# will be seen as a conflict (both branches added content there).
|
53
|
+
#
|
54
|
+
# This is in contrast to something like Gemfile.lock, where changes tend
|
55
|
+
# to be distributed throughout the file. The idea behind sorting by
|
56
|
+
# SHA-256 hash is to distribute new Nandi lockfile entries evenly, but
|
57
|
+
# also stably through the file. It needs to be stable or we'd have even
|
58
|
+
# worse merge conflict problems (e.g. if we randomised the order on
|
59
|
+
# writing the file, the whole thing would conflict pretty much every time
|
60
|
+
# it was regenerated).
|
61
|
+
content = Hash[lockfile.to_h.deep_stringify_keys.sort_by do |k, _|
|
62
|
+
Digest::SHA256.hexdigest(k)
|
63
|
+
end].to_yaml
|
64
|
+
|
65
|
+
File.write(path, content)
|
46
66
|
end
|
47
67
|
|
48
68
|
def path
|
data/lib/nandi/migration.rb
CHANGED
@@ -43,6 +43,7 @@ module Nandi
|
|
43
43
|
|
44
44
|
class << self
|
45
45
|
attr_reader :lock_timeout, :statement_timeout
|
46
|
+
|
46
47
|
# For sake both of correspondence with Postgres syntax and familiarity
|
47
48
|
# with activerecord-safe_migrations's identically named macros, we
|
48
49
|
# disable this cop.
|
@@ -111,7 +112,7 @@ module Nandi
|
|
111
112
|
# Nandi will:
|
112
113
|
# * add the `CONCURRENTLY` option, which means the change takes a less
|
113
114
|
# restrictive lock at the cost of not running in a DDL transaction
|
114
|
-
# *
|
115
|
+
# * default to the `BTREE` index type, as it is commonly a good fit.
|
115
116
|
#
|
116
117
|
# Because index creation is particularly failure-prone, and because
|
117
118
|
# we cannot run in a transaction and therefore risk partially applied
|
@@ -16,16 +16,28 @@ module Nandi
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def call
|
19
|
-
foreign_key = instruction.extra_args.fetch(:foreign_key
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
19
|
+
foreign_key = instruction.extra_args.fetch(:foreign_key, false)
|
20
|
+
index = instruction.extra_args.fetch(:index, false)
|
21
|
+
|
22
|
+
collect_errors(
|
23
|
+
assert(
|
24
|
+
!foreign_key,
|
25
|
+
foreign_key_message,
|
26
|
+
),
|
27
|
+
assert(
|
28
|
+
!index,
|
29
|
+
index_message,
|
30
|
+
),
|
24
31
|
)
|
25
32
|
end
|
26
33
|
|
27
34
|
private
|
28
35
|
|
36
|
+
def index_message
|
37
|
+
"Indexing a reference column on creation can make the table unavailable." \
|
38
|
+
"Use the `add_index` method in a separate migration to index the column."
|
39
|
+
end
|
40
|
+
|
29
41
|
def foreign_key_message
|
30
42
|
"Adding a foreign key constraint must be done in two separate migrations. " \
|
31
43
|
"Use the `add_foreign_key` and `validate_foreign_key` methods, or the " \
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: nandi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.11.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
|
-
-
|
8
|
-
autorequire:
|
7
|
+
- GoCardless Engineering
|
8
|
+
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2021-08-09 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activesupport
|
@@ -100,28 +100,28 @@ dependencies:
|
|
100
100
|
requirements:
|
101
101
|
- - "~>"
|
102
102
|
- !ruby/object:Gem::Version
|
103
|
-
version: 2.
|
103
|
+
version: 2.15.0
|
104
104
|
type: :development
|
105
105
|
prerelease: false
|
106
106
|
version_requirements: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - "~>"
|
109
109
|
- !ruby/object:Gem::Version
|
110
|
-
version: 2.
|
110
|
+
version: 2.15.0
|
111
111
|
- !ruby/object:Gem::Dependency
|
112
112
|
name: pry-byebug
|
113
113
|
requirement: !ruby/object:Gem::Requirement
|
114
114
|
requirements:
|
115
115
|
- - "~>"
|
116
116
|
- !ruby/object:Gem::Version
|
117
|
-
version: 3.
|
117
|
+
version: 3.9.0
|
118
118
|
type: :development
|
119
119
|
prerelease: false
|
120
120
|
version_requirements: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - "~>"
|
123
123
|
- !ruby/object:Gem::Version
|
124
|
-
version: 3.
|
124
|
+
version: 3.9.0
|
125
125
|
- !ruby/object:Gem::Dependency
|
126
126
|
name: rails
|
127
127
|
requirement: !ruby/object:Gem::Requirement
|
@@ -140,16 +140,22 @@ dependencies:
|
|
140
140
|
name: rake
|
141
141
|
requirement: !ruby/object:Gem::Requirement
|
142
142
|
requirements:
|
143
|
+
- - ">="
|
144
|
+
- !ruby/object:Gem::Version
|
145
|
+
version: 12.3.3
|
143
146
|
- - "~>"
|
144
147
|
- !ruby/object:Gem::Version
|
145
|
-
version: '
|
148
|
+
version: '13.0'
|
146
149
|
type: :development
|
147
150
|
prerelease: false
|
148
151
|
version_requirements: !ruby/object:Gem::Requirement
|
149
152
|
requirements:
|
153
|
+
- - ">="
|
154
|
+
- !ruby/object:Gem::Version
|
155
|
+
version: 12.3.3
|
150
156
|
- - "~>"
|
151
157
|
- !ruby/object:Gem::Version
|
152
|
-
version: '
|
158
|
+
version: '13.0'
|
153
159
|
- !ruby/object:Gem::Dependency
|
154
160
|
name: rspec
|
155
161
|
requirement: !ruby/object:Gem::Requirement
|
@@ -184,14 +190,14 @@ dependencies:
|
|
184
190
|
requirements:
|
185
191
|
- - "~>"
|
186
192
|
- !ruby/object:Gem::Version
|
187
|
-
version: '0
|
193
|
+
version: '1.0'
|
188
194
|
type: :development
|
189
195
|
prerelease: false
|
190
196
|
version_requirements: !ruby/object:Gem::Requirement
|
191
197
|
requirements:
|
192
198
|
- - "~>"
|
193
199
|
- !ruby/object:Gem::Version
|
194
|
-
version: '0
|
200
|
+
version: '1.0'
|
195
201
|
- !ruby/object:Gem::Dependency
|
196
202
|
name: yard
|
197
203
|
requirement: !ruby/object:Gem::Requirement
|
@@ -206,9 +212,9 @@ dependencies:
|
|
206
212
|
- - "~>"
|
207
213
|
- !ruby/object:Gem::Version
|
208
214
|
version: '0.9'
|
209
|
-
description:
|
215
|
+
description:
|
210
216
|
email:
|
211
|
-
-
|
217
|
+
- engineering@gocardless.com
|
212
218
|
executables:
|
213
219
|
- nandi-enforce
|
214
220
|
extensions: []
|
@@ -276,6 +282,7 @@ files:
|
|
276
282
|
- lib/nandi/validation/result.rb
|
277
283
|
- lib/nandi/validation/timeout_validator.rb
|
278
284
|
- lib/nandi/validator.rb
|
285
|
+
- lib/nandi/version.rb
|
279
286
|
- lib/templates/nandi/renderers/active_record/generate/show.rb.erb
|
280
287
|
- lib/templates/nandi/renderers/active_record/instructions/add_check_constraint/show.rb.erb
|
281
288
|
- lib/templates/nandi/renderers/active_record/instructions/add_column/show.rb.erb
|
@@ -292,10 +299,11 @@ files:
|
|
292
299
|
- lib/templates/nandi/renderers/active_record/instructions/remove_not_null_constraint/show.rb.erb
|
293
300
|
- lib/templates/nandi/renderers/active_record/instructions/remove_reference/show.rb.erb
|
294
301
|
- lib/templates/nandi/renderers/active_record/instructions/validate_constraint/show.rb.erb
|
295
|
-
homepage:
|
296
|
-
licenses:
|
302
|
+
homepage: https://github.com/gocardless/nandi
|
303
|
+
licenses:
|
304
|
+
- MIT
|
297
305
|
metadata: {}
|
298
|
-
post_install_message:
|
306
|
+
post_install_message:
|
299
307
|
rdoc_options: []
|
300
308
|
require_paths:
|
301
309
|
- lib
|
@@ -303,15 +311,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
303
311
|
requirements:
|
304
312
|
- - ">="
|
305
313
|
- !ruby/object:Gem::Version
|
306
|
-
version:
|
314
|
+
version: 2.4.0
|
307
315
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
308
316
|
requirements:
|
309
317
|
- - ">="
|
310
318
|
- !ruby/object:Gem::Version
|
311
319
|
version: '0'
|
312
320
|
requirements: []
|
313
|
-
rubygems_version: 3.
|
314
|
-
signing_key:
|
321
|
+
rubygems_version: 3.2.3
|
322
|
+
signing_key:
|
315
323
|
specification_version: 4
|
316
324
|
summary: Fear-free migrations for PostgreSQL
|
317
325
|
test_files: []
|