pg_ha_migrations 1.3.0 → 1.4.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: 642f8332dd491d8b489d7044c8989bcfc8a7e34c63ad380c42ed3e78f45c5c8f
4
- data.tar.gz: 0bec0715601bce8ddd77d83c03c399b2dff21039301a72b67899d5041012c231
3
+ metadata.gz: 05dbece254aee14a92945662e8af6ef7a0a94a871b55f21f527c8b277c9ec543
4
+ data.tar.gz: b744971a9a2616b41c78dacd4f6d912a97ca4e3b0799b87fbcc9823d7da11213
5
5
  SHA512:
6
- metadata.gz: b40ccad5d82c2f2167515eca20da2152482c7e9cd11b84dbf721b0840c7c40462a8818d4bb8dbea840196171185dd3ddc1fb28e205f96a7845cc9c3df69d1a67
7
- data.tar.gz: 2a07b86116d69ee0a51ec8b9d7fb4bcc6ba876e363df79902e7bed3f7ab123bd9f4c4c21b15ba538c0d8850b6f82c353f0c02fa7ad2ac11f8f84ee1f29787bd6
6
+ metadata.gz: 7a6ed6c77b7106354a2f9a78545aae555145f9aac8d851e61be20d54bdaa283858646fe4f03172bb39836919aa942e8caa3854a48146caffeebf0c9bcfe48e03
7
+ data.tar.gz: b502c70bdc1eebda9e152bea35f1e8d000daa55b592d043eb5ae3f0bde347c459f60c83d31c6f000f741ff4d5b953ed8e3bcd70b0e4488288a3cc9b7657a9246
data/README.md CHANGED
@@ -148,6 +148,8 @@ safe_change_column_default :table, :column, -> { "NOW()" }
148
148
  safe_change_column_default :table, :column, -> { "'NOW()'" }
149
149
  ```
150
150
 
151
+ Note: On Postgres 11+ adding a column with a constant default value does not rewrite or scan the table (under a lock or otherwise). In that case a migration adding a column with a default should do so in a single operation rather than the two-step `safe_add_column` followed by `safe_change_column_default`. We enforce this best practice with the error `PgHaMigrations::BestPracticeError`, but if your prefer otherwise (or are running in a mixed Postgres version environment), you may opt out by setting `config.prefer_single_step_column_addition_with_default = true` [in your configuration initializer](#configuration).
152
+
151
153
  #### safe\_make\_column\_nullable
152
154
 
153
155
  Safely make the column nullable.
@@ -272,6 +274,8 @@ end
272
274
 
273
275
  - `disable_default_migration_methods`: If true, the default implementations of DDL changes in `ActiveRecord::Migration` and the PostgreSQL adapter will be overridden by implementations that raise a `PgHaMigrations::UnsafeMigrationError`. Default: `true`
274
276
  - `check_for_dependent_objects`: If true, some `unsafe_*` migration methods will raise a `PgHaMigrations::UnsafeMigrationError` if any dependent objects exist. Default: `false`
277
+ - `prefer_single_step_column_addition_with_default`: If `true`, raise an error when adding a column and separately setting a constant default value for that column in the same migration. Default: `false`
278
+ - 'allow_force_create_table`: If false, the `force: true` option to ActiveRecord's `create_table` method is disallowed. Default: `true`
275
279
 
276
280
  ### Rake Tasks
277
281
 
@@ -299,7 +303,11 @@ After checking out the repo, run `bin/setup` to install dependencies and start a
299
303
 
300
304
  Running tests will automatically create a test database in the locally running Postgres server. You can find the connection parameters in `spec/spec_helper.rb`, but setting the environment variables `PGHOST`, `PGPORT`, `PGUSER`, and `PGPASSWORD` will override the defaults.
301
305
 
302
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
306
+ To install this gem onto your local machine, run `bundle exec rake install`.
307
+
308
+ To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).
309
+
310
+ Note: if while releasing the gem you get the error `Your rubygems.org credentials aren't set. Run \`gem push\` to set them.` you can more simply run `gem signin`.
303
311
 
