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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 938d28fc99ea36454247de34a03ff3a202f0892e11f590b0c41556de4e041ee4
4
- data.tar.gz: e28790317276015c4ffaeb9150c7e2a5eeb3a3fad1713604bda670225c6e181b
3
+ metadata.gz: f6810104b2e7de311501c58b38b5ab605bf808b2391e9406901dd97394ae29c2
4
+ data.tar.gz: 251bdd83425a0986d5d3cdded7fc05e4d53731eb86269a3059f2524780287b6e
5
5
  SHA512:
6
- metadata.gz: 6eeca296f8626d383bccc0978440f26dd05c7a4da002648101db578e553d4a407da4238e35cf7ee18a21e821d7c1f66a30c55bd665dff9863bdad80e3f6c60b9
7
- data.tar.gz: 78b1799fd87375c9042b3340b40db4439702b007977632afe104800bd01b12aad34e44f9694b3d58e9a277a3a42a8785794d87c31d2b56c3a9b59f448b60eda4
6
+ metadata.gz: 866539e9bcac6acc7740766524d52e87de8572bde63d336b4dd1636c87da876d178729eaa5e716dafed53339c903ba79677980a0f29346c8ad36e0cebb145e7f
7
+ data.tar.gz: 0c7840100abf5b849e6750061f269fab888633bba7afd287cad3461e70e941f26f9a7a42fd215effa89797c7841c0b1200aab69d44d1119c79951ef53e8dee98
@@ -15,17 +15,19 @@ jobs:
15
15
  fail-fast: false
16
16
  max-parallel: 8
17
17
  matrix:
18
- activerecord: ["6.1", "7.0", "7.1", "head"]
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.0
25
+ - activerecord: 7.2
26
26
  ruby: head
27
+ - activerecord: 8.0
28
+ ruby: 3.1
27
29
  - activerecord: head
28
- ruby: 3.0
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.2.2
1
+ 3.3.6
data/Appraisals CHANGED
@@ -1,15 +1,9 @@
1
- appraise "activerecord-6.1" do
2
- gem "activerecord", "6.1.0"
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.0" do
7
- gem "activerecord", "7.0.8"
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.2)
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 (7.2.0)
11
- activesupport (= 7.2.0)
12
- activerecord (7.2.0)
13
- activemodel (= 7.2.0)
14
- activesupport (= 7.2.0)
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 (7.2.0)
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
- bigdecimal (3.1.8)
35
+ benchmark (0.4.0)
36
+ bigdecimal (3.1.9)
34
37
  byebug (11.1.3)
35
- concurrent-ruby (1.3.4)
36
- connection_pool (2.4.1)
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.5)
42
+ i18n (1.14.7)
40
43
  concurrent-ruby (~> 1.0)
41
- logger (1.6.0)
42
- minitest (5.25.1)
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.3.1)
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.1)
57
- timeout (0.4.1)
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.2.22
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@5.7
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 -ioE -q "lhm.*running\(4\)"
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
@@ -2,7 +2,6 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "activerecord", "6.1.0"
6
- gem "activerecord-trilogy-adapter"
5
+ gem "activerecord", "7.2.2.1"
7
6
 
8
7
  gemspec path: "../"
@@ -1,76 +1,90 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- lhm-shopify (4.4.2)
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 (6.1.0)
11
- activesupport (= 6.1.0)
12
- activerecord (6.1.0)
13
- activemodel (= 6.1.0)
14
- activesupport (= 6.1.0)
15
- activerecord-trilogy-adapter (3.1.2)
16
- activerecord (>= 6.0.a, < 7.1.a)
17
- trilogy (>= 2.4.0)
18
- activesupport (6.1.0)
19
- concurrent-ruby (~> 1.0, >= 1.0.2)
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
- tzinfo (~> 2.0)
23
- zeitwerk (~> 2.3)
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.2.2)
37
+ concurrent-ruby (1.3.5)
38
+ connection_pool (2.5.0)
31
39
  docile (1.4.0)
32
- i18n (1.14.1)
40
+ drb (2.2.1)
41
+ i18n (1.14.7)
33
42
  concurrent-ruby (~> 1.0)
34
- minitest (5.22.2)
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.2.2)
59
+ thor (1.3.2)
60
+ timeout (0.4.3)
48
61
  toxiproxy (2.0.2)
49
- trilogy (2.6.0)
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 (= 6.1.0)
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.2.22
90
+ 2.6.3
@@ -2,6 +2,6 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "activerecord", "7.1.1"
5
+ gem "activerecord", "8.0.1"
6
6
 
7
7
  gemspec path: "../"
@@ -1,83 +1,92 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- lhm-shopify (4.4.2)
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 (7.1.1)
11
- activesupport (= 7.1.1)
12
- activerecord (7.1.1)
13
- activemodel (= 7.1.1)
14
- activesupport (= 7.1.1)
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 (7.1.1)
16
+ activesupport (8.0.1)
17
17
  base64
18
+ benchmark (>= 0.3)
18
19
  bigdecimal
19
- concurrent-ruby (~> 1.0, >= 1.0.2)
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
- mutex_m
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.1.1)
32
- bigdecimal (3.1.4)
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.2.2)
35
- connection_pool (2.4.1)
38
+ concurrent-ruby (1.3.5)
39
+ connection_pool (2.5.0)
36
40
  docile (1.4.0)
