capture_migration_sql 1.0.4 → 1.0.5
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/CHANGELOG.md +16 -0
- data/README.md +0 -1
- data/VERSION +1 -1
- data/capture_migration_sql.gemspec +8 -4
- data/lib/capture_migration_sql/migration_extension.rb +16 -12
- data/lib/capture_migration_sql/sql_subscriber.rb +24 -6
- data/lib/capture_migration_sql.rb +21 -3
- metadata +10 -25
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 244ae0fce5c5654d09321b61daea560a442e213b395fb532145f611f8622f873
|
|
4
|
+
data.tar.gz: 3bb661d211e3a5bf357cdcd447f7b8516ae48e5a7a3c0b27810bc67db388b5c7
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: df54712d0d2471fe64222635299652c816cee27309ce42cb4a7d783975cac9e6485fcb3aef192e0cd3403e813992117d1a42eb361668c786a622c23322b992f6
|
|
7
|
+
data.tar.gz: b130cec56900275e6e2da6771814fba7cc0f9ce4fc0d87c5f2303980031a8c67085c2200f87f9741ff92f345ef797b3b0b8b53964a38041b6ec5f8e98ea080c7
|
data/CHANGELOG.md
CHANGED
|
@@ -4,6 +4,22 @@ All notable changes to this project will be documented in this file.
|
|
|
4
4
|
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
5
5
|
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
6
6
|
|
|
7
|
+
## 1.0.5
|
|
8
|
+
|
|
9
|
+
### Fixed
|
|
10
|
+
|
|
11
|
+
- SQL files are no longer deleted before a down migration runs; if the down migration fails, the SQL file is kept since the migration is still applied.
|
|
12
|
+
- SQL files are now written to a temporary file and atomically renamed into place, so a process killed mid-migration can no longer leave a permanent, truncated SQL file behind.
|
|
13
|
+
- The migration SQL directory is now created with `FileUtils.mkdir_p`, eliminating a race condition between concurrent migration processes and supporting nested custom directories.
|
|
14
|
+
- Attaching the SQL subscriber is now thread safe, preventing duplicate subscribers (and duplicated SQL output) when migrations run in parallel threads.
|
|
15
|
+
- Ignored statement filters are now applied after stripping leading whitespace, so statements with leading whitespace no longer bypass them.
|
|
16
|
+
- The `INSERT INTO schema_migrations` statement written to SQL files now honors custom schema migrations table names and table name prefixes and suffixes.
|
|
17
|
+
- Connection labels from `using_connection` are no longer written to the SQL file when SQL logging is disabled.
|
|
18
|
+
|
|
19
|
+
### Changed
|
|
20
|
+
|
|
21
|
+
- Rails 5.2 and Ruby 2.6 are the minimum supported versions.
|
|
22
|
+
|
|
7
23
|
## 1.0.4
|
|
8
24
|
|
|
9
25
|
### Fixed
|
data/README.md
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
# Capture Migration SQL
|
|
2
2
|
|
|
3
3
|
[](https://github.com/bdurand/capture_migration_sql/actions/workflows/continuous_integration.yml)
|
|
4
|
-
[](https://github.com/bdurand/capture_migration_sql/actions/workflows/regression_test.yml)
|
|
5
4
|
[](https://github.com/testdouble/standard)
|
|
6
5
|
[](https://badge.fury.io/rb/capture_migration_sql)
|
|
7
6
|
|
data/VERSION
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
1.0.
|
|
1
|
+
1.0.5
|
|
@@ -10,6 +10,12 @@ Gem::Specification.new do |spec|
|
|
|
10
10
|
spec.homepage = "https://github.com/bdurand/capture_migration_sql"
|
|
11
11
|
spec.license = "MIT"
|
|
12
12
|
|
|
13
|
+
spec.metadata = {
|
|
14
|
+
"homepage_uri" => spec.homepage,
|
|
15
|
+
"source_code_uri" => spec.homepage,
|
|
16
|
+
"changelog_uri" => "#{spec.homepage}/blob/main/CHANGELOG.md"
|
|
17
|
+
}
|
|
18
|
+
|
|
13
19
|
# Specify which files should be added to the gem when it is released.
|
|
14
20
|
# The `git ls-files -z` loads the files in the RubyGem that have been added into git.
|
|
15
21
|
ignore_files = %w[
|
|
@@ -27,9 +33,7 @@ Gem::Specification.new do |spec|
|
|
|
27
33
|
|
|
28
34
|
spec.require_paths = ["lib"]
|
|
29
35
|
|
|
30
|
-
spec.add_dependency "activerecord", ">=
|
|
31
|
-
|
|
32
|
-
spec.add_development_dependency "bundler"
|
|
36
|
+
spec.add_dependency "activerecord", ">= 5.2"
|
|
33
37
|
|
|
34
|
-
spec.required_ruby_version = ">= 2.
|
|
38
|
+
spec.required_ruby_version = ">= 2.6"
|
|
35
39
|
end
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
+
require "fileutils"
|
|
4
|
+
|
|
3
5
|
# Extension methods for ActiveRecord::Migration class.
|
|
4
6
|
module CaptureMigrationSql
|
|
5
7
|
module MigrationExtension
|
|
@@ -18,7 +20,7 @@ module CaptureMigrationSql
|
|
|
18
20
|
end
|
|
19
21
|
|
|
20
22
|
# Enable SQL logging. You can call this method within a block where SQL
|
|
21
|
-
# logging was disabled to
|
|
23
|
+
# logging was disabled to re-enable it.
|
|
22
24
|
def enable_sql_logging(&block)
|
|
23
25
|
sql_logging(enabled: true, &block)
|
|
24
26
|
end
|
|
@@ -46,7 +48,7 @@ module CaptureMigrationSql
|
|
|
46
48
|
save_connection = @connection
|
|
47
49
|
begin
|
|
48
50
|
@connection = connection
|
|
49
|
-
stream = CaptureMigrationSql.capture_stream
|
|
51
|
+
stream = CaptureMigrationSql.capture_stream if CaptureMigrationSql.capture_enabled?
|
|
50
52
|
stream.write("-- BEGIN #{label}\n\n") if label && stream
|
|
51
53
|
retval = yield
|
|
52
54
|
stream.write("-- END #{label}\n\n") if label && stream
|
|
@@ -73,21 +75,23 @@ module CaptureMigrationSql
|
|
|
73
75
|
if File.exist?(output_file)
|
|
74
76
|
yield
|
|
75
77
|
else
|
|
76
|
-
|
|
78
|
+
FileUtils.mkdir_p(migration_sql_dir)
|
|
77
79
|
SqlSubscriber.attach_if_necessary
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
80
|
+
temp_file = "#{output_file}.tmp.#{Process.pid}.#{Thread.current.object_id}"
|
|
81
|
+
begin
|
|
82
|
+
retval = File.open(temp_file, "w") do |f|
|
|
83
|
+
capture_migration_sql(f, &block)
|
|
84
|
+
end
|
|
85
|
+
File.rename(temp_file, output_file)
|
|
86
|
+
retval
|
|
83
87
|
ensure
|
|
84
|
-
File.unlink(
|
|
88
|
+
File.unlink(temp_file) if File.exist?(temp_file)
|
|
85
89
|
end
|
|
86
|
-
retval
|
|
87
90
|
end
|
|
88
91
|
else
|
|
92
|
+
retval = yield
|
|
89
93
|
File.unlink(output_file) if output_file && File.exist?(output_file)
|
|
90
|
-
|
|
94
|
+
retval
|
|
91
95
|
end
|
|
92
96
|
end
|
|
93
97
|
|
|
@@ -100,7 +104,7 @@ module CaptureMigrationSql
|
|
|
100
104
|
ensure
|
|
101
105
|
Thread.current[:capture_migration_sql_stream] = save_stream
|
|
102
106
|
end
|
|
103
|
-
f.write("INSERT INTO
|
|
107
|
+
f.write("INSERT INTO #{CaptureMigrationSql.schema_migrations_table_name} (version) VALUES ('#{version.to_i}');\n")
|
|
104
108
|
retval
|
|
105
109
|
end
|
|
106
110
|
end
|
|
@@ -10,16 +10,19 @@ module CaptureMigrationSql
|
|
|
10
10
|
|
|
11
11
|
SHOW_STATEMENT = /\ASHOW\b/i
|
|
12
12
|
EXPLAIN_STATEMENT = /\AEXPLAIN\b/i
|
|
13
|
-
SELECT_SCHEMA_MIGRATIONS = /\ASELECT.*FROM.*schema_migrations/i
|
|
14
13
|
SELECT_INFORMATION_SCHEMA = /\ASELECT.*information_schema/im
|
|
15
14
|
SQLLITE_VERSION = /\ASELECT sqlite_version\(/i
|
|
16
|
-
IGNORE_STATEMENTS = Regexp.union(SHOW_STATEMENT, EXPLAIN_STATEMENT,
|
|
15
|
+
IGNORE_STATEMENTS = Regexp.union(SHOW_STATEMENT, EXPLAIN_STATEMENT, SELECT_INFORMATION_SCHEMA, SQLLITE_VERSION)
|
|
16
|
+
|
|
17
|
+
ATTACH_MUTEX = Mutex.new
|
|
17
18
|
|
|
18
19
|
class << self
|
|
19
20
|
def attach_if_necessary
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
21
|
+
ATTACH_MUTEX.synchronize do
|
|
22
|
+
unless defined?(@attached) && @attached
|
|
23
|
+
attach_to(:active_record)
|
|
24
|
+
@attached = true
|
|
25
|
+
end
|
|
23
26
|
end
|
|
24
27
|
end
|
|
25
28
|
end
|
|
@@ -31,11 +34,26 @@ module CaptureMigrationSql
|
|
|
31
34
|
payload = event.payload
|
|
32
35
|
return if IGNORE_PAYLOAD_NAMES.include?(payload[:name])
|
|
33
36
|
sql = payload[:sql]
|
|
34
|
-
return if sql.nil?
|
|
37
|
+
return if sql.nil?
|
|
35
38
|
|
|
36
39
|
sql = sql.strip
|
|
40
|
+
return if IGNORE_STATEMENTS.match(sql)
|
|
41
|
+
return if schema_migrations_query?(sql)
|
|
42
|
+
|
|
37
43
|
sql = "#{sql};" unless sql.end_with?(";")
|
|
38
44
|
stream.write("#{sql}\n\n")
|
|
39
45
|
end
|
|
46
|
+
|
|
47
|
+
private
|
|
48
|
+
|
|
49
|
+
# Ignore ActiveRecord's own reads of the schema migrations table. The
|
|
50
|
+
# table name is resolved at runtime so that custom table names and any
|
|
51
|
+
# table name prefix or suffix are matched, staying consistent with the
|
|
52
|
+
# name written to the SQL file.
|
|
53
|
+
def schema_migrations_query?(sql)
|
|
54
|
+
table_name = CaptureMigrationSql.schema_migrations_table_name
|
|
55
|
+
return false if table_name.nil? || table_name.empty?
|
|
56
|
+
/\ASELECT.*FROM.*#{Regexp.escape(table_name)}/im.match?(sql)
|
|
57
|
+
end
|
|
40
58
|
end
|
|
41
59
|
end
|
|
@@ -18,7 +18,7 @@ module CaptureMigrationSql
|
|
|
18
18
|
unless ::ActiveRecord::Migration.include?(MigrationExtension)
|
|
19
19
|
::ActiveRecord::Migration.prepend(MigrationExtension)
|
|
20
20
|
end
|
|
21
|
-
@sql_directory =
|
|
21
|
+
@sql_directory = directory || Rails.root + "db" + "migration_sql"
|
|
22
22
|
@starting_with_version = starting_with.to_i
|
|
23
23
|
end
|
|
24
24
|
|
|
@@ -27,7 +27,7 @@ module CaptureMigrationSql
|
|
|
27
27
|
@sql_directory if defined?(@sql_directory)
|
|
28
28
|
end
|
|
29
29
|
|
|
30
|
-
# Return the migration version number to start
|
|
30
|
+
# Return the migration version number to start capturing SQL.
|
|
31
31
|
def starting_with_version
|
|
32
32
|
@starting_with_version if defined?(@starting_with_version)
|
|
33
33
|
end
|
|
@@ -37,9 +37,27 @@ module CaptureMigrationSql
|
|
|
37
37
|
!!Thread.current[:capture_migration_sql_enabled]
|
|
38
38
|
end
|
|
39
39
|
|
|
40
|
-
# Return the
|
|
40
|
+
# Return the stream migration SQL is being written to.
|
|
41
41
|
def capture_stream
|
|
42
42
|
Thread.current[:capture_migration_sql_stream]
|
|
43
43
|
end
|
|
44
|
+
|
|
45
|
+
# Resolve the schema migrations table name so that both the SQL that is
|
|
46
|
+
# written to the file and the statement filter honor custom table names
|
|
47
|
+
# and any table name prefix or suffix. Falls back to "schema_migrations"
|
|
48
|
+
# if the name cannot be determined.
|
|
49
|
+
def schema_migrations_table_name
|
|
50
|
+
if defined?(ActiveRecord::SchemaMigration) && ActiveRecord::SchemaMigration.respond_to?(:table_name)
|
|
51
|
+
ActiveRecord::SchemaMigration.table_name
|
|
52
|
+
else
|
|
53
|
+
connection = ActiveRecord::Base.connection
|
|
54
|
+
schema_migration = if connection.respond_to?(:schema_migration)
|
|
55
|
+
connection.schema_migration
|
|
56
|
+
elsif connection.pool.respond_to?(:schema_migration)
|
|
57
|
+
connection.pool.schema_migration
|
|
58
|
+
end
|
|
59
|
+
schema_migration ? schema_migration.table_name : "schema_migrations"
|
|
60
|
+
end
|
|
61
|
+
end
|
|
44
62
|
end
|
|
45
63
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,13 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: capture_migration_sql
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 1.0.
|
|
4
|
+
version: 1.0.5
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Brian Durand
|
|
8
|
-
autorequire:
|
|
9
8
|
bindir: bin
|
|
10
9
|
cert_chain: []
|
|
11
|
-
date:
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
12
11
|
dependencies:
|
|
13
12
|
- !ruby/object:Gem::Dependency
|
|
14
13
|
name: activerecord
|
|
@@ -16,29 +15,14 @@ dependencies:
|
|
|
16
15
|
requirements:
|
|
17
16
|
- - ">="
|
|
18
17
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '
|
|
18
|
+
version: '5.2'
|
|
20
19
|
type: :runtime
|
|
21
20
|
prerelease: false
|
|
22
21
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
22
|
requirements:
|
|
24
23
|
- - ">="
|
|
25
24
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '
|
|
27
|
-
- !ruby/object:Gem::Dependency
|
|
28
|
-
name: bundler
|
|
29
|
-
requirement: !ruby/object:Gem::Requirement
|
|
30
|
-
requirements:
|
|
31
|
-
- - ">="
|
|
32
|
-
- !ruby/object:Gem::Version
|
|
33
|
-
version: '0'
|
|
34
|
-
type: :development
|
|
35
|
-
prerelease: false
|
|
36
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
37
|
-
requirements:
|
|
38
|
-
- - ">="
|
|
39
|
-
- !ruby/object:Gem::Version
|
|
40
|
-
version: '0'
|
|
41
|
-
description:
|
|
25
|
+
version: '5.2'
|
|
42
26
|
email:
|
|
43
27
|
- bbdurand@gmail.com
|
|
44
28
|
executables: []
|
|
@@ -57,8 +41,10 @@ files:
|
|
|
57
41
|
homepage: https://github.com/bdurand/capture_migration_sql
|
|
58
42
|
licenses:
|
|
59
43
|
- MIT
|
|
60
|
-
metadata:
|
|
61
|
-
|
|
44
|
+
metadata:
|
|
45
|
+
homepage_uri: https://github.com/bdurand/capture_migration_sql
|
|
46
|
+
source_code_uri: https://github.com/bdurand/capture_migration_sql
|
|
47
|
+
changelog_uri: https://github.com/bdurand/capture_migration_sql/blob/main/CHANGELOG.md
|
|
62
48
|
rdoc_options: []
|
|
63
49
|
require_paths:
|
|
64
50
|
- lib
|
|
@@ -66,15 +52,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
66
52
|
requirements:
|
|
67
53
|
- - ">="
|
|
68
54
|
- !ruby/object:Gem::Version
|
|
69
|
-
version: '2.
|
|
55
|
+
version: '2.6'
|
|
70
56
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
71
57
|
requirements:
|
|
72
58
|
- - ">="
|
|
73
59
|
- !ruby/object:Gem::Version
|
|
74
60
|
version: '0'
|
|
75
61
|
requirements: []
|
|
76
|
-
rubygems_version:
|
|
77
|
-
signing_key:
|
|
62
|
+
rubygems_version: 4.0.3
|
|
78
63
|
specification_version: 4
|
|
79
64
|
summary: Capture the SQL that is executed when running ActiveRecord migrations so
|
|
80
65
|
that it can be run in in other environments that don't support migrations.
|