304
312
  ## Contributing
305
313
 
@@ -49,10 +49,6 @@ module PgHaMigrations
49
49
  LEFT JOIN pg_class c ON ( -- Database wide
50
50
  l.locktype = 'relation'
51
51
  AND l.relation = c.oid
52
- -- Be explicit about this being for a single database -- it's already implicit in
53
- -- the relations used, and if we don't restrict this we could get incorrect results
54
- -- with oid collisions from pg_namespace and pg_class.
55
- AND l.database = (SELECT d.oid FROM pg_database d WHERE d.datname = current_database())
56
52
  )
57
53
  LEFT JOIN pg_namespace ns ON (c.relnamespace = ns.oid) -- Database wide
58
54
  WHERE psa.#{pid_column} != pg_backend_pid()
@@ -65,6 +61,10 @@ module PgHaMigrations
65
61
  )
66
62
  AND psa.xact_start < clock_timestamp() - ?::interval
67
63
  AND psa.#{query_column} !~ ?
64
+ -- Be explicit about this being for a single database -- it's already implicit in
65
+ -- the relations used, and if we don't restrict this we could get incorrect results
66
+ -- with oid collisions from pg_namespace and pg_class.
67
+ AND psa.datname = current_database()
68
68
  #{postgres_version >= 10_00_00 ? "AND #{ignore_sqlsender_sql}" : ""}
69
69
  GROUP BY psa.datname, psa.#{query_column}, psa.state, psa.xact_start
70
70
  SQL
@@ -1,4 +1,8 @@
1
1
  module PgHaMigrations::SafeStatements
2
+ def safe_added_columns_without_default_value
3
+ @safe_added_columns_without_default_value ||= []
4
+ end
5
+
2
6
  def safe_create_table(table, options={}, &block)
3
7
  if options[:force]
4
8
  raise PgHaMigrations::UnsafeMigrationError.new(":force is NOT SAFE! Explicitly call unsafe_drop_table first if you want to recreate an existing table")
@@ -52,6 +56,10 @@ module PgHaMigrations::SafeStatements
52
56
  raise PgHaMigrations::UnsafeMigrationError.new(":null => false is NOT SAFE if the table has data! If you _really_ want to do this, use unsafe_make_column_not_nullable")
53
57
  end
54
58
 
59
+ unless options.has_key?(:default)
60
+ self.safe_added_columns_without_default_value << [table.to_s, column.to_s]
61
+ end
62
+
55
63
  unsafe_add_column(table, column, type, options)
56
64
  end
57
65
 
@@ -62,6 +70,12 @@ module PgHaMigrations::SafeStatements
62
70
  end
63
71
 
64
72
  def safe_change_column_default(table_name, column_name, default_value)
73
+ if PgHaMigrations.config.prefer_single_step_column_addition_with_default &&
74
+ ActiveRecord::Base.connection.postgresql_version >= 11_00_00 &&
75
+ self.safe_added_columns_without_default_value.include?([table_name.to_s, column_name.to_s])
76
+ raise PgHaMigrations::BestPracticeError, "On Postgres 11+ it's safe to set a constant default value when adding a new column; please set the default value as part of the column addition"
77
+ end
78
+
65
79
  column = connection.send(:column_for, table_name, column_name)
66
80
 
67
81
  # In 5.2 we have an edge whereby passing in a string literal with an expression
@@ -1,3 +1,3 @@
1
1
  module PgHaMigrations
2
- VERSION = "1.3.0"
2
+ VERSION = "1.4.0"
3
3
  end
@@ -8,14 +8,16 @@ module PgHaMigrations
8
8
  Config = Struct.new(
9
9
  :disable_default_migration_methods,
10
10
  :check_for_dependent_objects,
11
- :allow_force_create_table
11
+ :allow_force_create_table,
12
+ :prefer_single_step_column_addition_with_default
12
13
  )
13
14
 
14
15
  def self.config