37
- drb (2.1.1)
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.2.2)
56
- timeout (0.4.0)
60
+ thor (1.3.2)
61
+ timeout (0.4.3)
57
62
  toxiproxy (2.0.2)
58
- trilogy (2.6.0)
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 (= 7.1.1)
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.2.22
92
+ 2.6.3
@@ -1,16 +1,17 @@
1
1
  GIT
2
2
  remote: https://github.com/rails/rails.git
3
- revision: f4a9b7618fc32f0d3b2c0ff03a3f34f4964cc553
3
+ revision: bdad2707835949a96dd29e747b8c324593efd4d8
4
4
  branch: main
5
5
  specs:
6
- activemodel (8.0.0.alpha)
7
- activesupport (= 8.0.0.alpha)
8
- activerecord (8.0.0.alpha)
9
- activemodel (= 8.0.0.alpha)
10
- activesupport (= 8.0.0.alpha)
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.0.0.alpha)
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.4.2)
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
- bigdecimal (3.1.8)
41
+ benchmark (0.4.0)
42
+ bigdecimal (3.1.9)
40
43
  byebug (11.1.3)
41
- concurrent-ruby (1.3.3)
42
- connection_pool (2.4.1)
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.5)
48
+ i18n (1.14.7)
46
49
  concurrent-ruby (~> 1.0)
47
- logger (1.6.0)
48
- minitest (5.24.1)
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.3.1)
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.1)
63
- timeout (0.4.1)
66
+ thor (1.3.2)
67
+ timeout (0.4.3)
64
68
  toxiproxy (2.0.2)
65
- trilogy (2.8.1)
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.2.22
96
+ 2.6.3
data/lhm.gemspec CHANGED
@@ -36,4 +36,6 @@ Gem::Specification.new do |s|
36
36
  s.add_development_dependency 'toxiproxy'
37
37
  s.add_development_dependency 'appraisal'
38
38
  s.add_development_dependency 'byebug'
39
+ s.add_development_dependency 'ostruct'
40
+ s.add_development_dependency 'logger'
39
41
  end
data/lib/lhm/entangler.rb CHANGED
@@ -27,8 +27,8 @@ module Lhm
27
27
  def entangle
28
28
  [
29
29
  create_delete_trigger,
30
+ create_update_trigger,
30
31
  create_insert_trigger,
31
- create_update_trigger
32
32
  ]
33
33
  end
34
34
 
@@ -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(options = {})
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: 'INPLACE')
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: 'INPLACE')
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: 'INPLACE')
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
@@ -199,6 +199,7 @@ module Lhm
199
199
  /The MySQL server is running with the --read-only option so it cannot execute this statement/,
200
200
  ],
201
201
  Trilogy::ConnectionError => nil,
202
+ Trilogy::TimeoutError => nil,
202
203
  }
203
204
 
204
205
  if ActiveRecord::VERSION::STRING >= "7.1"
@@ -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
@@ -2,5 +2,5 @@
2
2
  # Schmidt
3
3
 
4
4
  module Lhm
5
- VERSION = '4.4.2'
5
+ VERSION = '4.5.1'
6
6
  end
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(options)
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
- assert_raises ActiveRecord::StatementInvalid do
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' - 1 tries")
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' - 2 tries")
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
 
@@ -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 insert trigger to destination table' do
30
+ it 'should create the delete trigger to the destination table first' do
31
31
  ddl = %Q{
32
- create trigger `lhmt_ins_origin`
33
- after insert on `origin` for each row
34
- replace into `destination` (`info`, `tags`) /* large hadron migration */
35
- values (`NEW`.`info`, `NEW`.`tags`)
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
- value(@entangler.entangle).must_include strip(ddl)
38
+ assert_equal strip(ddl), @entangler.entangle[0]
39
39
  end
40
40
 
41
- it 'should create an update trigger to the destination table' do
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
- value(@entangler.entangle).must_include strip(ddl)
49
+ assert_equal strip(ddl), @entangler.entangle[1]
50
50
  end
51
51
 
52
- it 'should create a delete trigger to the destination table' do
52
+ it 'should create the insert trigger to destination table last' do
53
53
  ddl = %Q{
54
- create trigger `lhmt_del_origin`
55
- after delete on `origin` for each row
56
- delete ignore from `destination` /* large hadron migration */
57
- where `destination`.`id` = OLD.`id`
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
- value(@entangler.entangle).must_include strip(ddl)
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
@@ -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=INPLACE'
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=INPLACE'
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=INPLACE')
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=INPLACE')
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: 'COPY')
180
- @creator.add_column('last', 'VARCHAR(64)', algorithm: 'COPY')
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=COPY')
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=COPY')
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
- if ActiveRecord::VERSION::MAJOR > 6 || ActiveRecord::VERSION::MAJOR == 6 && ActiveRecord::VERSION::MINOR >= 1
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.2
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: 2024-09-09 00:00:00.000000000 Z
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/activerecord_6.1.gemfile
210
- - gemfiles/activerecord_6.1.gemfile.lock
211
- - gemfiles/activerecord_7.0.gemfile
212
- - gemfiles/activerecord_7.0.gemfile.lock
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.5.18
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,8 +0,0 @@
1
- # This file was generated by Appraisal
2
-
3
- source "https://rubygems.org"
4
-
5
- gem "activerecord", "7.0.8"
6
- gem "activerecord-trilogy-adapter"
7
-
8
- gemspec path: "../"
@@ -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