ridgepole 3.0.3 → 3.0.4

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: 5d9ad7e2017aa2af02dd9f0fb5c45cdc7fd1a4f3925778e966246589e352d5ea
4
- data.tar.gz: b07a08f0001ed86483597794962e0293be0dc609b7c0a5fdc4425c28c10b8b49
3
+ metadata.gz: 931a6b90df6d277ffd72a272342058290e4fcc8b793ffc0b94f2719a9fc6de4e
4
+ data.tar.gz: '01879ec62757730657f0197c052f2601fe74561286cef3fc4d7c9e82bc329764'
5
5
  SHA512:
6
- metadata.gz: 5747b6d95e0fb69c35c40508935d5474f1ed3750d09354218cfdda6a35de7b5ecbe2a45307bcdca718f2d15a1af12e9c7d95271837c1ae46e0903def31568e09
7
- data.tar.gz: 1ca608fb67b6fcfb6b21fd2c2d4a6fd354a1f7e93333c7e183b5af01a7fbf711693ba4910a43019145d342cb311523c6b54395c5afceb5624b36fddb7a0d361d
6
+ metadata.gz: ada25e648306fce2dbb1755c5746e2bcaf6a7e4413fada585ce278f4750f7b28493b2e156139b17cacdb5b95d70073771dc174c11ce32986033bfa80a8cc3bf9
7
+ data.tar.gz: 61e689542f00d014065941fab911c0c11a6cbd1f41ef0f293cce18ffb4f71de37f9499985f9a6c4241699fe796c7a7bc2721979834a3882ad52bb2fcbfac0011
data/CHANGELOG.md CHANGED
@@ -2,6 +2,11 @@
2
2
 
3
3
  ## 3.0
4
4
 
