pg_ha_migrations 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 +4 -4
- data/.gitignore +1 -0
- data/.travis.yml +5 -0
- data/Appraisals +12 -0
- data/README.md +37 -0
- data/Rakefile +5 -0
- data/gemfiles/.bundle/config +2 -0
- data/gemfiles/rails_5.0.gemfile +7 -0
- data/gemfiles/rails_5.1.gemfile +7 -0
- data/gemfiles/rails_5.2.gemfile +7 -0
- data/lib/pg_ha_migrations/blocking_database_transactions.rb +32 -16
- data/lib/pg_ha_migrations/hacks/cleanup_unnecessary_output.rb +29 -0
- data/lib/pg_ha_migrations/safe_statements.rb +113 -4
- data/lib/pg_ha_migrations/unsafe_statements.rb +2 -0
- data/lib/pg_ha_migrations/version.rb +1 -1
- data/lib/pg_ha_migrations.rb +5 -0
- data/pg_ha_migrations.gemspec +3 -3
- metadata +23 -17
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 36546429641ce670fa116d251f17993538b3ab60b5014c1917103e45b1fa0f45
|
4
|
+
data.tar.gz: 969078be676bc767aa8f325328da8aeda95b6120e620c5d8556bda639c94a3f4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d2ee13eed929c6278cf745b6b4e4ecff210858e930f97be67d0db2ff4bd2efc65288cc2c80090343cb6cc3e2097c8e1fcf62955fddf442eced723660793706df
|
7
|
+
data.tar.gz: d1f0853d0d47774e889835716f6619097f3e56016e8997a7115e31c34e87dfc80b0871eee128161f4583247265afbfd9aeae752312dad4bb11a5dd5bf0946184
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
@@ -9,3 +9,8 @@ addons:
|
|
9
9
|
before_install:
|
10
10
|
- gem uninstall -v '>= 2' -i $(rvm gemdir)@global -ax bundler || true
|
11
11
|
- gem install bundler -v 1.15.4
|
12
|
+
gemfile:
|
13
|
+
- gemfiles/rails_5.0.gemfile
|
14
|
+
- gemfiles/rails_5.1.gemfile
|
15
|
+
- gemfiles/rails_5.2.gemfile
|
16
|
+
script: "bundle exec rake spec"
|
data/Appraisals
ADDED
data/README.md
CHANGED
@@ -127,7 +127,13 @@ unsafe_add_column :table, :column, :type
|
|
127
127
|
Safely change the default value for a column.
|
128
128
|
|
129
129
|
```ruby
|
130
|
+
# Constant value:
|
130
131
|
safe_change_column_default :table, :column, "value"
|
132
|
+
safe_change_column_default :table, :column, DateTime.new(...)
|
133
|
+
# Functional expression evaluated at row insert time:
|
134
|
+
safe_change_column_default :table, :column, -> { "NOW()" }
|
135
|
+
# Functional expression evaluated at migration time:
|
136
|
+
safe_change_column_default :table, :column, -> { "'NOW()'" }
|
131
137
|
```
|
132
138
|
|
133
139
|
#### safe\_make\_column\_nullable
|
@@ -168,6 +174,37 @@ Safely remove an index. Migrations that contain this statement must also include
|
|
168
174
|
safe_remove_concurrent_index :table, :name => :index_name
|
169
175
|
```
|
170
176
|
|
177
|
+
#### safe\_add\_unvalidated\_check\_constraint
|
178
|
+
|
179
|
+
Safely add a `CHECK` constraint. The constraint will not be immediately validated on existing rows to avoid a full table scan while holding an exclusive lock. After adding the constraint, you'll need to use `safe_validate_check_constraint` to validate existing rows.
|
180
|
+
|
181
|
+
```ruby
|
182
|
+
safe_add_unvalidated_check_constraint :table, "column LIKE 'example%'", name: :constraint_table_on_column_like_example
|
183
|
+
```
|
184
|
+
|
185
|
+
#### safe\_validate\_check\_constraint
|
186
|
+
|
187
|
+
Safely validate (without acquiring an exclusive lock) existing rows for a newly added but as-yet unvalidated `CHECK` constraint.
|
188
|
+
|
189
|
+
```ruby
|
190
|
+
safe_validate_check_constraint :table, name: :constraint_table_on_column_like_example
|
191
|
+
```
|
192
|
+
|
193
|
+
#### safe\_rename\_constraint
|
194
|
+
|
195
|
+
Safely rename any (not just `CHECK`) constraint.
|
196
|
+
|
197
|
+
```ruby
|
198
|
+
safe_rename_constraint :table, from: :constraint_table_on_column_like_typo, to: :constraint_table_on_column_like_example
|
199
|
+
```
|
200
|
+
|
201
|
+
#### unsafe\_remove\_constraint
|
202
|
+
|
203
|
+
Drop any (not just `CHECK`) constraint.
|
204
|
+
|
205
|
+
```ruby
|
206
|
+
unsafe_remove_constraint :table, name: :constraint_table_on_column_like_example
|
207
|
+
```
|
171
208
|
|
172
209
|
### Utilities
|
173
210
|
|
data/Rakefile
CHANGED
@@ -1,8 +1,13 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
2
|
require "rspec/core/rake_task"
|
3
|
+
require "appraisal"
|
3
4
|
require_relative File.join("lib", "pg_ha_migrations")
|
4
5
|
|
5
6
|
RSpec::Core::RakeTask.new(:spec)
|
6
7
|
|
8
|
+
if !ENV["APPRAISAL_INITIALIZED"] && !ENV["TRAVIS"]
|
9
|
+
task :default => :appraisal
|
10
|
+
end
|
11
|
+
|
7
12
|
task :default => :spec
|
8
13
|
|
@@ -1,13 +1,23 @@
|
|
1
1
|
module PgHaMigrations
|
2
2
|
class BlockingDatabaseTransactions
|
3
|
-
LongRunningTransaction = Struct.new(:database, :current_query, :transaction_age, :tables_with_locks) do
|
3
|
+
LongRunningTransaction = Struct.new(:database, :current_query, :state, :transaction_age, :tables_with_locks) do
|
4
4
|
def description
|
5
|
-
|
5
|
+
locked_tables = tables_with_locks.compact
|
6
|
+
[
|
7
|
+
database,
|
8
|
+
locked_tables.size > 0 ? "tables (#{locked_tables.join(', ')})" : nil,
|
9
|
+
"#{idle? ? "currently idle " : ""}transaction open for #{transaction_age}",
|
10
|
+
"#{idle? ? "last " : ""}query: #{current_query}"
|
11
|
+
].compact.join(" | ")
|
6
12
|
end
|
7
13
|
|
8
14
|
def concurrent_index_creation?
|
9
15
|
!!current_query.match(/create\s+index\s+concurrently/i)
|
10
16
|
end
|
17
|
+
|
18
|
+
def idle?
|
19
|
+
state == "idle in transaction"
|
20
|
+
end
|
11
21
|
end
|
12
22
|
|
13
23
|
def self.autovacuum_regex
|
@@ -15,7 +25,7 @@ module PgHaMigrations
|
|
15
25
|
end
|
16
26
|
|
17
27
|
def self.find_blocking_transactions(minimum_transaction_age = "0 seconds")
|
18
|
-
pid_column,
|
28
|
+
pid_column, query_column = if ActiveRecord::Base.connection.select_value("SHOW server_version") =~ /9\.1/
|
19
29
|
["procpid", "current_query"]
|
20
30
|
else
|
21
31
|
["pid", "query"]
|
@@ -24,26 +34,32 @@ module PgHaMigrations
|
|
24
34
|
raw_query = <<-SQL
|
25
35
|
SELECT
|
26
36
|
psa.datname as database, -- Will only ever be one database
|
27
|
-
psa.#{
|
37
|
+
psa.#{query_column} as current_query,
|
38
|
+
psa.state,
|
28
39
|
clock_timestamp() - psa.xact_start AS transaction_age,
|
29
40
|
array_agg(distinct c.relname) AS tables_with_locks
|
30
41
|
FROM pg_stat_activity psa -- Cluster wide
|
31
|
-
JOIN pg_locks l ON (psa.#{pid_column} = l.pid) -- Cluster wide
|
32
|
-
JOIN pg_class c ON (
|
33
|
-
|
34
|
-
|
35
|
-
AND ns.nspname != 'pg_catalog'
|
36
|
-
AND c.relkind = 'r'
|
37
|
-
AND psa.xact_start < clock_timestamp() - ?::interval
|
38
|
-
AND psa.#{state_column} !~ ?
|
39
|
-
AND (
|
42
|
+
LEFT JOIN pg_locks l ON (psa.#{pid_column} = l.pid) -- Cluster wide
|
43
|
+
LEFT JOIN pg_class c ON ( -- Database wide
|
44
|
+
l.locktype = 'relation'
|
45
|
+
AND l.relation = c.oid
|
40
46
|
-- Be explicit about this being for a single database -- it's already implicit in
|
41
47
|
-- the relations used, and if we don't restrict this we could get incorrect results
|
42
48
|
-- with oid collisions from pg_namespace and pg_class.
|
43
|
-
l.database =
|
44
|
-
OR l.database = (SELECT d.oid FROM pg_database d WHERE d.datname = current_database())
|
49
|
+
AND l.database = (SELECT d.oid FROM pg_database d WHERE d.datname = current_database())
|
45
50
|
)
|
46
|
-
|
51
|
+
LEFT JOIN pg_namespace ns ON (c.relnamespace = ns.oid) -- Database wide
|
52
|
+
WHERE psa.#{pid_column} != pg_backend_pid()
|
53
|
+
AND (
|
54
|
+
l.locktype != 'relation'
|
55
|
+
OR (
|
56
|
+
ns.nspname != 'pg_catalog'
|
57
|
+
AND c.relkind = 'r'
|
58
|
+
)
|
59
|
+
)
|
60
|
+
AND psa.xact_start < clock_timestamp() - ?::interval
|
61
|
+
AND psa.#{query_column} !~ ?
|
62
|
+
GROUP BY psa.datname, psa.#{query_column}, psa.state, psa.xact_start
|
47
63
|
SQL
|
48
64
|
|
49
65
|
query = ActiveRecord::Base.send(:sanitize_sql_for_conditions, [raw_query, minimum_transaction_age, autovacuum_regex])
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "active_record/migration/compatibility"
|
2
|
+
|
3
|
+
module PgHaMigrations
|
4
|
+
module ActiveRecordHacks
|
5
|
+
module CleanupUnnecessaryOutput
|
6
|
+
# This is fixed in Rails 6+, but previously there were several
|
7
|
+
# places where #adapter_name was called directly which implicitly
|
8
|
+
# delegated to the connection through #method_missing. That
|
9
|
+
# delegation though results in wrapping the call in #say_with_time
|
10
|
+
# which unnecessarily outputs a bunch of calls to #adapter_name.
|
11
|
+
# The easiest way to clean this up retroactively is to just patch
|
12
|
+
# in a direct dispatch to the connection's method.
|
13
|
+
#
|
14
|
+
# See: https://github.com/rails/rails/commit/eb7c71bcd3d0c7e079dffdb11e43fb466eec06aa
|
15
|
+
def adapter_name
|
16
|
+
connection.adapter_name
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
patchable_module = [
|
23
|
+
defined?(ActiveRecord::Migration::Compatibility::V5_2) ? ActiveRecord::Migration::Compatibility::V5_2 : nil,
|
24
|
+
defined?(ActiveRecord::Migration::Compatibility::V5_1) ? ActiveRecord::Migration::Compatibility::V5_1 : nil,
|
25
|
+
defined?(ActiveRecord::Migration::Compatibility::V5_0) ? ActiveRecord::Migration::Compatibility::V5_0 : nil,
|
26
|
+
].detect { |m| m }
|
27
|
+
if patchable_module
|
28
|
+
patchable_module.prepend(PgHaMigrations::ActiveRecordHacks::CleanupUnnecessaryOutput)
|
29
|
+
end
|
@@ -45,10 +45,51 @@ module PgHaMigrations::SafeStatements
|
|
45
45
|
def safe_change_column_default(table_name, column_name, default_value)
|
46
46
|
column = connection.send(:column_for, table_name, column_name)
|
47
47
|
|
48
|
+
# In 5.2 we have an edge whereby passing in a string literal with an expression
|
49
|
+
# results in confusing behavior because instead of being executed in the database
|
50
|
+
# that expression is turned into a Ruby nil before being sent to the database layer;
|
51
|
+
# this seems to be an expected side effect of a change that was targeted at a use
|
52
|
+
# case unrelated to migrations: https://github.com/rails/rails/commit/7b2dfdeab6e4ef096e4dc1fe313056f08ccf7dc5
|
53
|
+
#
|
54
|
+
# On the other hand, the behavior in 5.1 is also confusing because it quotes the
|
55
|
+
# expression (instead of maintaining the string as-is), which results in Postgres
|
56
|
+
# evaluating the expression once when executing the DDL and setting the default to
|
57
|
+
# the constant result of that evaluation rather than setting the default to the
|
58
|
+
# expression itself.
|
59
|
+
#
|
60
|
+
# Therefore we want to disallow passing in an expression directly as a string and
|
61
|
+
# require the use of a Proc instead with specific quoting rules to determine exact
|
62
|
+
# behavior. It's fairly difficult (without relying on something like the PgQuery gem
|
63
|
+
# which requires native extensions built with the Postgres dev packages installed)
|
64
|
+
# to determine if a string literal represent an expression or just a constant. So
|
65
|
+
# instead of trying to parse the expression, we employ a set of heuristics:
|
66
|
+
# - If the column is text-like or binary, then we can allow anything in the default
|
67
|
+
# value since a Ruby string there will always coerce directly to the equivalent
|
68
|
+
# text/binary value rather than being interpreted as a DDL-time expression.
|
69
|
+
# - Otherwise, disallow any Ruby string values and instead require the Ruby object
|
70
|
+
# type that maps to the column type.
|
71
|
+
#
|
72
|
+
# These heuristics eliminate (virtually?) all ambiguity. In theory there's a
|
73
|
+
# possiblity that some custom object could be coerced-Ruby side into a SQL string
|
74
|
+
# that does something weird here, but that seems an odd enough case that we can
|
75
|
+
# safely ignore it.
|
48
76
|
if default_value.present? &&
|
49
77
|
!default_value.is_a?(Proc) &&
|
50
|
-
|
51
|
-
|
78
|
+
(
|
79
|
+
connection.quote_default_expression(default_value, column) == "NULL" ||
|
80
|
+
(
|
81
|
+
![:string, :text, :binary].include?(column.sql_type_metadata.type) &&
|
82
|
+
default_value.is_a?(String)
|
83
|
+
)
|
84
|
+
)
|
85
|
+
raise PgHaMigrations::InvalidMigrationError, <<~ERROR
|
86
|
+
Setting a default value to an expression using a string literal is ambiguous.
|
87
|
+
|
88
|
+
If you want the default to be:
|
89
|
+
* ...a constant scalar value, use the matching Ruby object type instead of a string if possible (e.g., `DateTime.new(...)`).
|
90
|
+
* ...an expression evaluated at runtime for each row, then pass a Proc that returns the expression string (e.g., `-> { "NOW()" }`).
|
91
|
+
* ...an expression evaluated at migration time, then pass a Proc that returns a quoted expression string (e.g., `-> { "'NOW()'" }`).
|
92
|
+
ERROR
|
52
93
|
end
|
53
94
|
|
54
95
|
safely_acquire_lock_for_table(table_name) do
|
@@ -76,7 +117,7 @@ module PgHaMigrations::SafeStatements
|
|
76
117
|
unless options.is_a?(Hash) && options.key?(:name)
|
77
118
|
raise ArgumentError, "Expected safe_remove_concurrent_index to be called with arguments (table_name, :name => ...)"
|
78
119
|
end
|
79
|
-
unless ActiveRecord::Base.connection.postgresql_version >=
|
120
|
+
unless ActiveRecord::Base.connection.postgresql_version >= 9_06_00
|
80
121
|
raise PgHaMigrations::InvalidMigrationError, "Removing an index concurrently is not supported on Postgres 9.1 databases"
|
81
122
|
end
|
82
123
|
index_size = select_value("SELECT pg_size_pretty(pg_relation_size('#{options[:name]}'))")
|
@@ -88,6 +129,66 @@ module PgHaMigrations::SafeStatements
|
|
88
129
|
unsafe_execute("SET maintenance_work_mem = '#{PG::Connection.escape_string(gigabytes.to_s)} GB'")
|
89
130
|
end
|
90
131
|
|
132
|
+
def safe_add_unvalidated_check_constraint(table, expression, name:)
|
133
|
+
unsafe_add_check_constraint(table, expression, name: name, validate: false)
|
134
|
+
end
|
135
|
+
|
136
|
+
def unsafe_add_check_constraint(table, expression, name:, validate: true)
|
137
|
+
raise ArgumentError, "Expected <name> to be present" unless name.present?
|
138
|
+
|
139
|
+
quoted_table_name = connection.quote_table_name(table)
|
140
|
+
quoted_constraint_name = connection.quote_table_name(name)
|
141
|
+
sql = "ALTER TABLE #{quoted_table_name} ADD CONSTRAINT #{quoted_constraint_name} CHECK (#{expression}) #{validate ? "" : "NOT VALID"}"
|
142
|
+
|
143
|
+
safely_acquire_lock_for_table(table) do
|
144
|
+
say_with_time "add_check_constraint(#{table.inspect}, #{expression.inspect}, name: #{name.inspect}, validate: #{validate.inspect})" do
|
145
|
+
connection.execute(sql)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
|
150
|
+
def safe_validate_check_constraint(table, name:)
|
151
|
+
raise ArgumentError, "Expected <name> to be present" unless name.present?
|
152
|
+
|
153
|
+
quoted_table_name = connection.quote_table_name(table)
|
154
|
+
quoted_constraint_name = connection.quote_table_name(name)
|
155
|
+
sql = "ALTER TABLE #{quoted_table_name} VALIDATE CONSTRAINT #{quoted_constraint_name}"
|
156
|
+
|
157
|
+
say_with_time "validate_check_constraint(#{table.inspect}, name: #{name.inspect})" do
|
158
|
+
connection.execute(sql)
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
def safe_rename_constraint(table, from:, to:)
|
163
|
+
raise ArgumentError, "Expected <from> to be present" unless from.present?
|
164
|
+
raise ArgumentError, "Expected <to> to be present" unless to.present?
|
165
|
+
|
166
|
+
quoted_table_name = connection.quote_table_name(table)
|
167
|
+
quoted_constraint_from_name = connection.quote_table_name(from)
|
168
|
+
quoted_constraint_to_name = connection.quote_table_name(to)
|
169
|
+
sql = "ALTER TABLE #{quoted_table_name} RENAME CONSTRAINT #{quoted_constraint_from_name} TO #{quoted_constraint_to_name}"
|
170
|
+
|
171
|
+
safely_acquire_lock_for_table(table) do
|
172
|
+
say_with_time "rename_constraint(#{table.inspect}, from: #{from.inspect}, to: #{to.inspect})" do
|
173
|
+
connection.execute(sql)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
def unsafe_remove_constraint(table, name:)
|
179
|
+
raise ArgumentError, "Expected <name> to be present" unless name.present?
|
180
|
+
|
181
|
+
quoted_table_name = connection.quote_table_name(table)
|
182
|
+
quoted_constraint_name = connection.quote_table_name(name)
|
183
|
+
sql = "ALTER TABLE #{quoted_table_name} DROP CONSTRAINT #{quoted_constraint_name}"
|
184
|
+
|
185
|
+
safely_acquire_lock_for_table(table) do
|
186
|
+
say_with_time "remove_constraint(#{table.inspect}, name: #{name.inspect})" do
|
187
|
+
connection.execute(sql)
|
188
|
+
end
|
189
|
+
end
|
190
|
+
end
|
191
|
+
|
91
192
|
def _per_migration_caller
|
92
193
|
@_per_migration_caller ||= Kernel.caller
|
93
194
|
end
|
@@ -98,6 +199,14 @@ module PgHaMigrations::SafeStatements
|
|
98
199
|
raise PgHaMigrations::UnsupportedAdapter, "This gem only works with the #{expected_adapter} adapter, found #{actual_adapter} instead" unless actual_adapter == expected_adapter
|
99
200
|
end
|
100
201
|
|
202
|
+
def migrate(direction)
|
203
|
+
if respond_to?(:change)
|
204
|
+
raise PgHaMigrations::UnsupportedMigrationError, "Tracking changes for automated rollback is not supported; use explicit #up instead."
|
205
|
+
end
|
206
|
+
|
207
|
+
super(direction)
|
208
|
+
end
|
209
|
+
|
101
210
|
def exec_migration(conn, direction)
|
102
211
|
_check_postgres_adapter!
|
103
212
|
super(conn, direction)
|
@@ -123,7 +232,7 @@ module PgHaMigrations::SafeStatements
|
|
123
232
|
end
|
124
233
|
|
125
234
|
connection.transaction do
|
126
|
-
adjust_timeout_method = connection.postgresql_version >=
|
235
|
+
adjust_timeout_method = connection.postgresql_version >= 9_03_00 ? :adjust_lock_timeout : :adjust_statement_timeout
|
127
236
|
begin
|
128
237
|
method(adjust_timeout_method).call(PgHaMigrations::LOCK_TIMEOUT_SECONDS) do
|
129
238
|
connection.execute("LOCK #{quoted_table_name};")
|
@@ -43,6 +43,7 @@ module PgHaMigrations::UnsafeStatements
|
|
43
43
|
delegate_unsafe_method_to_migration_base_class :execute
|
44
44
|
delegate_unsafe_method_to_migration_base_class :remove_index
|
45
45
|
delegate_unsafe_method_to_migration_base_class :add_foreign_key
|
46
|
+
delegate_unsafe_method_to_migration_base_class :remove_foreign_key
|
46
47
|
|
47
48
|
disable_or_delegate_default_method :create_table, ":create_table is NOT SAFE! Use safe_create_table instead"
|
48
49
|
disable_or_delegate_default_method :add_column, ":add_column is NOT SAFE! Use safe_add_column instead"
|
@@ -58,6 +59,7 @@ module PgHaMigrations::UnsafeStatements
|
|
58
59
|
disable_or_delegate_default_method :execute, ":execute is NOT SAFE! Explicitly call :unsafe_execute to proceed", allow_reentry_from_compatibility_module: true
|
59
60
|
disable_or_delegate_default_method :remove_index, ":remove_index is NOT SAFE! Use safe_remove_concurrent_index instead for Postgres 9.6 databases; Explicitly call :unsafe_remove_index to proceed on Postgres 9.1"
|
60
61
|
disable_or_delegate_default_method :add_foreign_key, ":add_foreign_key is NOT SAFE! Explicitly call :unsafe_add_foreign_key"
|
62
|
+
disable_or_delegate_default_method :remove_foreign_key, ":remove_foreign_key is NOT SAFE! Explicitly call :unsafe_remove_foreign_key"
|
61
63
|
|
62
64
|
def unsafe_create_table(table, options={}, &block)
|
63
65
|
if options[:force] && !PgHaMigrations.config.allow_force_create_table
|
data/lib/pg_ha_migrations.rb
CHANGED
@@ -35,6 +35,10 @@ module PgHaMigrations
|
|
35
35
|
# as expected or get the schema into an inconsistent state
|
36
36
|
InvalidMigrationError = Class.new(Exception)
|
37
37
|
|
38
|
+
# Unsupported migrations use ActiveRecord::Migration features that
|
39
|
+
# we don't support, and therefore will likely have unexpected behavior.
|
40
|
+
UnsupportedMigrationError = Class.new(Exception)
|
41
|
+
|
38
42
|
# This gem only supports the PostgreSQL adapter at this time.
|
39
43
|
UnsupportedAdapter = Class.new(Exception)
|
40
44
|
end
|
@@ -47,6 +51,7 @@ require "pg_ha_migrations/dependent_objects_checks"
|
|
47
51
|
require "pg_ha_migrations/allowed_versions"
|
48
52
|
require "pg_ha_migrations/railtie"
|
49
53
|
require "pg_ha_migrations/hacks/disable_ddl_transaction"
|
54
|
+
require "pg_ha_migrations/hacks/cleanup_unnecessary_output"
|
50
55
|
|
51
56
|
module PgHaMigrations::AutoIncluder
|
52
57
|
def inherited(klass)
|
data/pg_ha_migrations.gemspec
CHANGED
@@ -29,13 +29,13 @@ Gem::Specification.new do |spec|
|
|
29
29
|
spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
|
30
30
|
spec.require_paths = ["lib"]
|
31
31
|
|
32
|
-
spec.add_development_dependency "bundler", "~> 1.15"
|
33
32
|
spec.add_development_dependency "rake", "~> 10.0"
|
34
33
|
spec.add_development_dependency "rspec", "~> 3.0"
|
35
34
|
spec.add_development_dependency "pg"
|
36
35
|
spec.add_development_dependency "db-query-matchers", "~> 0.9.0"
|
37
|
-
spec.add_development_dependency
|
38
|
-
spec.add_development_dependency
|
36
|
+
spec.add_development_dependency "pry"
|
37
|
+
spec.add_development_dependency "pry-byebug"
|
38
|
+
spec.add_development_dependency "appraisal", "~> 2.2.0"
|
39
39
|
|
40
40
|
spec.add_dependency "rails", ">= 5.0", "< 5.3"
|
41
41
|
spec.add_dependency "relation_to_struct"
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pg_ha_migrations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- celeen
|
@@ -14,22 +14,8 @@ authors:
|
|
14
14
|
autorequire:
|
15
15
|
bindir: exe
|
16
16
|
cert_chain: []
|
17
|
-
date:
|
17
|
+
date: 2020-01-31 00:00:00.000000000 Z
|
18
18
|
dependencies:
|
19
|
-
- !ruby/object:Gem::Dependency
|
20
|
-
name: bundler
|
21
|
-
requirement: !ruby/object:Gem::Requirement
|
22
|
-
requirements:
|
23
|
-
- - "~>"
|
24
|
-
- !ruby/object:Gem::Version
|
25
|
-
version: '1.15'
|
26
|
-
type: :development
|
27
|
-
prerelease: false
|
28
|
-
version_requirements: !ruby/object:Gem::Requirement
|
29
|
-
requirements:
|
30
|
-
- - "~>"
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: '1.15'
|
33
19
|
- !ruby/object:Gem::Dependency
|
34
20
|
name: rake
|
35
21
|
requirement: !ruby/object:Gem::Requirement
|
@@ -114,6 +100,20 @@ dependencies:
|
|
114
100
|
- - ">="
|
115
101
|
- !ruby/object:Gem::Version
|
116
102
|
version: '0'
|
103
|
+
- !ruby/object:Gem::Dependency
|
104
|
+
name: appraisal
|
105
|
+
requirement: !ruby/object:Gem::Requirement
|
106
|
+
requirements:
|
107
|
+
- - "~>"
|
108
|
+
- !ruby/object:Gem::Version
|
109
|
+
version: 2.2.0
|
110
|
+
type: :development
|
111
|
+
prerelease: false
|
112
|
+
version_requirements: !ruby/object:Gem::Requirement
|
113
|
+
requirements:
|
114
|
+
- - "~>"
|
115
|
+
- !ruby/object:Gem::Version
|
116
|
+
version: 2.2.0
|
117
117
|
- !ruby/object:Gem::Dependency
|
118
118
|
name: rails
|
119
119
|
requirement: !ruby/object:Gem::Requirement
|
@@ -161,6 +161,7 @@ files:
|
|
161
161
|
- ".rspec"
|
162
162
|
- ".ruby-version"
|
163
163
|
- ".travis.yml"
|
164
|
+
- Appraisals
|
164
165
|
- CODE_OF_CONDUCT.md
|
165
166
|
- Gemfile
|
166
167
|
- LICENSE.txt
|
@@ -168,11 +169,16 @@ files:
|
|
168
169
|
- Rakefile
|
169
170
|
- bin/console
|
170
171
|
- bin/setup
|
172
|
+
- gemfiles/.bundle/config
|
173
|
+
- gemfiles/rails_5.0.gemfile
|
174
|
+
- gemfiles/rails_5.1.gemfile
|
175
|
+
- gemfiles/rails_5.2.gemfile
|
171
176
|
- lib/pg_ha_migrations.rb
|
172
177
|
- lib/pg_ha_migrations/allowed_versions.rb
|
173
178
|
- lib/pg_ha_migrations/blocking_database_transactions.rb
|
174
179
|
- lib/pg_ha_migrations/blocking_database_transactions_reporter.rb
|
175
180
|
- lib/pg_ha_migrations/dependent_objects_checks.rb
|
181
|
+
- lib/pg_ha_migrations/hacks/cleanup_unnecessary_output.rb
|
176
182
|
- lib/pg_ha_migrations/hacks/disable_ddl_transaction.rb
|
177
183
|
- lib/pg_ha_migrations/railtie.rb
|
178
184
|
- lib/pg_ha_migrations/safe_statements.rb
|
@@ -199,7 +205,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
199
205
|
- !ruby/object:Gem::Version
|
200
206
|
version: '0'
|
201
207
|
requirements: []
|
202
|
-
rubygems_version: 3.0.
|
208
|
+
rubygems_version: 3.0.6
|
203
209
|
signing_key:
|
204
210
|
specification_version: 4
|
205
211
|
summary: Enforces DDL/migration safety in Ruby on Rails project with an emphasis on
|