after_migrate 0.1.0 → 0.1.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a04f2af70c48d8299c3c1eedce77608a6a57aca044711bbc2c0e8030299d18e3
4
- data.tar.gz: d511331553aacbe753d40b2004af8d523b2c823ef4ba425f8491eb8a0336d234
3
+ metadata.gz: 2602aa9ee3d2ffa2c1ea85ca8cbfa1b101679aa42ed05e0a4cfa4c742f258f59
4
+ data.tar.gz: d581242202742eb6a62be1cd1799a49c196ca82c99e8b36428ee6390fd12c415
5
5
  SHA512:
6
- metadata.gz: c3f07535162f76e33ff8a7a399bbdee3b45d534b48a5609c600504a1f8b0e9c8d4d2e027ec653b7106c12e6663f91194370a9617912bd35860cdb77e6c451e6d
7
- data.tar.gz: 8c529f7d643720957caf72ae2607055e286dbcafc7c15004a03e3908a6be9eab15c7dcc9c66b83c1b741265c70a2a1476e440846178bea2799a4884857639187
6
+ metadata.gz: d81dce8555f469b190b3cfd37f7eb2b919aab714e6fcfb1842271c323495b213be2c2e779c8400ad67d28832c11dbc7ad7147e90f93b6950069b6b6b9ea8d558
7
+ data.tar.gz: 77f23e51b264cf80b5cbf028a0e43106d13498f9f7d109b1eafe26c6380269c08bb3574946ec534d08b8ac175a09c008823e64d0c862c4e4441e66c1df145399
data/README.md CHANGED
@@ -28,7 +28,6 @@ Stale statistics and fragmentation after schema changes silently hurt query perf
28
28
  - No monkey-patching of ActiveRecord core classes
29
29
  - Works in development, test, CI, and production
30
30
  - Rails 7.0+ / Ruby 3.2+ only
31
- - Dependency-free
32
31
 
33
32
  ---
34
33
 
@@ -43,5 +43,6 @@ Gem::Specification.new do |spec|
43
43
 
44
44
  spec.required_ruby_version = '>= 3.2'
45
45
 
46
+ spec.add_dependency 'pg_query', '>= 6.1'
46
47
  spec.add_dependency 'rails', '>= 7.0'
47
48
  end
@@ -2,6 +2,8 @@
2
2
 
3
3
  module AfterMigrate
4
4
  module Mysql
5
+ extend Sql
6
+
5
7
  module_function
6
8
 
7
9
  def optimize_tables(connection:, table_names:, **)
@@ -1,7 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'pg_query'
4
+
3
5
  module AfterMigrate
4
6
  module Postgresql
7
+ extend Sql
8
+
5
9
  module_function
6
10
 
7
11
  def vacuum(table_name, schema: nil, verbose: true)
@@ -64,22 +68,26 @@ module AfterMigrate
64
68
  tables = table_names - cleaned_tables
65
69
  run_analyze(schema:, tables:)
66
70
  end
67
- end
68
71
 
69
- def all_tables(schema: nil)
70
- connection = ActiveRecord::Base.connection
71
- schema_value = schema ? schema.to_s.strip : 'public'
72
+ def all_tables(schema: nil)
73
+ connection = ActiveRecord::Base.connection
74
+ schema_value = schema ? schema.to_s.strip : 'public'
72
75
 
73
- query = <<~SQL.squish
74
- SELECT c.relname AS table_name
75
- FROM pg_class c
76
- JOIN pg_namespace n ON n.oid = c.relnamespace
77
- WHERE n.nspname = #{connection.quote(schema_value)}
78
- AND c.relkind IN ('r', 'p') -- ordinary tables + partitioned tables
79
- AND c.relispartition = FALSE -- exclude partition child tables
80
- ORDER BY table_name
81
- SQL
76
+ query = <<~SQL.squish
77
+ SELECT c.relname AS table_name
78
+ FROM pg_class c
79
+ JOIN pg_namespace n ON n.oid = c.relnamespace
80
+ WHERE n.nspname = #{connection.quote(schema_value)}
81
+ AND c.relkind IN ('r', 'p') -- ordinary tables + partitioned tables
82
+ AND c.relispartition = FALSE -- exclude partition child tables
83
+ ORDER BY table_name
84
+ SQL
85
+
86
+ connection.select_values(query)
87
+ end
82
88
 
83
- connection.select_values(query)
89
+ def parse_tables(sql)
90
+ PgQuery.parse(sql).tables
91
+ end
84
92
  end