5
+ ### 3.0.4 (2025/08/31)
6
+
7
+ - Fix checking foreign key without index [pull#571](https://github.com/ridgepole/ridgepole/pull/571)
8
+ - Use `change_column_comment` for comment-only column changes [pull#567](https://github.com/ridgepole/ridgepole/pull/567)
9
+
5
10
  ### 3.0.3 (2025/07/23)
6
11
 
7
12
  - Fix for index `algorithm` option [pull#555](https://github.com/ridgepole/ridgepole/pull/555)
data/README.md CHANGED
@@ -329,6 +329,42 @@ Apply `Schemafile`
329
329
  ...
330
330
  ```
331
331
 
332
+ ## Define a partial index in PostgreSQL
333
+
334
+ Partial indexes in PostgreSQL are normalized so differences are always detected.
335
+
336
+ ```ruby
337
+ create_table "users", id: :serial, force: :cascade do |t|
338
+ t.text "email"
339
+ t.text "name"
340
+ t.index ["email"], name: "idx_users_email", unique: true, where: "email is not null"
341
+ end
342
+ ```
343
+
344
+ ```sh
345
+ % ridgepole -a -c database.yml --dry-run --verbose
346
+ Apply `Schemafile` (dry-run)
347
+ # Parse DSL
348
+ # ...
349
+ # Compare definitions
350
+ # users
351
+ :options=>
352
+ {:name=>"idx_users_email",
353
+ :unique=>true,
354
+ - :where=>"(email IS NOT NULL)"}}},
355
+ + :where=>"email is not null"}}},
356
+ :options=>{:id=>:serial}}
357
+ ```
358
+
359
+ Use a normalized WHERE clause to avoid detecting differences.
360
+
361
+ ```ruby
362
+ #t.index ["email"], name: "idx_users_email", unique: true, where: "email is not null"
363
+ t.index ["email"], name: "idx_users_email", unique: true, where: "(email IS NOT NULL)"
364
+ ```
365
+
366
+ see https://github.com/ridgepole/ridgepole/issues/568
367
+
332
368
  ## Run tests
333
369
 
334
370
 
@@ -344,6 +344,7 @@ execute "ALTER TABLE #{ActiveRecord::Base.connection.quote_table_name(table_name
344
344
  table_charset = attrs[:table_charset]
345
345
  table_collation = attrs[:table_collation]
346
346
  table_comment = attrs[:table_comment]
347
+ column_comments = attrs[:column_comments] || {}
347
348
 
348
349
  if !definition.empty? || !indices.empty? || !primary_key_definition.empty?
349
350
  append_change_table(table_name, buf) do
@@ -365,12 +366,21 @@ execute "ALTER TABLE #{ActiveRecord::Base.connection.quote_table_name(table_name
365
366
  end
366
367
 
367
368
  append_change_table_comment(table_name, table_comment, buf) if table_comment
369
+ append_change_column_comments(table_name, column_comments, buf) unless column_comments.empty?
368
370
 
369
371
  buf.puts
370
372
  pre_buf_for_fk.puts
371
373
  post_buf_for_fk.puts
372
374
  end
373
375
 
376
+ def append_change_column_comments(table_name, column_comments, buf)
377
+ column_comments.each do |column_name, comment|
378
+ buf.puts(<<-RUBY)
379
+ change_column_comment(#{table_name.inspect}, #{column_name.inspect}, #{comment.inspect})
380
+ RUBY
381
+ end
382
+ end
383
+
374
384
  def append_change_table(table_name, buf)
375
385
  buf.puts "change_table(#{table_name.inspect}, bulk: true) do |t|" if @options[:bulk_change]
376
386
  yield
@@ -234,6 +234,7 @@ module Ridgepole
234
234
  from = (from || {}).dup
235
235
  to = (to || {}).dup
236
236
  definition_delta = {}
237
+ column_comments = {}
237
238
 
238
239
  scan_column_rename(from, to, definition_delta)
239
240
 
@@ -249,10 +250,14 @@ module Ridgepole
249
250
  next if ignore_column
250
251
 
251
252
  if from_attrs
252
- to_attrs = build_attrs_if_changed(to_attrs, from_attrs)
253
- if to_attrs
254
- definition_delta[:change] ||= {}
255
- definition_delta[:change][column_name] = to_attrs
253
+ changed_attrs = build_attrs_if_changed(to_attrs, from_attrs)
254
+ if changed_attrs
255
+ if comment_only_change?(from_attrs, to_attrs)
256
+ column_comments[column_name] = to_attrs[:options][:comment]
257
+ else
258
+ definition_delta[:change] ||= {}
259
+ definition_delta[:change][column_name] = changed_attrs
260
+ end
256
261
  end
257
262
  else
258
263
  definition_delta[:add] ||= {}
@@ -307,6 +312,7 @@ module Ridgepole
307
312
  end
308
313
 
309
314
  table_delta[:definition] = definition_delta unless definition_delta.empty?
315
+ table_delta[:column_comments] = column_comments unless column_comments.empty?
310
316
  end
311
317
 
312
318
  def scan_column_rename(from, to, definition_delta)
@@ -626,6 +632,19 @@ module Ridgepole
626
632
  attrs1 == attrs2
627
633
  end
628
634
 
635
+ def comment_only_change?(attrs1, attrs2)
636
+ return false if @options[:skip_column_comment_change]
637
+
638
+ attrs1 = attrs1.merge(options: attrs1.fetch(:options, {}).dup)
639
+ attrs2 = attrs2.merge(options: attrs2.fetch(:options, {}).dup)
640
+ normalize_default_proc_options!(attrs1[:options], attrs2[:options])
641
+
642
+ comment1 = attrs1.fetch(:options).delete(:comment)
643
+ comment2 = attrs2.fetch(:options).delete(:comment)
644
+
645
+ attrs1 == attrs2 && comment1 != comment2
646
+ end
647
+
629
648
  def normalize_default_proc_options!(opts1, opts2)
630
649
  if opts1[:default].is_a?(Proc) && opts2[:default].is_a?(Proc)
631
650
  opts1[:default] = opts1[:default].call
@@ -31,8 +31,9 @@ module Ridgepole
31
31
  end
32
32
 
33
33
  def check_foreign_key_without_index(table_name, attrs)
34
+ return if Ridgepole::ConnectionAdapters.postgresql?
34
35
  return unless attrs[:foreign_keys]
35
- return unless attrs[:options][:options]&.include?('ENGINE=InnoDB')
36
+ return unless innodb_table?(attrs)
36
37
 
37
38
  attrs[:foreign_keys].each_value do |foreign_key_attrs|
38
39
  fk_index = foreign_key_attrs[:options][:column] || "#{foreign_key_attrs[:to_table].singularize}_id"
@@ -53,5 +54,10 @@ module Ridgepole
53
54
  Array(index_column_name).first == fk_index
54
55
  end
55
56
  end
57
+
58
+ def innodb_table?(attrs)
59
+ engine = attrs[:options][:options]&.match(/ENGINE=([^ ]+)/) && Regexp.last_match(1)
60
+ engine.nil? || engine == 'InnoDB'
61
+ end
56
62
  end
57
63
  end
@@ -3,6 +3,7 @@
3
3
  module Ridgepole
4
4
  class Logger < ::Logger
5
5
  include Singleton
6
+
6
7
  cattr_accessor :verbose
7
8
 
8
9
  def initialize
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Ridgepole
4
- VERSION = '3.0.3'
4
+ VERSION = '3.0.4'
5
5
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: ridgepole
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.0.3
4
+ version: 3.0.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Genki Sugawara
@@ -231,14 +231,14 @@ dependencies:
231
231
  requirements:
232
232
  - - '='
233
233
  - !ruby/object:Gem::Version
234
- version: 1.78.0
234
+ version: 1.80.0
235
235
  type: :development
236
236
  prerelease: false
237
237
  version_requirements: !ruby/object:Gem::Requirement
238
238
  requirements:
239
239
  - - '='
240
240
  - !ruby/object:Gem::Version
241
- version: 1.78.0
241
+ version: 1.80.0
242
242
  - !ruby/object:Gem::Dependency
243
243
  name: rubocop-rake
244
244
  requirement: !ruby/object:Gem::Requirement
@@ -318,22 +318,10 @@ executables:
318
318
  extensions: []
319
319
  extra_rdoc_files: []
320
320
  files:
321
- - ".rspec"
322
- - ".rubocop.yml"
323
- - ".simplecov"
324
- - Appraisals
325
321
  - CHANGELOG.md
326
- - Gemfile
327
322
  - LICENSE.txt
328
323
  - README.md
329
- - Rakefile
330
324
  - bin/ridgepole
331
- - compose.yml
332
- - gemfiles/activerecord_6.1.gemfile
333
- - gemfiles/activerecord_7.0.gemfile
334
- - gemfiles/activerecord_7.1.gemfile
335
- - gemfiles/activerecord_7.2.gemfile
336
- - gemfiles/activerecord_8.0.gemfile
337
325
  - lib/ridgepole.rb
338
326
  - lib/ridgepole/cli/config.rb
339
327
  - lib/ridgepole/client.rb
@@ -356,7 +344,6 @@ files:
356
344
  - lib/ridgepole/schema_dumper_ext.rb
357
345
  - lib/ridgepole/schema_statements_ext.rb
358
346
  - lib/ridgepole/version.rb
359
- - ridgepole.gemspec
360
347
  homepage: https://github.com/ridgepole/ridgepole
361
348
  licenses:
362
349
  - MIT
data/.rspec DELETED
@@ -1,3 +0,0 @@
1
- --color
2
- --require spec_helper
3
- --format HidePendingFormatter
data/.rubocop.yml DELETED
@@ -1,64 +0,0 @@
1
- AllCops:
2
- Exclude:
3
- - "gemfiles/**/*"
4
- - "omnibus-ridgepole/**/*"
5
- - "vendor/bundle/**/*"
6
- - "Schemafile"
7
- - "**/*.schema"
8
- TargetRubyVersion: 2.7
9
- NewCops: enable
10
- SuggestExtensions: false
11
- Bundler/OrderedGems:
12
- Include:
13
- - "Appraisals"
14
- Layout/HeredocIndentation:
15
- Enabled: false
16
- Metrics/AbcSize:
17
- Enabled: false
18
- Metrics/BlockLength:
19
- Enabled: false
20
- Metrics/BlockNesting:
21
- Enabled: false
22
- Metrics/ClassLength:
23
- Enabled: false
24
- Metrics/CyclomaticComplexity:
25
- Enabled: false
26
- Layout/LineLength:
27
- Max: 200
28
- Metrics/MethodLength:
29
- Enabled: false
30
- Metrics/ModuleLength:
31
- Max: 106
32
- Metrics/ParameterLists:
33
- Enabled: false
34
- Metrics/PerceivedComplexity:
35
- Enabled: false
36
- Style/Documentation:
37
- Enabled: false
38
- Style/GuardClause:
39
- Enabled: false
40
- Style/MixinUsage:
41
- Exclude:
42
- - "spec/**/*"
43
- Style/TrailingCommaInHashLiteral:
44
- EnforcedStyleForMultiline: consistent_comma
45
- Layout/ClosingHeredocIndentation:
46
- Enabled: false
47
- Style/NumericPredicate:
48
- Enabled: false
49
- Lint/MissingSuper:
50
- Enabled: false
51
- Style/StringConcatenation:
52
- Enabled: false
53
- Style/SoleNestedConditional:
54
- Enabled: false
55
- Lint/DuplicateBranch:
56
- Enabled: false
57
- Style/OptionalBooleanParameter:
58
- Enabled: false
59
- Gemspec/DevelopmentDependencies:
60
- Enabled: false
61
- Lint/LiteralInInterpolation:
62
- Enabled: false
63
- Naming/PredicateMethod:
64
- Enabled: false
data/.simplecov DELETED
@@ -1,6 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- SimpleCov.configure do
4
- # exclude directories and files
5
- add_filter '/spec/'
6
- end
data/Appraisals DELETED
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- appraise 'activerecord-6.1' do
4
- gem 'activerecord', '~> 6.1.7'
5
- end
6
-
7
- appraise 'activerecord-7.0' do
8
- gem 'activerecord', '~> 7.0.4'
9
- end
10
-
11
- appraise 'activerecord-7.1' do
12
- gem 'activerecord', '~> 7.1.0'
13
- end
14
-
15
- appraise 'activerecord-7.2' do
16
- gem 'activerecord', '~> 7.2.0'
17
- end
18
-
19
- appraise 'activerecord-8.0' do
20
- gem 'activerecord', '~> 8.0.0'
21
- end
data/Gemfile DELETED
@@ -1,8 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- source 'https://rubygems.org'
4
-
5
- # Specify your gem's dependencies in ridgepole.gemspec
6
- gemspec
7
-
8
- gem 'mutex_m' if Gem::Version.create(RUBY_VERSION) >= Gem::Version.create('3.4.0')
data/Rakefile DELETED
@@ -1,13 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'bundler/gem_tasks'
4
- require 'rspec/core/rake_task'
5
- require 'rubocop/rake_task'
6
-
7
- RSpec::Core::RakeTask.new('spec')
8
-
9
- RuboCop::RakeTask.new do |task|
10
- task.options = %w[-c .rubocop.yml]
11
- end
12
-
13
- task default: %i[rubocop spec]
data/compose.yml DELETED
@@ -1,20 +0,0 @@
1
- services:
2
- mysql57:
3
- image: "mysql:5.7"
4
- platform: linux/amd64
5
- ports:
6
- - "13316:3306"
7
- environment:
8
- MYSQL_ROOT_PASSWORD: password
9
- mysql80:
10
- image: "mysql:8.0"
11
- ports:
12
- - "13318:3306"
13
- environment:
14
- MYSQL_ROOT_PASSWORD: password
15
- postgres:
16
- image: "postgres:14"
17
- ports:
18
- - "15442:5432"
19
- environment:
20
- POSTGRES_PASSWORD: password
@@ -1,7 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "activerecord", "~> 6.1.7"
6
-
7
- gemspec path: "../"
@@ -1,7 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "activerecord", "~> 7.0.4"
6
-
7
- gemspec path: "../"
@@ -1,7 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "activerecord", "~> 7.1.0"
6
-
7
- gemspec path: "../"
@@ -1,7 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "activerecord", "~> 7.2.0"
6
-
7
- gemspec path: "../"
@@ -1,7 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "activerecord", "~> 8.0.0"
6
-
7
- gemspec path: "../"
data/ridgepole.gemspec DELETED
@@ -1,51 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- lib = File.expand_path('lib', __dir__)
4
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
5
- require 'ridgepole/version'
6
-
7
- Gem::Specification.new do |spec|
8
- spec.name = 'ridgepole'
9
- spec.version = Ridgepole::VERSION
10
- spec.authors = ['Genki Sugawara']
11
- spec.email = ['sugawara@winebarrel.jp']
12
- spec.summary = 'Ridgepole is a tool to manage DB schema.'
13
- spec.description = 'Ridgepole is a tool to manage DB schema. It defines DB schema using Rails DSL, and updates DB schema according to DSL.'
14
- spec.homepage = 'https://github.com/ridgepole/ridgepole'
15
- spec.license = 'MIT'
16
- spec.platform = Gem::Platform::RUBY
17
-
18
- spec.files = Dir.chdir(File.expand_path(__dir__)) do
19
- `git ls-files -z`.split("\x0").reject do |f|
20
- f.match(%r{\A(?:(?:test|spec|features)/|\.(?:git|travis|circleci)|appveyor)})
21
- end
22
- end
23
- spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
24
- spec.require_paths = ['lib']
25
-
26
- spec.required_ruby_version = Gem::Requirement.new('>= 2.7')
27
-
28
- spec.add_dependency 'activerecord', '>= 6.1', '< 8.1'
29
- spec.add_dependency 'diffy'
30
- spec.add_dependency 'logger'
31
-
32
- spec.add_development_dependency 'appraisal', '>= 2.2.0'
33
- spec.add_development_dependency 'bigdecimal'
34
- spec.add_development_dependency 'bundler'
35
- spec.add_development_dependency 'erbh', '>= 0.2.1'
36
- spec.add_development_dependency 'hash_modern_inspect', '>= 0.1.1'
37
- spec.add_development_dependency 'hash_order_helper', '>= 0.1.6'
38
- spec.add_development_dependency 'mysql2'
39
- spec.add_development_dependency 'pg'
40
- spec.add_development_dependency 'rake'
41
- spec.add_development_dependency 'rspec', '>= 3.0.0'
42
- spec.add_development_dependency 'rspec-match_fuzzy', '>= 0.2.0'
43
- spec.add_development_dependency 'rspec-match_ruby', '>= 0.1.3'
44
- spec.add_development_dependency 'rubocop', '1.78.0'
45
- spec.add_development_dependency 'rubocop-rake', '>= 0.5.1'
46
- spec.add_development_dependency 'rubocop-rspec', '>= 2.1.0'
47
- spec.add_development_dependency 'simplecov'
48
- spec.add_development_dependency 'simplecov-lcov'
49
- spec.add_development_dependency 'trilogy'
50
- spec.metadata['rubygems_mfa_required'] = 'true'
51
- end