lhm-shopify 4.4.2 → 4.5.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 +4 -4
- data/.github/workflows/test.yml +5 -3
- data/.ruby-version +1 -1
- data/Appraisals +4 -10
- data/CHANGELOG.md +10 -0
- data/Gemfile.lock +25 -17
- data/dev.yml +4 -3
- data/gemfiles/{activerecord_6.1.gemfile → activerecord_7.2.gemfile} +1 -2
- data/gemfiles/{activerecord_6.1.gemfile.lock → activerecord_7.2.gemfile.lock} +36 -22
- data/gemfiles/{activerecord_7.1.gemfile → activerecord_8.0.gemfile} +1 -1
- data/gemfiles/{activerecord_7.1.gemfile.lock → activerecord_8.0.gemfile.lock} +31 -22
- data/gemfiles/activerecord_head.gemfile.lock +27 -19
- data/lhm.gemspec +2 -0
- data/lib/lhm/entangler.rb +1 -1
- data/lib/lhm/intersection.rb +3 -2
- data/lib/lhm/invoker.rb +8 -7
- data/lib/lhm/migration.rb +3 -2
- data/lib/lhm/migrator.rb +15 -5
- data/lib/lhm/sql_retry.rb +1 -0
- data/lib/lhm/throttler/replica_lag.rb +1 -18
- data/lib/lhm/version.rb +1 -1
- data/lib/lhm.rb +2 -2
- data/spec/fixtures/myisam_users.ddl +10 -0
- data/spec/integration/lhm_spec.rb +95 -1
- data/spec/integration/sql_retry/db_connection_helper.rb +1 -1
- data/spec/integration/sql_retry/lock_wait_spec.rb +4 -2
- data/spec/unit/entangler_spec.rb +14 -14
- data/spec/unit/migrator_spec.rb +8 -8
- data/spec/unit/throttler/replica_lag_spec.rb +1 -5
- metadata +36 -12
- data/gemfiles/activerecord_7.0.gemfile +0 -8
- data/gemfiles/activerecord_7.0.gemfile.lock +0 -74
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f6810104b2e7de311501c58b38b5ab605bf808b2391e9406901dd97394ae29c2
|
4
|
+
data.tar.gz: 251bdd83425a0986d5d3cdded7fc05e4d53731eb86269a3059f2524780287b6e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 866539e9bcac6acc7740766524d52e87de8572bde63d336b4dd1636c87da876d178729eaa5e716dafed53339c903ba79677980a0f29346c8ad36e0cebb145e7f
|
7
|
+
data.tar.gz: 0c7840100abf5b849e6750061f269fab888633bba7afd287cad3461e70e941f26f9a7a42fd215effa89797c7841c0b1200aab69d44d1119c79951ef53e8dee98
|
data/.github/workflows/test.yml
CHANGED
@@ -15,17 +15,19 @@ jobs:
|
|
15
15
|
fail-fast: false
|
16
16
|
max-parallel: 8
|
17
17
|
matrix:
|
18
|
-
activerecord: ["
|
18
|
+
activerecord: ["7.2", "8.0", "head"]
|
19
19
|
ruby: ["3.1", "3.2", "3.3", "head"]
|
20
20
|
mysql: ["5.7", "8.0"]
|
21
21
|
adapter: ["mysql2", "trilogy"]
|
22
22
|
exclude:
|
23
23
|
- activerecord: 6.1
|
24
24
|
ruby: head
|
25
|
-
- activerecord: 7.
|
25
|
+
- activerecord: 7.2
|
26
26
|
ruby: head
|
27
|
+
- activerecord: 8.0
|
28
|
+
ruby: 3.1
|
27
29
|
- activerecord: head
|
28
|
-
ruby: 3.
|
30
|
+
ruby: 3.1
|
29
31
|
|
30
32
|
env:
|
31
33
|
BUNDLE_GEMFILE: "${{ github.workspace }}/gemfiles/activerecord_${{ matrix.activerecord }}.gemfile"
|
data/.ruby-version
CHANGED
@@ -1 +1 @@
|
|
1
|
-
3.
|
1
|
+
3.3.6
|
data/Appraisals
CHANGED
@@ -1,15 +1,9 @@
|
|
1
|
-
appraise "activerecord-
|
2
|
-
gem "activerecord", "
|
3
|
-
gem "activerecord-trilogy-adapter"
|
1
|
+
appraise "activerecord-7.2" do
|
2
|
+
gem "activerecord", "7.2.2.1"
|
4
3
|
end
|
5
4
|
|
6
|
-
appraise "activerecord-
|
7
|
-
gem "activerecord", "
|
8
|
-
gem "activerecord-trilogy-adapter"
|
9
|
-
end
|
10
|
-
|
11
|
-
appraise "activerecord-7.1" do
|
12
|
-
gem "activerecord", "7.1.1"
|
5
|
+
appraise "activerecord-8.0" do
|
6
|
+
gem "activerecord", "8.0.1"
|
13
7
|
end
|
14
8
|
|
15
9
|
appraise "activerecord-head" do
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,15 @@
|
|
1
1
|
# Unreleased
|
2
2
|
|
3
|
+
# 4.5.1 (Jul, 2025)
|
4
|
+
* Create update before insert trigger
|
5
|
+
|
6
|
+
# 4.5.0 (Feb, 2025)
|
7
|
+
* Update test matrix to include Rails 8
|
8
|
+
* Add option to force tables to use default engine
|
9
|
+
* Change default algorithm for add/rename/remove column operations
|
10
|
+
* Drop support for ActiveRecord version 6.1, as it has reached EOL
|
11
|
+
* Add support for tables with generated columns
|
12
|
+
|
3
13
|
# 4.4.2 (Sep, 2024)
|
4
14
|
* Allow caller to set the algorithm that will be used for DDL ALTER TABLE operations
|
5
15
|
|
data/Gemfile.lock
CHANGED
@@ -1,20 +1,21 @@
|
|
1
1
|
PATH
|
2
2
|
remote: .
|
3
3
|
specs:
|
4
|
-
lhm-shopify (4.
|
4
|
+
lhm-shopify (4.5.1)
|
5
5
|
retriable (>= 3.0.0)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
-
activemodel (
|
11
|
-
activesupport (=
|
12
|
-
activerecord (
|
13
|
-
activemodel (=
|
14
|
-
activesupport (=
|
10
|
+
activemodel (8.0.1)
|
11
|
+
activesupport (= 8.0.1)
|
12
|
+
activerecord (8.0.1)
|
13
|
+
activemodel (= 8.0.1)
|
14
|
+
activesupport (= 8.0.1)
|
15
15
|
timeout (>= 0.4.0)
|
16
|
-
activesupport (
|
16
|
+
activesupport (8.0.1)
|
17
17
|
base64
|
18
|
+
benchmark (>= 0.3)
|
18
19
|
bigdecimal
|
19
20
|
concurrent-ruby (~> 1.0, >= 1.3.1)
|
20
21
|
connection_pool (>= 2.2.5)
|
@@ -24,45 +25,50 @@ GEM
|
|
24
25
|
minitest (>= 5.1)
|
25
26
|
securerandom (>= 0.3)
|
26
27
|
tzinfo (~> 2.0, >= 2.0.5)
|
28
|
+
uri (>= 0.13.1)
|
27
29
|
after_do (0.4.0)
|
28
30
|
appraisal (2.5.0)
|
29
31
|
bundler
|
30
32
|
rake
|
31
33
|
thor (>= 0.14.0)
|
32
34
|
base64 (0.2.0)
|
33
|
-
|
35
|
+
benchmark (0.4.0)
|
36
|
+
bigdecimal (3.1.9)
|
34
37
|
byebug (11.1.3)
|
35
|
-
concurrent-ruby (1.3.
|
36
|
-
connection_pool (2.
|
38
|
+
concurrent-ruby (1.3.5)
|
39
|
+
connection_pool (2.5.0)
|
37
40
|
docile (1.4.1)
|
38
41
|
drb (2.2.1)
|
39
|
-
i18n (1.14.
|
42
|
+
i18n (1.14.7)
|
40
43
|
concurrent-ruby (~> 1.0)
|
41
|
-
logger (1.6.
|
42
|
-
minitest (5.25.
|
44
|
+
logger (1.6.5)
|
45
|
+
minitest (5.25.4)
|
43
46
|
mocha (2.4.5)
|
44
47
|
ruby2_keywords (>= 0.0.5)
|
45
48
|
mysql2 (0.5.6)
|
49
|
+
ostruct (0.6.1)
|
46
50
|
rake (13.2.1)
|
47
51
|
retriable (3.1.2)
|
48
52
|
ruby2_keywords (0.0.5)
|
49
|
-
securerandom (0.
|
53
|
+
securerandom (0.4.1)
|
50
54
|
simplecov (0.22.0)
|
51
55
|
docile (~> 1.1)
|
52
56
|
simplecov-html (~> 0.11)
|
53
57
|
simplecov_json_formatter (~> 0.1)
|
54
58
|
simplecov-html (0.12.3)
|
55
59
|
simplecov_json_formatter (0.1.4)
|
56
|
-
thor (1.3.
|
57
|
-
timeout (0.4.
|
60
|
+
thor (1.3.2)
|
61
|
+
timeout (0.4.3)
|
58
62
|
toxiproxy (2.0.2)
|
59
63
|
trilogy (2.8.1)
|
60
64
|
tzinfo (2.0.6)
|
61
65
|
concurrent-ruby (~> 1.0)
|
66
|
+
uri (1.0.2)
|
62
67
|
|
63
68
|
PLATFORMS
|
64
69
|
arm64-darwin-21
|
65
70
|
arm64-darwin-22
|
71
|
+
arm64-darwin-23
|
66
72
|
x86_64-darwin-20
|
67
73
|
x86_64-linux
|
68
74
|
|
@@ -72,13 +78,15 @@ DEPENDENCIES
|
|
72
78
|
appraisal
|
73
79
|
byebug
|
74
80
|
lhm-shopify!
|
81
|
+
logger
|
75
82
|
minitest
|
76
83
|
mocha
|
77
84
|
mysql2
|
85
|
+
ostruct
|
78
86
|
rake
|
79
87
|
simplecov
|
80
88
|
toxiproxy
|
81
89
|
trilogy
|
82
90
|
|
83
91
|
BUNDLED WITH
|
84
|
-
2.
|
92
|
+
2.6.3
|
data/dev.yml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
name: lhm
|
2
2
|
up:
|
3
3
|
- packages:
|
4
|
-
- mysql-client
|
4
|
+
- mysql-client
|
5
5
|
- wget
|
6
6
|
- ruby
|
7
7
|
- bundler
|
@@ -12,8 +12,9 @@ up:
|
|
12
12
|
meet: ":"
|
13
13
|
- custom:
|
14
14
|
name: Podman compose
|
15
|
-
met?: podman-compose ps | grep -
|
16
|
-
meet: podman-compose up -d
|
15
|
+
met?: "[[ $(podman-compose ps | grep -c -e 'running' -e 'Up') == 4 ]] 2> /dev/null"
|
16
|
+
meet: podman-compose -f docker-compose-mysql-8.0.yml up -d
|
17
|
+
down: podman-compose down
|
17
18
|
- custom:
|
18
19
|
name: Waiting for DBs to be operational
|
19
20
|
met?: ./scripts/helpers/wait-for-dbs.sh
|
@@ -1,76 +1,90 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
lhm-shopify (4.
|
4
|
+
lhm-shopify (4.5.1)
|
5
5
|
retriable (>= 3.0.0)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
-
activemodel (
|
11
|
-
activesupport (=
|
12
|
-
activerecord (
|
13
|
-
activemodel (=
|
14
|
-
activesupport (=
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
10
|
+
activemodel (7.2.2.1)
|
11
|
+
activesupport (= 7.2.2.1)
|
12
|
+
activerecord (7.2.2.1)
|
13
|
+
activemodel (= 7.2.2.1)
|
14
|
+
activesupport (= 7.2.2.1)
|
15
|
+
timeout (>= 0.4.0)
|
16
|
+
activesupport (7.2.2.1)
|
17
|
+
base64
|
18
|
+
benchmark (>= 0.3)
|
19
|
+
bigdecimal
|
20
|
+
concurrent-ruby (~> 1.0, >= 1.3.1)
|
21
|
+
connection_pool (>= 2.2.5)
|
22
|
+
drb
|
20
23
|
i18n (>= 1.6, < 2)
|
24
|
+
logger (>= 1.4.2)
|
21
25
|
minitest (>= 5.1)
|
22
|
-
|
23
|
-
|
26
|
+
securerandom (>= 0.3)
|
27
|
+
tzinfo (~> 2.0, >= 2.0.5)
|
24
28
|
after_do (0.4.0)
|
25
29
|
appraisal (2.5.0)
|
26
30
|
bundler
|
27
31
|
rake
|
28
32
|
thor (>= 0.14.0)
|
33
|
+
base64 (0.2.0)
|
34
|
+
benchmark (0.4.0)
|
35
|
+
bigdecimal (3.1.9)
|
29
36
|
byebug (11.1.3)
|
30
|
-
concurrent-ruby (1.
|
37
|
+
concurrent-ruby (1.3.5)
|
38
|
+
connection_pool (2.5.0)
|
31
39
|
docile (1.4.0)
|
32
|
-
|
40
|
+
drb (2.2.1)
|
41
|
+
i18n (1.14.7)
|
33
42
|
concurrent-ruby (~> 1.0)
|
34
|
-
|
43
|
+
logger (1.6.5)
|
44
|
+
minitest (5.25.4)
|
35
45
|
mocha (2.1.0)
|
36
46
|
ruby2_keywords (>= 0.0.5)
|
37
47
|
mysql2 (0.5.5)
|
48
|
+
ostruct (0.6.1)
|
38
49
|
rake (13.0.6)
|
39
50
|
retriable (3.1.2)
|
40
51
|
ruby2_keywords (0.0.5)
|
52
|
+
securerandom (0.4.1)
|
41
53
|
simplecov (0.22.0)
|
42
54
|
docile (~> 1.1)
|
43
55
|
simplecov-html (~> 0.11)
|
44
56
|
simplecov_json_formatter (~> 0.1)
|
45
57
|
simplecov-html (0.12.3)
|
46
58
|
simplecov_json_formatter (0.1.4)
|
47
|
-
thor (1.
|
59
|
+
thor (1.3.2)
|
60
|
+
timeout (0.4.3)
|
48
61
|
toxiproxy (2.0.2)
|
49
|
-
trilogy (2.
|
62
|
+
trilogy (2.9.0)
|
50
63
|
tzinfo (2.0.6)
|
51
64
|
concurrent-ruby (~> 1.0)
|
52
|
-
zeitwerk (2.6.12)
|
53
65
|
|
54
66
|
PLATFORMS
|
55
67
|
arm64-darwin-21
|
56
68
|
arm64-darwin-22
|
69
|
+
arm64-darwin-23
|
57
70
|
x86_64-darwin-20
|
58
71
|
x86_64-linux
|
59
72
|
|
60
73
|
DEPENDENCIES
|
61
|
-
activerecord (=
|
62
|
-
activerecord-trilogy-adapter
|
74
|
+
activerecord (= 7.2.2.1)
|
63
75
|
after_do
|
64
76
|
appraisal
|
65
77
|
byebug
|
66
78
|
lhm-shopify!
|
79
|
+
logger
|
67
80
|
minitest
|
68
81
|
mocha
|
69
82
|
mysql2
|
83
|
+
ostruct
|
70
84
|
rake
|
71
85
|
simplecov
|
72
86
|
toxiproxy
|
73
87
|
trilogy
|
74
88
|
|
75
89
|
BUNDLED WITH
|
76
|
-
2.
|
90
|
+
2.6.3
|
@@ -1,83 +1,92 @@
|
|
1
1
|
PATH
|
2
2
|
remote: ..
|
3
3
|
specs:
|
4
|
-
lhm-shopify (4.
|
4
|
+
lhm-shopify (4.5.1)
|
5
5
|
retriable (>= 3.0.0)
|
6
6
|
|
7
7
|
GEM
|
8
8
|
remote: https://rubygems.org/
|
9
9
|
specs:
|
10
|
-
activemodel (
|
11
|
-
activesupport (=
|
12
|
-
activerecord (
|
13
|
-
activemodel (=
|
14
|
-
activesupport (=
|
10
|
+
activemodel (8.0.1)
|
11
|
+
activesupport (= 8.0.1)
|
12
|
+
activerecord (8.0.1)
|
13
|
+
activemodel (= 8.0.1)
|
14
|
+
activesupport (= 8.0.1)
|
15
15
|
timeout (>= 0.4.0)
|
16
|
-
activesupport (
|
16
|
+
activesupport (8.0.1)
|
17
17
|
base64
|
18
|
+
benchmark (>= 0.3)
|
18
19
|
bigdecimal
|
19
|
-
concurrent-ruby (~> 1.0, >= 1.
|
20
|
+
concurrent-ruby (~> 1.0, >= 1.3.1)
|
20
21
|
connection_pool (>= 2.2.5)
|
21
22
|
drb
|
22
23
|
i18n (>= 1.6, < 2)
|
24
|
+
logger (>= 1.4.2)
|
23
25
|
minitest (>= 5.1)
|
24
|
-
|
25
|
-
tzinfo (~> 2.0)
|
26
|
+
securerandom (>= 0.3)
|
27
|
+
tzinfo (~> 2.0, >= 2.0.5)
|
28
|
+
uri (>= 0.13.1)
|
26
29
|
after_do (0.4.0)
|
27
30
|
appraisal (2.5.0)
|
28
31
|
bundler
|
29
32
|
rake
|
30
33
|
thor (>= 0.14.0)
|
31
|
-
base64 (0.
|
32
|
-
|
34
|
+
base64 (0.2.0)
|
35
|
+
benchmark (0.4.0)
|
36
|
+
bigdecimal (3.1.9)
|
33
37
|
byebug (11.1.3)
|
34
|
-
concurrent-ruby (1.
|
35
|
-
connection_pool (2.
|
38
|
+
concurrent-ruby (1.3.5)
|
39
|
+
connection_pool (2.5.0)
|
36
40
|
docile (1.4.0)
|
37
|
-
drb (2.
|
38
|
-
ruby2_keywords
|
41
|
+
drb (2.2.1)
|
39
42
|
i18n (1.14.1)
|
40
43
|
concurrent-ruby (~> 1.0)
|
44
|
+
logger (1.6.1)
|
41
45
|
minitest (5.22.2)
|
42
46
|
mocha (2.1.0)
|
43
47
|
ruby2_keywords (>= 0.0.5)
|
44
|
-
mutex_m (0.1.2)
|
45
48
|
mysql2 (0.5.5)
|
49
|
+
ostruct (0.6.1)
|
46
50
|
rake (13.0.6)
|
47
51
|
retriable (3.1.2)
|
48
52
|
ruby2_keywords (0.0.5)
|
53
|
+
securerandom (0.4.1)
|
49
54
|
simplecov (0.22.0)
|
50
55
|
docile (~> 1.1)
|
51
56
|
simplecov-html (~> 0.11)
|
52
57
|
simplecov_json_formatter (~> 0.1)
|
53
58
|
simplecov-html (0.12.3)
|
54
59
|
simplecov_json_formatter (0.1.4)
|
55
|
-
thor (1.
|
56
|
-
timeout (0.4.
|
60
|
+
thor (1.3.2)
|
61
|
+
timeout (0.4.3)
|
57
62
|
toxiproxy (2.0.2)
|
58
|
-
trilogy (2.
|
63
|
+
trilogy (2.9.0)
|
59
64
|
tzinfo (2.0.6)
|
60
65
|
concurrent-ruby (~> 1.0)
|
66
|
+
uri (1.0.2)
|
61
67
|
|
62
68
|
PLATFORMS
|
63
69
|
arm64-darwin-21
|
64
70
|
arm64-darwin-22
|
71
|
+
arm64-darwin-23
|
65
72
|
x86_64-darwin-20
|
66
73
|
x86_64-linux
|
67
74
|
|
68
75
|
DEPENDENCIES
|
69
|
-
activerecord (=
|
76
|
+
activerecord (= 8.0.1)
|
70
77
|
after_do
|
71
78
|
appraisal
|
72
79
|
byebug
|
73
80
|
lhm-shopify!
|
81
|
+
logger
|
74
82
|
minitest
|
75
83
|
mocha
|
76
84
|
mysql2
|
85
|
+
ostruct
|
77
86
|
rake
|
78
87
|
simplecov
|
79
88
|
toxiproxy
|
80
89
|
trilogy
|
81
90
|
|
82
91
|
BUNDLED WITH
|
83
|
-
2.
|
92
|
+
2.6.3
|
@@ -1,16 +1,17 @@
|
|
1
1
|
GIT
|
2
2
|
remote: https://github.com/rails/rails.git
|
3
|
-
revision:
|
3
|
+
revision: bdad2707835949a96dd29e747b8c324593efd4d8
|
4
4
|
branch: main
|
5
5
|
specs:
|
6
|
-
activemodel (8.
|
7
|
-
activesupport (= 8.
|
8
|
-
activerecord (8.
|
9
|
-
activemodel (= 8.
|
10
|
-
activesupport (= 8.
|
6
|
+
activemodel (8.1.0.alpha)
|
7
|
+
activesupport (= 8.1.0.alpha)
|
8
|
+
activerecord (8.1.0.alpha)
|
9
|
+
activemodel (= 8.1.0.alpha)
|
10
|
+
activesupport (= 8.1.0.alpha)
|
11
11
|
timeout (>= 0.4.0)
|
12
|
-
activesupport (8.
|
12
|
+
activesupport (8.1.0.alpha)
|
13
13
|
base64
|
14
|
+
benchmark (>= 0.3)
|
14
15
|
bigdecimal
|
15
16
|
concurrent-ruby (~> 1.0, >= 1.3.1)
|
16
17
|
connection_pool (>= 2.2.5)
|
@@ -20,11 +21,12 @@ GIT
|
|
20
21
|
minitest (>= 5.1)
|
21
22
|
securerandom (>= 0.3)
|
22
23
|
tzinfo (~> 2.0, >= 2.0.5)
|
24
|
+
uri (>= 0.13.1)
|
23
25
|
|
24
26
|
PATH
|
25
27
|
remote: ..
|
26
28
|
specs:
|
27
|
-
lhm-shopify (4.
|
29
|
+
lhm-shopify (4.5.1)
|
28
30
|
retriable (>= 3.0.0)
|
29
31
|
|
30
32
|
GEM
|
@@ -36,38 +38,42 @@ GEM
|
|
36
38
|
rake
|
37
39
|
thor (>= 0.14.0)
|
38
40
|
base64 (0.2.0)
|
39
|
-
|
41
|
+
benchmark (0.4.0)
|
42
|
+
bigdecimal (3.1.9)
|
40
43
|
byebug (11.1.3)
|
41
|
-
concurrent-ruby (1.3.
|
42
|
-
connection_pool (2.
|
44
|
+
concurrent-ruby (1.3.5)
|
45
|
+
connection_pool (2.5.0)
|
43
46
|
docile (1.4.1)
|
44
47
|
drb (2.2.1)
|
45
|
-
i18n (1.14.
|
48
|
+
i18n (1.14.7)
|
46
49
|
concurrent-ruby (~> 1.0)
|
47
|
-
logger (1.6.
|
48
|
-
minitest (5.
|
50
|
+
logger (1.6.5)
|
51
|
+
minitest (5.25.4)
|
49
52
|
mocha (2.4.5)
|
50
53
|
ruby2_keywords (>= 0.0.5)
|
51
54
|
mysql2 (0.5.6)
|
55
|
+
ostruct (0.6.1)
|
52
56
|
rake (13.2.1)
|
53
57
|
retriable (3.1.2)
|
54
58
|
ruby2_keywords (0.0.5)
|
55
|
-
securerandom (0.
|
59
|
+
securerandom (0.4.1)
|
56
60
|
simplecov (0.22.0)
|
57
61
|
docile (~> 1.1)
|
58
62
|
simplecov-html (~> 0.11)
|
59
63
|
simplecov_json_formatter (~> 0.1)
|
60
64
|
simplecov-html (0.12.3)
|
61
65
|
simplecov_json_formatter (0.1.4)
|
62
|
-
thor (1.3.
|
63
|
-
timeout (0.4.
|
66
|
+
thor (1.3.2)
|
67
|
+
timeout (0.4.3)
|
64
68
|
toxiproxy (2.0.2)
|
65
|
-
trilogy (2.
|
69
|
+
trilogy (2.9.0)
|
66
70
|
tzinfo (2.0.6)
|
67
71
|
concurrent-ruby (~> 1.0)
|
72
|
+
uri (1.0.2)
|
68
73
|
|
69
74
|
PLATFORMS
|
70
75
|
arm64-darwin-22
|
76
|
+
arm64-darwin-23
|
71
77
|
x86_64-linux
|
72
78
|
|
73
79
|
DEPENDENCIES
|
@@ -76,13 +82,15 @@ DEPENDENCIES
|
|
76
82
|
appraisal
|
77
83
|
byebug
|
78
84
|
lhm-shopify!
|
85
|
+
logger
|
79
86
|
minitest
|
80
87
|
mocha
|
81
88
|
mysql2
|
89
|
+
ostruct
|
82
90
|
rake
|
83
91
|
simplecov
|
84
92
|
toxiproxy
|
85
93
|
trilogy
|
86
94
|
|
87
95
|
BUNDLED WITH
|
88
|
-
2.
|
96
|
+
2.6.3
|
data/lhm.gemspec
CHANGED
data/lib/lhm/entangler.rb
CHANGED
data/lib/lhm/intersection.rb
CHANGED
@@ -4,10 +4,11 @@
|
|
4
4
|
module Lhm
|
5
5
|
# Determine and format columns common to origin and destination.
|
6
6
|
class Intersection
|
7
|
-
def initialize(origin, destination, renames = {})
|
7
|
+
def initialize(origin, destination, renames = {}, generated_column_names = [])
|
8
8
|
@origin = origin
|
9
9
|
@destination = destination
|
10
10
|
@renames = renames
|
11
|
+
@generated_column_names = generated_column_names
|
11
12
|
end
|
12
13
|
|
13
14
|
def origin
|
@@ -21,7 +22,7 @@ module Lhm
|
|
21
22
|
private
|
22
23
|
|
23
24
|
def common
|
24
|
-
(@origin.columns.keys & @destination.columns.keys).sort
|
25
|
+
((@origin.columns.keys & @destination.columns.keys) - @generated_column_names).sort
|
25
26
|
end
|
26
27
|
|
27
28
|
module Joiners
|
data/lib/lhm/invoker.rb
CHANGED
@@ -21,9 +21,11 @@ module Lhm
|
|
21
21
|
|
22
22
|
attr_reader :migrator, :connection
|
23
23
|
|
24
|
-
def initialize(origin, connection)
|
24
|
+
def initialize(origin, connection, options = {})
|
25
25
|
@connection = connection
|
26
|
-
@migrator = Migrator.new(origin, connection)
|
26
|
+
@migrator = Migrator.new(origin, connection, options)
|
27
|
+
@options = options
|
28
|
+
normalize_options(@options)
|
27
29
|
end
|
28
30
|
|
29
31
|
def set_session_lock_wait_timeouts
|
@@ -45,17 +47,16 @@ module Lhm
|
|
45
47
|
end
|
46
48
|
end
|
47
49
|
|
48
|
-
def run
|
49
|
-
normalize_options(options)
|
50
|
+
def run
|
50
51
|
set_session_lock_wait_timeouts
|
51
52
|
migration = @migrator.run
|
52
53
|
entangler = Entangler.new(migration, @connection)
|
53
54
|
|
54
55
|
entangler.run do
|
55
|
-
options[:verifier] ||= Proc.new { |conn| triggers_still_exist?(conn, entangler) }
|
56
|
-
Chunker.new(migration, @connection, options).run
|
56
|
+
@options[:verifier] ||= Proc.new { |conn| triggers_still_exist?(conn, entangler) }
|
57
|
+
Chunker.new(migration, @connection, @options).run
|
57
58
|
raise "Required triggers do not exist" unless triggers_still_exist?(@connection, entangler)
|
58
|
-
if options[:atomic_switch]
|
59
|
+
if @options[:atomic_switch]
|
59
60
|
AtomicSwitcher.new(migration, @connection).run
|
60
61
|
else
|
61
62
|
LockedSwitcher.new(migration, @connection).run
|
data/lib/lhm/migration.rb
CHANGED
@@ -8,12 +8,13 @@ module Lhm
|
|
8
8
|
class Migration
|
9
9
|
attr_reader :origin, :destination, :conditions, :renames
|
10
10
|
|
11
|
-
def initialize(origin, destination, conditions = nil, renames = {}, time = Time.now)
|
11
|
+
def initialize(origin, destination, conditions = nil, renames = {}, time = Time.now, generated_column_names = [])
|
12
12
|
@origin = origin
|
13
13
|
@destination = destination
|
14
14
|
@conditions = conditions
|
15
15
|
@renames = renames
|
16
16
|
@table_name = TableName.new(@origin.name, time)
|
17
|
+
@generated_column_names = generated_column_names
|
17
18
|
end
|
18
19
|
|
19
20
|
def archive_name
|
@@ -21,7 +22,7 @@ module Lhm
|
|
21
22
|
end
|
22
23
|
|
23
24
|
def intersection
|
24
|
-
Intersection.new(@origin, @destination, @renames)
|
25
|
+
Intersection.new(@origin, @destination, @renames, @generated_column_names)
|
25
26
|
end
|
26
27
|
|
27
28
|
def origin_name
|
data/lib/lhm/migrator.rb
CHANGED
@@ -15,12 +15,13 @@ module Lhm
|
|
15
15
|
|
16
16
|
attr_reader :name, :statements, :connection, :conditions, :renames, :origin
|
17
17
|
|
18
|
-
def initialize(table, connection = nil)
|
18
|
+
def initialize(table, connection = nil, options = {})
|
19
19
|
@connection = connection
|
20
20
|
@origin = table
|
21
21
|
@name = table.destination_name
|
22
22
|
@statements = []
|
23
23
|
@renames = {}
|
24
|
+
@options = options
|
24
25
|
end
|
25
26
|
|
26
27
|
# Alter a table with a custom statement
|
@@ -55,7 +56,7 @@ module Lhm
|
|
55
56
|
# @param [String] name Name of the column to add
|
56
57
|
# @param [String] definition Valid SQL column definition
|
57
58
|
# @param [String] algorithm Algorithm that will be used in the DDL operation
|
58
|
-
def add_column(name, definition, algorithm: '
|
59
|
+
def add_column(name, definition, algorithm: 'COPY')
|
59
60
|
ddl('alter table `%s` add column `%s` %s' % [@name, name, definition], algorithm:)
|
60
61
|
end
|
61
62
|
|
@@ -88,7 +89,7 @@ module Lhm
|
|
88
89
|
# @param [String] old Name of the column to change
|
89
90
|
# @param [String] nu New name to use for the column
|
90
91
|
# @param [String] algorithm Algorithm that will be used in the DDL operation
|
91
|
-
def rename_column(old, nu, algorithm: '
|
92
|
+
def rename_column(old, nu, algorithm: 'COPY')
|
92
93
|
col = @origin.columns[old.to_s]
|
93
94
|
|
94
95
|
definition = col[:type]
|
@@ -112,7 +113,7 @@ module Lhm
|
|
112
113
|
#
|
113
114
|
# @param [String] name Name of the column to delete
|
114
115
|
# @param [String] algorithm Algorithm that will be used in the DDL operation
|
115
|
-
def remove_column(name, algorithm: '
|
116
|
+
def remove_column(name, algorithm: 'COPY')
|
116
117
|
ddl('alter table `%s` drop `%s`' % [@name, name], algorithm:)
|
117
118
|
end
|
118
119
|
|
@@ -215,13 +216,22 @@ module Lhm
|
|
215
216
|
@statements.each do |stmt|
|
216
217
|
@connection.execute(tagged(stmt))
|
217
218
|
end
|
218
|
-
Migration.new(@origin, destination_read, conditions, renames)
|
219
|
+
Migration.new(@origin, destination_read, conditions, renames, Time.now, generated_column_names)
|
220
|
+
end
|
221
|
+
|
222
|
+
def generated_column_names
|
223
|
+
@connection.columns(@origin.name).select(&:virtual?).map(&:name)
|
219
224
|
end
|
220
225
|
|
221
226
|
def destination_create
|
222
227
|
original = %{CREATE TABLE `#{ @origin.name }`}
|
223
228
|
replacement = %{CREATE TABLE `#{ @origin.destination_name }`}
|
224
229
|
stmt = @origin.ddl.gsub(original, replacement)
|
230
|
+
|
231
|
+
if @options[:force_default_engine]
|
232
|
+
stmt = stmt.sub(/ENGINE=\w+\s/, "")
|
233
|
+
end
|
234
|
+
|
225
235
|
@connection.execute(tagged(stmt))
|
226
236
|
|
227
237
|
Lhm.logger.info("Created destination table #{@origin.destination_name}")
|
data/lib/lhm/sql_retry.rb
CHANGED
@@ -134,7 +134,7 @@ module Lhm
|
|
134
134
|
raise ArgumentError, "Expected #{config_proc.inspect} to respond to `call`"
|
135
135
|
end
|
136
136
|
else
|
137
|
-
db_config
|
137
|
+
ActiveRecord::Base.connection_pool.db_config.configuration_hash.dup
|
138
138
|
end
|
139
139
|
config.deep_symbolize_keys!
|
140
140
|
config[:host] = @host
|
@@ -147,23 +147,6 @@ module Lhm
|
|
147
147
|
Lhm.logger.info "Unable to connect and/or query #{host}: #{e}"
|
148
148
|
[nil]
|
149
149
|
end
|
150
|
-
|
151
|
-
private
|
152
|
-
|
153
|
-
def db_config
|
154
|
-
if ar_supports_db_config?
|
155
|
-
ActiveRecord::Base.connection_pool.db_config.configuration_hash.dup
|
156
|
-
else
|
157
|
-
ActiveRecord::Base.connection_pool.spec.config.dup
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
def ar_supports_db_config?
|
162
|
-
# https://api.rubyonrails.org/v6.0/classes/ActiveRecord/ConnectionAdapters/ConnectionPool.html <-- has spec
|
163
|
-
# vs
|
164
|
-
# https://api.rubyonrails.org/v6.1/classes/ActiveRecord/ConnectionAdapters/ConnectionPool.html <-- has db_config
|
165
|
-
ActiveRecord::VERSION::MAJOR > 6 || ActiveRecord::VERSION::MAJOR == 6 && ActiveRecord::VERSION::MINOR >= 1
|
166
|
-
end
|
167
150
|
end
|
168
151
|
end
|
169
152
|
end
|
data/lib/lhm/version.rb
CHANGED
data/lib/lhm.rb
CHANGED
@@ -54,9 +54,9 @@ module Lhm
|
|
54
54
|
def change_table(table_name, options = {}, &block)
|
55
55
|
with_flags(options) do
|
56
56
|
origin = Table.parse(table_name, connection)
|
57
|
-
invoker = Invoker.new(origin, connection)
|
57
|
+
invoker = Invoker.new(origin, connection, options)
|
58
58
|
block.call(invoker.migrator)
|
59
|
-
invoker.run
|
59
|
+
invoker.run
|
60
60
|
true
|
61
61
|
end
|
62
62
|
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
CREATE TABLE `myisam_users` (
|
2
|
+
`id` int(11) NOT NULL AUTO_INCREMENT,
|
3
|
+
`reference` int(11) DEFAULT NULL,
|
4
|
+
`username` varchar(255) DEFAULT NULL,
|
5
|
+
`group` varchar(255) DEFAULT 'Superfriends',
|
6
|
+
`created_at` datetime DEFAULT NULL,
|
7
|
+
`comment` varchar(20) DEFAULT NULL,
|
8
|
+
`description` text,
|
9
|
+
PRIMARY KEY (`id`)
|
10
|
+
) ENGINE=MyISAM CHARSET=utf8
|
@@ -531,6 +531,61 @@ describe Lhm do
|
|
531
531
|
end
|
532
532
|
end
|
533
533
|
|
534
|
+
it 'works when table has generated columns' do
|
535
|
+
table_create(:users)
|
536
|
+
execute("insert into `users` set id = 1, `username` = 'memyself'")
|
537
|
+
execute("insert into `users` set id = 2, `username` = 'youyourself'")
|
538
|
+
|
539
|
+
# Add a generated column
|
540
|
+
Lhm.change_table(:users) do |t|
|
541
|
+
t.add_column(:sample_generated_column, 'VARCHAR(255) GENERATED ALWAYS AS (SUBSTRING(`username`, -2))')
|
542
|
+
end
|
543
|
+
|
544
|
+
# Without the handling of generated columns
|
545
|
+
Lhm::Migrator.any_instance.stubs(:generated_column_names).returns([])
|
546
|
+
# without the Migration passing in generated columns to Intersection, we observe an error as an attempt to write
|
547
|
+
# directly into generated columns will fail.
|
548
|
+
exception = assert_raises ActiveRecord::StatementInvalid do
|
549
|
+
Lhm.change_table(:users) do |t|
|
550
|
+
t.add_column(:sample_additional_column, "VARCHAR(255)")
|
551
|
+
end
|
552
|
+
end
|
553
|
+
assert_match "The value specified for generated column 'sample_generated_column' in table 'lhmn_users' is not allowed.", exception.message
|
554
|
+
|
555
|
+
Lhm.cleanup(true)
|
556
|
+
|
557
|
+
# With the handling of generated columns
|
558
|
+
Lhm::Migrator.any_instance.unstub(:generated_column_names)
|
559
|
+
# As we are now skipping the writing to generated columns, this migration should succeed
|
560
|
+
Lhm.change_table(:users) do |t|
|
561
|
+
t.add_column(:sample_additional_column, "VARCHAR(255)")
|
562
|
+
end
|
563
|
+
|
564
|
+
replica do
|
565
|
+
# new column is added
|
566
|
+
value(table_read(:users).columns['sample_additional_column']).must_equal({
|
567
|
+
:type => 'varchar(255)',
|
568
|
+
:is_nullable => 'YES',
|
569
|
+
:column_default => nil,
|
570
|
+
:comment => '',
|
571
|
+
:collate => collation,
|
572
|
+
})
|
573
|
+
|
574
|
+
# generated column remains intact
|
575
|
+
value(table_read(:users).columns['sample_generated_column']).must_equal({
|
576
|
+
:type => 'varchar(255)',
|
577
|
+
:is_nullable => 'YES',
|
578
|
+
:column_default => nil,
|
579
|
+
:comment => '',
|
580
|
+
:collate => collation,
|
581
|
+
})
|
582
|
+
end
|
583
|
+
|
584
|
+
result = select_one('SELECT sample_generated_column FROM users')
|
585
|
+
# generated column populated appropriately
|
586
|
+
assert_match "lf", result["sample_generated_column"]
|
587
|
+
end
|
588
|
+
|
534
589
|
it 'works when mysql reserved words are used' do
|
535
590
|
table_create(:lines)
|
536
591
|
execute("insert into `lines` set id = 1, `between` = 'foo'")
|
@@ -553,6 +608,39 @@ describe Lhm do
|
|
553
608
|
end
|
554
609
|
end
|
555
610
|
|
611
|
+
it 'creates the shadow table with the default engine when the `force_default_engine` option is used' do
|
612
|
+
table_create(:myisam_users)
|
613
|
+
|
614
|
+
engine = select_value("SELECT ENGINE FROM information_schema.TABLES WHERE TABLE_NAME = 'myisam_users'")
|
615
|
+
value(engine).must_equal("MyISAM")
|
616
|
+
|
617
|
+
Lhm.change_table(:myisam_users) do |t|
|
618
|
+
t.add_column(:logins, "INT(12) DEFAULT '0'", algorithm: "COPY")
|
619
|
+
end
|
620
|
+
|
621
|
+
engine = select_value("SELECT ENGINE FROM information_schema.TABLES WHERE TABLE_NAME = 'myisam_users'")
|
622
|
+
value(engine).must_equal("MyISAM")
|
623
|
+
|
624
|
+
Lhm.change_table(:myisam_users, force_default_engine: true) do |t|
|
625
|
+
t.remove_column(:logins)
|
626
|
+
end
|
627
|
+
|
628
|
+
engine = select_value("SELECT ENGINE FROM information_schema.TABLES WHERE TABLE_NAME = 'myisam_users'")
|
629
|
+
value(engine).must_equal("InnoDB")
|
630
|
+
end
|
631
|
+
|
632
|
+
it "should not fail using the default algorithms when changing tables with fulltext indexes" do
|
633
|
+
table_create(:users)
|
634
|
+
execute("DROP INDEX `index_with_a_custom_name` ON `users`")
|
635
|
+
execute("CREATE FULLTEXT INDEX `index_with_a_custom_name` ON `users` (`username`, `group`)")
|
636
|
+
|
637
|
+
Lhm.change_table(:users) do |t|
|
638
|
+
t.add_column(:email, "VARCHAR(255)")
|
639
|
+
end
|
640
|
+
|
641
|
+
value(table_read(:users).columns).must_include("email")
|
642
|
+
end
|
643
|
+
|
556
644
|
describe 'parallel' do
|
557
645
|
it 'should perserve inserts during migration' do
|
558
646
|
50.times { |n| execute("insert into users set reference = '#{ n }'") }
|
@@ -616,7 +704,13 @@ describe Lhm do
|
|
616
704
|
table_create(:users)
|
617
705
|
100.times { |n| execute("insert into users set reference = '#{ n }'") }
|
618
706
|
|
619
|
-
|
707
|
+
error = if ActiveRecord.version >= ::Gem::Version.new('8.1.0.alpha')
|
708
|
+
ActiveRecord::ConnectionNotEstablished
|
709
|
+
else
|
710
|
+
ActiveRecord::StatementInvalid
|
711
|
+
end
|
712
|
+
|
713
|
+
assert_raises error do
|
620
714
|
Toxiproxy[:mysql_master].down do
|
621
715
|
Lhm.change_table(:users, :atomic_switch => false) do |t|
|
622
716
|
t.ddl("ALTER TABLE #{t.name} CHANGE id id bigint (20) NOT NULL")
|
@@ -20,7 +20,7 @@ class DBConnectionHelper
|
|
20
20
|
:database => test_db_name,
|
21
21
|
:port => db_config[key]['port']
|
22
22
|
)
|
23
|
-
conn = conn.connection
|
23
|
+
conn = conn.respond_to?(:lease_connection) ? conn.lease_connection : conn.connection
|
24
24
|
init_with_dummy_data(conn) if with_data
|
25
25
|
conn
|
26
26
|
end
|
@@ -81,10 +81,12 @@ describe Lhm::SqlRetry do
|
|
81
81
|
logs = @logger.string.split("\n")
|
82
82
|
assert_equal 2, logs.length
|
83
83
|
|
84
|
-
assert logs.first.include?("Lock wait timeout exceeded; try restarting transaction
|
84
|
+
assert logs.first.include?("Lock wait timeout exceeded; try restarting transaction")
|
85
|
+
assert logs.first.include?("- 1 tries")
|
85
86
|
assert logs.first.include?("0.2 seconds until the next try")
|
86
87
|
|
87
|
-
assert logs.last.include?("Lock wait timeout exceeded; try restarting transaction
|
88
|
+
assert logs.last.include?("Lock wait timeout exceeded; try restarting transaction")
|
89
|
+
assert logs.last.include?("- 2 tries")
|
88
90
|
assert logs.last.include?("0.2 seconds until the next try")
|
89
91
|
end
|
90
92
|
|
data/spec/unit/entangler_spec.rb
CHANGED
@@ -27,18 +27,18 @@ describe Lhm::Entangler do
|
|
27
27
|
@destination.columns['tags'] = { :type => 'varchar(255)' }
|
28
28
|
end
|
29
29
|
|
30
|
-
it 'should create
|
30
|
+
it 'should create the delete trigger to the destination table first' do
|
31
31
|
ddl = %Q{
|
32
|
-
create trigger `
|
33
|
-
after
|
34
|
-
|
35
|
-
|
32
|
+
create trigger `lhmt_del_origin`
|
33
|
+
after delete on `origin` for each row
|
34
|
+
delete ignore from `destination` /* large hadron migration */
|
35
|
+
where `destination`.`id` = OLD.`id`
|
36
36
|
}
|
37
37
|
|
38
|
-
|
38
|
+
assert_equal strip(ddl), @entangler.entangle[0]
|
39
39
|
end
|
40
40
|
|
41
|
-
it 'should create
|
41
|
+
it 'should create the update trigger to the destination table second' do
|
42
42
|
ddl = %Q{
|
43
43
|
create trigger `lhmt_upd_origin`
|
44
44
|
after update on `origin` for each row
|
@@ -46,18 +46,18 @@ describe Lhm::Entangler do
|
|
46
46
|
values (`NEW`.`info`, `NEW`.`tags`)
|
47
47
|
}
|
48
48
|
|
49
|
-
|
49
|
+
assert_equal strip(ddl), @entangler.entangle[1]
|
50
50
|
end
|
51
51
|
|
52
|
-
it 'should create
|
52
|
+
it 'should create the insert trigger to destination table last' do
|
53
53
|
ddl = %Q{
|
54
|
-
create trigger `
|
55
|
-
after
|
56
|
-
|
57
|
-
|
54
|
+
create trigger `lhmt_ins_origin`
|
55
|
+
after insert on `origin` for each row
|
56
|
+
replace into `destination` (`info`, `tags`) /* large hadron migration */
|
57
|
+
values (`NEW`.`info`, `NEW`.`tags`)
|
58
58
|
}
|
59
59
|
|
60
|
-
|
60
|
+
assert_equal strip(ddl), @entangler.entangle[2]
|
61
61
|
end
|
62
62
|
|
63
63
|
it 'should retry trigger creation when it hits a lock wait timeout' do
|
data/spec/unit/migrator_spec.rb
CHANGED
@@ -97,7 +97,7 @@ describe Lhm::Migrator do
|
|
97
97
|
@creator.add_column('logins', 'INT(12)')
|
98
98
|
|
99
99
|
value(@creator.statements).must_equal([
|
100
|
-
'alter table `lhmn_alt` add column `logins` INT(12), ALGORITHM=
|
100
|
+
'alter table `lhmn_alt` add column `logins` INT(12), ALGORITHM=COPY'
|
101
101
|
])
|
102
102
|
end
|
103
103
|
|
@@ -113,7 +113,7 @@ describe Lhm::Migrator do
|
|
113
113
|
@creator.remove_column('logins')
|
114
114
|
|
115
115
|
value(@creator.statements).must_equal([
|
116
|
-
'alter table `lhmn_alt` drop `logins`, ALGORITHM=
|
116
|
+
'alter table `lhmn_alt` drop `logins`, ALGORITHM=COPY'
|
117
117
|
])
|
118
118
|
end
|
119
119
|
|
@@ -167,24 +167,24 @@ describe Lhm::Migrator do
|
|
167
167
|
value(@creator.statements.length).must_equal(2)
|
168
168
|
|
169
169
|
value(@creator.statements[0])
|
170
|
-
.must_equal('alter table `lhmn_alt` add column `first` VARCHAR(64), ALGORITHM=
|
170
|
+
.must_equal('alter table `lhmn_alt` add column `first` VARCHAR(64), ALGORITHM=COPY')
|
171
171
|
|
172
172
|
value(@creator.statements[1])
|
173
|
-
.must_equal('alter table `lhmn_alt` add column `last` VARCHAR(64), ALGORITHM=
|
173
|
+
.must_equal('alter table `lhmn_alt` add column `last` VARCHAR(64), ALGORITHM=COPY')
|
174
174
|
end
|
175
175
|
end
|
176
176
|
|
177
177
|
describe 'multiple changes using the passed algorithm' do
|
178
178
|
it 'should add two columns' do
|
179
|
-
@creator.add_column('first', 'VARCHAR(64)', algorithm: '
|
180
|
-
@creator.add_column('last', 'VARCHAR(64)', algorithm: '
|
179
|
+
@creator.add_column('first', 'VARCHAR(64)', algorithm: 'INPLACE')
|
180
|
+
@creator.add_column('last', 'VARCHAR(64)', algorithm: 'INPLACE')
|
181
181
|
value(@creator.statements.length).must_equal(2)
|
182
182
|
|
183
183
|
value(@creator.statements[0])
|
184
|
-
.must_equal('alter table `lhmn_alt` add column `first` VARCHAR(64), ALGORITHM=
|
184
|
+
.must_equal('alter table `lhmn_alt` add column `first` VARCHAR(64), ALGORITHM=INPLACE')
|
185
185
|
|
186
186
|
value(@creator.statements[1])
|
187
|
-
.must_equal('alter table `lhmn_alt` add column `last` VARCHAR(64), ALGORITHM=
|
187
|
+
.must_equal('alter table `lhmn_alt` add column `last` VARCHAR(64), ALGORITHM=INPLACE')
|
188
188
|
end
|
189
189
|
end
|
190
190
|
end
|
@@ -66,11 +66,7 @@ describe Lhm::Throttler::Replica do
|
|
66
66
|
describe 'with active record config' do
|
67
67
|
it 'logs and creates client' do
|
68
68
|
active_record_config = { username: 'user', password: 'pw', database: 'db' }
|
69
|
-
|
70
|
-
ActiveRecord::Base.stubs(:connection_pool).returns(stub(db_config: stub(configuration_hash: active_record_config)))
|
71
|
-
else
|
72
|
-
ActiveRecord::Base.stubs(:connection_pool).returns(stub(spec: stub(config: active_record_config)))
|
73
|
-
end
|
69
|
+
ActiveRecord::Base.stubs(:connection_pool).returns(stub(db_config: stub(configuration_hash: active_record_config)))
|
74
70
|
|
75
71
|
DATABASE.client.stubs(:new).returns(mock())
|
76
72
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: lhm-shopify
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.5.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- SoundCloud
|
@@ -9,10 +9,9 @@ authors:
|
|
9
9
|
- Rany Keddo
|
10
10
|
- Tobias Bielohlawek
|
11
11
|
- Tobias Schmidt
|
12
|
-
autorequire:
|
13
12
|
bindir: bin
|
14
13
|
cert_chain: []
|
15
|
-
date:
|
14
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
16
15
|
dependencies:
|
17
16
|
- !ruby/object:Gem::Dependency
|
18
17
|
name: retriable
|
@@ -182,6 +181,34 @@ dependencies:
|
|
182
181
|
- - ">="
|
183
182
|
- !ruby/object:Gem::Version
|
184
183
|
version: '0'
|
184
|
+
- !ruby/object:Gem::Dependency
|
185
|
+
name: ostruct
|
186
|
+
requirement: !ruby/object:Gem::Requirement
|
187
|
+
requirements:
|
188
|
+
- - ">="
|
189
|
+
- !ruby/object:Gem::Version
|
190
|
+
version: '0'
|
191
|
+
type: :development
|
192
|
+
prerelease: false
|
193
|
+
version_requirements: !ruby/object:Gem::Requirement
|
194
|
+
requirements:
|
195
|
+
- - ">="
|
196
|
+
- !ruby/object:Gem::Version
|
197
|
+
version: '0'
|
198
|
+
- !ruby/object:Gem::Dependency
|
199
|
+
name: logger
|
200
|
+
requirement: !ruby/object:Gem::Requirement
|
201
|
+
requirements:
|
202
|
+
- - ">="
|
203
|
+
- !ruby/object:Gem::Version
|
204
|
+
version: '0'
|
205
|
+
type: :development
|
206
|
+
prerelease: false
|
207
|
+
version_requirements: !ruby/object:Gem::Requirement
|
208
|
+
requirements:
|
209
|
+
- - ">="
|
210
|
+
- !ruby/object:Gem::Version
|
211
|
+
version: '0'
|
185
212
|
description: Migrate large tables without downtime by copying to a temporary table
|
186
213
|
in chunks. The old table is not dropped. Instead, it is moved to timestamp_table_name
|
187
214
|
for verification.
|
@@ -206,12 +233,10 @@ files:
|
|
206
233
|
- docker-compose-mysql-5.7.yml
|
207
234
|
- docker-compose-mysql-8.0.yml
|
208
235
|
- docker-compose.yml
|
209
|
-
- gemfiles/
|
210
|
-
- gemfiles/
|
211
|
-
- gemfiles/
|
212
|
-
- gemfiles/
|
213
|
-
- gemfiles/activerecord_7.1.gemfile
|
214
|
-
- gemfiles/activerecord_7.1.gemfile.lock
|
236
|
+
- gemfiles/activerecord_7.2.gemfile
|
237
|
+
- gemfiles/activerecord_7.2.gemfile.lock
|
238
|
+
- gemfiles/activerecord_8.0.gemfile
|
239
|
+
- gemfiles/activerecord_8.0.gemfile.lock
|
215
240
|
- gemfiles/activerecord_head.gemfile
|
216
241
|
- gemfiles/activerecord_head.gemfile.lock
|
217
242
|
- lhm.gemspec
|
@@ -263,6 +288,7 @@ files:
|
|
263
288
|
- spec/fixtures/custom_primary_key_dest.ddl
|
264
289
|
- spec/fixtures/destination.ddl
|
265
290
|
- spec/fixtures/lines.ddl
|
291
|
+
- spec/fixtures/myisam_users.ddl
|
266
292
|
- spec/fixtures/origin.ddl
|
267
293
|
- spec/fixtures/permissions.ddl
|
268
294
|
- spec/fixtures/small_table.ddl
|
@@ -312,7 +338,6 @@ licenses:
|
|
312
338
|
- BSD-3-Clause
|
313
339
|
metadata:
|
314
340
|
allowed_push_host: https://rubygems.org
|
315
|
-
post_install_message:
|
316
341
|
rdoc_options: []
|
317
342
|
require_paths:
|
318
343
|
- lib
|
@@ -327,8 +352,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
327
352
|
- !ruby/object:Gem::Version
|
328
353
|
version: '0'
|
329
354
|
requirements: []
|
330
|
-
rubygems_version: 3.
|
331
|
-
signing_key:
|
355
|
+
rubygems_version: 3.6.9
|
332
356
|
specification_version: 4
|
333
357
|
summary: online schema changer for mysql
|
334
358
|
test_files: []
|
@@ -1,74 +0,0 @@
|
|
1
|
-
PATH
|
2
|
-
remote: ..
|
3
|
-
specs:
|
4
|
-
lhm-shopify (4.4.2)
|
5
|
-
retriable (>= 3.0.0)
|
6
|
-
|
7
|
-
GEM
|
8
|
-
remote: https://rubygems.org/
|
9
|
-
specs:
|
10
|
-
activemodel (7.0.8)
|
11
|
-
activesupport (= 7.0.8)
|
12
|
-
activerecord (7.0.8)
|
13
|
-
activemodel (= 7.0.8)
|
14
|
-
activesupport (= 7.0.8)
|
15
|
-
activerecord-trilogy-adapter (3.1.2)
|
16
|
-
activerecord (>= 6.0.a, < 7.1.a)
|
17
|
-
trilogy (>= 2.4.0)
|
18
|
-
activesupport (7.0.8)
|
19
|
-
concurrent-ruby (~> 1.0, >= 1.0.2)
|
20
|
-
i18n (>= 1.6, < 2)
|
21
|
-
minitest (>= 5.1)
|
22
|
-
tzinfo (~> 2.0)
|
23
|
-
after_do (0.4.0)
|
24
|
-
appraisal (2.5.0)
|
25
|
-
bundler
|
26
|
-
rake
|
27
|
-
thor (>= 0.14.0)
|
28
|
-
byebug (11.1.3)
|
29
|
-
concurrent-ruby (1.2.2)
|
30
|
-
docile (1.4.0)
|
31
|
-
i18n (1.14.1)
|
32
|
-
concurrent-ruby (~> 1.0)
|
33
|
-
minitest (5.22.2)
|
34
|
-
mocha (2.1.0)
|
35
|
-
ruby2_keywords (>= 0.0.5)
|
36
|
-
mysql2 (0.5.5)
|
37
|
-
rake (13.0.6)
|
38
|
-
retriable (3.1.2)
|
39
|
-
ruby2_keywords (0.0.5)
|
40
|
-
simplecov (0.22.0)
|
41
|
-
docile (~> 1.1)
|
42
|
-
simplecov-html (~> 0.11)
|
43
|
-
simplecov_json_formatter (~> 0.1)
|
44
|
-
simplecov-html (0.12.3)
|
45
|
-
simplecov_json_formatter (0.1.4)
|
46
|
-
thor (1.2.2)
|
47
|
-
toxiproxy (2.0.2)
|
48
|
-
trilogy (2.6.0)
|
49
|
-
tzinfo (2.0.6)
|
50
|
-
concurrent-ruby (~> 1.0)
|
51
|
-
|
52
|
-
PLATFORMS
|
53
|
-
arm64-darwin-21
|
54
|
-
arm64-darwin-22
|
55
|
-
x86_64-darwin-20
|
56
|
-
x86_64-linux
|
57
|
-
|
58
|
-
DEPENDENCIES
|
59
|
-
activerecord (= 7.0.8)
|
60
|
-
activerecord-trilogy-adapter
|
61
|
-
after_do
|
62
|
-
appraisal
|
63
|
-
byebug
|
64
|
-
lhm-shopify!
|
65
|
-
minitest
|
66
|
-
mocha
|
67
|
-
mysql2
|
68
|
-
rake
|
69
|
-
simplecov
|
70
|
-
toxiproxy
|
71
|
-
trilogy
|
72
|
-
|
73
|
-
BUNDLED WITH
|
74
|
-
2.2.22
|