15
16
  @config ||= Config.new(
16
17
  true,
17
18
  false,
18
- true
19
+ true,
20
+ false
19
21
  )
20
22
  end
21
23
 
@@ -29,18 +31,24 @@ module PgHaMigrations
29
31
  # Safe versus unsafe in this context specifically means the following:
30
32
  # - Safe operations will not block for long periods of time.
31
33
  # - Unsafe operations _may_ block for long periods of time.
32
- UnsafeMigrationError = Class.new(Exception)
34
+ UnsafeMigrationError = Class.new(StandardError)
33
35
 
34
36
  # Invalid migrations are operations which we expect to not function
35
37
  # as expected or get the schema into an inconsistent state
36
- InvalidMigrationError = Class.new(Exception)
38
+ InvalidMigrationError = Class.new(StandardError)
39
+
40
+ # Operations violating a best practice, but not actually unsafe will
41
+ # raise this error. For example, adding a column without a default and
42
+ # then setting its default in a second action in a single migration
43
+ # isn't our documented best practice and will raise this error.
44
+ BestPracticeError = Class.new(Exception)
37
45
 
38
46
  # Unsupported migrations use ActiveRecord::Migration features that
39
47
  # we don't support, and therefore will likely have unexpected behavior.
40
- UnsupportedMigrationError = Class.new(Exception)
48
+ UnsupportedMigrationError = Class.new(StandardError)
41
49
 
42
50
  # This gem only supports the PostgreSQL adapter at this time.
43
- UnsupportedAdapter = Class.new(Exception)
51
+ UnsupportedAdapter = Class.new(StandardError)
44
52
  end
45
53
 
46
54
  require "pg_ha_migrations/blocking_database_transactions"
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.3.0
4
+ version: 1.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - celeen
@@ -14,7 +14,7 @@ authors:
14
14
  autorequire:
15
15
  bindir: exe
16
16
  cert_chain: []
17
- date: 2021-09-14 00:00:00.000000000 Z
17
+ date: 2022-01-10 00:00:00.000000000 Z
18
18
  dependencies:
19
19
  - !ruby/object:Gem::Dependency
20
20
  name: rake
@@ -161,7 +161,6 @@ files:
161
161
  - ".pryrc"
162
162
  - ".rspec"
163
163
  - ".ruby-version"
164
- - ".travis.yml"
165
164
  - Appraisals
166
165
  - CODE_OF_CONDUCT.md
167
166
  - Gemfile
data/.travis.yml DELETED
@@ -1,27 +0,0 @@
1
- sudo: false
2
- language: ruby
3
- rvm:
4
- - 2.5
5
- env:
6
- jobs:
7
- - PGVERSION: "9.6"
8
- - PGVERSION: "10"
9
- - PGVERSION: "11"
10
- - PGVERSION: "12"
11
- services:
12
- - postgresql
13
- before_install:
14
- - "for CLUSTER_VERSION in $(pg_lsclusters -h | cut -d' ' -f1); do sudo pg_dropcluster $CLUSTER_VERSION main --stop || true; done"
15
- - sudo apt-get update
16
- - sudo apt-get -y install postgresql-$PGVERSION postgresql-client-$PGVERSION postgresql-server-dev-$PGVERSION postgresql-client-common postgresql-common
17
- - sudo pg_dropcluster $PGVERSION main --stop || true
18
- - sudo pg_createcluster $PGVERSION main -D /var/ramfs/postgresql/11/main -- --auth=trust
19
- - sudo pg_ctlcluster start $PGVERSION main
20
- - gem uninstall -v '>= 2' -i $(rvm gemdir)@global -ax bundler || true
21
- - gem install bundler -v 1.15.4
22
- gemfile:
23
- - gemfiles/rails_5.0.gemfile
24
- - gemfiles/rails_5.1.gemfile
25
- - gemfiles/rails_5.2.gemfile
26
- - gemfiles/rails_6.0.gemfile
27
- script: "bundle exec rake spec"