85
93
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AfterMigrate
4
+ module Sql
5
+ IDENT = /
6
+ (?:"[\w]+"|\w+)
7
+ (?:\.(?:"[\w]+"|\w+))*
8
+ /x
9
+
10
+ PATTERNS = {
11
+ update: /update\s+(?:only\s+)?(#{IDENT})(?!\s*\()/ix,
12
+ insert: /insert\s+into\s+(#{IDENT})(?!\s*\()/ix,
13
+ delete: /delete\s+from\s+(#{IDENT})(?!\s*\()/ix,
14
+ drop_table: /drop\s+table\s+(?:if\s+exists\s+)?(#{IDENT})(?!\s*\()/ix,
15
+ alter_table: /alter\s+table\s+(#{IDENT})(?!\s*\()/ix,
16
+ create_table: /create\s+table\s+(?:if\s+not\s+exists\s+)?(#{IDENT})(?!\s*\()/ix,
17
+ from_join: /(?:from|join)\s+(#{IDENT})(?!\s*\()/ix
18
+ }.freeze
19
+
20
+ def parse_tables(sql)
21
+ PATTERNS.flat_map { |_, r| sql.scan(r).flatten }.uniq
22
+ end
23
+ end
24
+ end
@@ -2,6 +2,8 @@
2
2
 
3
3
  module AfterMigrate
4
4
  module Sqlite
5
+ extend Sql
6
+
5
7
  module_function
6
8
 
7
9
  def optimize_tables(connection:, **)
@@ -12,9 +12,9 @@ module AfterMigrate
12
12
  return unless sql
13
13
  return unless sql.match?(/\A\s*(CREATE|ALTER|DROP|INSERT|UPDATE|DELETE|RENAME\s+TABLE|TRUNCATE)/i)
14
14
 
15
- table_names = sql.scan(/(?:from|join|update|into|table)\s+((?:"\w+"|\w+)(?:\.(?:"\w+"|\w+))*)/i).flatten
15
+ table_names = parse_tables(sql)
16
16
  schema ||= fetch_schema
17
- # AfterMigrate.log("[#{schema}] Detected change from '#{sql}' to table: #{table_names}") if table_names.present?
17
+ # AfterMigrate.log("[#{schema}] Detected change from '#{sql}' to tables: #{table_names}") if table_names.present?
18
18
  collect_tables(schema:, table_names:)
19
19
  end
20
20
 
@@ -36,5 +36,20 @@ module AfterMigrate
36
36
  quoted&.delete('"')
37
37
  end
38
38
  end
39
+
40
+ def parse_tables(sql)
41
+ connection = ActiveRecord::Base.connection
42
+ adapter = connection.adapter_name
43
+ case adapter
44
+ when 'PostgreSQL'
45
+ AfterMigrate::Postgresql.parse_tables(sql)
46
+ when 'SQLite'
47
+ AfterMigrate::Sqlite.parse_tables(sql)
48
+ when 'Mysql2', 'Trilogy'
49
+ AfterMigrate::Mysql.parse_tables(sql)
50
+ else
51
+ AfterMigrate.log("No maintenance implemented for #{adapter}")
52
+ end
53
+ end
39
54
  end
40
55
  end
@@ -1,5 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
+ require 'after_migrate/adapters/sql'
3
4
  require 'after_migrate/adapters/mysql'
4
5
  require 'after_migrate/adapters/postgresql'
5
6
  require 'after_migrate/adapters/sqlite'
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module AfterMigrate
4
- VERSION = '0.1.0'
4
+ VERSION = '0.1.1'
5
5
  end
metadata CHANGED
@@ -1,14 +1,29 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: after_migrate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Nikolay Moskvin
8
+ autorequire:
8
9
  bindir: exe
9
10
  cert_chain: []
10
- date: 1980-01-02 00:00:00.000000000 Z
11
+ date: 2025-12-11 00:00:00.000000000 Z
11
12
  dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: pg_query
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '6.1'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '6.1'
12
27
  - !ruby/object:Gem::Dependency
13
28
  name: rails
14
29
  requirement: !ruby/object:Gem::Requirement
@@ -48,6 +63,7 @@ files:
48
63
  - lib/after_migrate.rb
49
64
  - lib/after_migrate/adapters/mysql.rb
50
65
  - lib/after_migrate/adapters/postgresql.rb
66
+ - lib/after_migrate/adapters/sql.rb
51
67
  - lib/after_migrate/adapters/sqlite.rb
52
68
  - lib/after_migrate/collector.rb
53
69
  - lib/after_migrate/current.rb
@@ -63,6 +79,7 @@ metadata:
63
79
  source_code_uri: https://github.com/moskvin/after_migrate
64
80
  changelog_uri: https://github.com/moskvin/after_migrate/blob/master/CHANGELOG.md
65
81
  rubygems_mfa_required: 'true'
82
+ post_install_message:
66
83
  rdoc_options: []
67
84
  require_paths:
68
85
  - lib
@@ -77,7 +94,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
77
94
  - !ruby/object:Gem::Version
78
95
  version: '0'
79
96
  requirements: []
80
- rubygems_version: 3.6.9
97
+ rubygems_version: 3.4.19
98
+ signing_key:
81
99
  specification_version: 4
82
100
  summary: Automatically ANALYZE and VACUUM tables touched during Rails migrations.
83
101
  test_files: []