lhm-shopify 4.2.1 → 4.3.0

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: dec22d00a0a019706b1a6d62e85e416caf210aa2d0b4f77bb3ccf562f1db8fb2
4
- data.tar.gz: 181acf59e61b100dc3320b6674a7cd13a2a1dcf767c7259a88a58dbf4b826bf5
3
+ metadata.gz: f0c79dc83baf664e8cd4ad2e11f8e72b3927edbb2af0beb5626961339e7f75c7
4
+ data.tar.gz: 1a58b01ab3ab768c37f497e24329d0e4e3d85dc64af7b1a338c5447b742f4a4b
5
5
  SHA512:
6
- metadata.gz: 8c197de7b7658cdb9c31dd91adde7fdaf54505bc7e910812d8c80edf447f6266630c08a80d773391071c518f72b9527280e1ece7e2bdc00bc60d5a8c22f294ed
7
- data.tar.gz: 6f1f7da4e1bd2e61fb8921eb9e724408d01ee576d98eb8ba393c2c2dada846368ec2a187e5c61d77f3691290edc815addd0e93acb8e1fa065c206564243ef798
6
+ metadata.gz: e349310577754cebfe7fa4d067727946c19fb0b291f1f2305e87d26a7d30371fd37c80bcdb58039936c90c75618157904f3141722e5f3f83c9b0e05afb76e447
7
+ data.tar.gz: 63fe5f4a016b32ab3d299e5cd9368f226a575bd725040931b8dd28db7e8a35cef7fbd78f0ec2713108dd508a974c7b783734a02e4d724a3b40e00afb7502693e
@@ -0,0 +1,20 @@
1
+ version: 2
2
+ registries:
3
+ ruby-shopify:
4
+ type: rubygems-server
5
+ url: https://pkgs.shopify.io/basic/gems/ruby
6
+ username: ${{secrets.RUBYGEMS_SERVER_PKGS_SHOPIFY_IO_USERNAME}}
7
+ password: ${{secrets.RUBYGEMS_SERVER_PKGS_SHOPIFY_IO_PASSWORD}}
8
+ github-com:
9
+ type: git
10
+ url: https://github.com
11
+ username: ${{secrets.DEPENDENCIES_GITHUB_USER}}
12
+ password: ${{secrets.DEPENDENCIES_GITHUB_TOKEN}}
13
+ updates:
14
+ - package-ecosystem: bundler
15
+ directory: "/"
16
+ schedule:
17
+ interval: daily
18
+ open-pull-requests-limit: 100
19
+ insecure-external-code-execution: allow
20
+ registries: "*"
@@ -13,9 +13,10 @@ jobs:
13
13
 
14
14
  strategy:
15
15
  fail-fast: false
16
+ max-parallel: 8
16
17
  matrix:
17
- activerecord: ["6.1", "7.0", "7.1"]
18
- ruby: ["3.0", "3.1", "3.2", "head"]
18
+ activerecord: ["6.1", "7.0", "7.1", "head"]
19
+ ruby: ["3.1", "3.2", "3.3", "head"]
19
20
  mysql: ["5.7", "8.0"]
20
21
  adapter: ["mysql2", "trilogy"]
21
22
  exclude:
@@ -23,6 +24,8 @@ jobs:
23
24
  ruby: head
24
25
  - activerecord: 7.0
25
26
  ruby: head
27
+ - activerecord: head
28
+ ruby: 3.0
26
29
 
27
30
  env:
28
31
  BUNDLE_GEMFILE: "${{ github.workspace }}/gemfiles/activerecord_${{ matrix.activerecord }}.gemfile"
@@ -40,7 +43,7 @@ jobs:
40
43
 
41
44
  - name: Setup MySQL and ProxySQL (docker-compose)
42
45
  # Might have to change to docker compose up -d (i.e. Compose V2) when the Ubuntu image changes the docker-compose version
43
- run: docker-compose -f docker-compose-mysql-${{ matrix.mysql }}.yml up -d
46
+ run: docker compose -f docker-compose-mysql-${{ matrix.mysql }}.yml up -d
44
47
 
45
48
  - name: Wait until DBs are alive
46
49
  run: ./scripts/helpers/wait-for-dbs.sh
data/.gitignore CHANGED
@@ -2,7 +2,6 @@
2
2
  .bundle
3
3
  pkg/*
4
4
  .rvmrc
5
- .ruby-version
6
5
  .ruby-gemset
7
6
  bin/rake
8
7
  gemfiles/vendor
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ 3.2.2
data/CHANGELOG.md CHANGED
@@ -1,5 +1,15 @@
1
1
  # Unreleased
2
2
 
3
+ # 4.3.0 (Aug, 2024)
4
+ * Drop support for Ruby 3.0, as it reached its EOL
5
+ * Add support for next Rails version
6
+
7
+ # 4.2.3 (Jul, 2024)
8
+ * Fix check for warnings against PKs with line breaks
9
+
10
+ # 4.2.2 (Jun, 2024)
11
+ * Avoid using the INSTANT algorithm.
12
+
3
13
  # 4.2.1 (Mar, 2024)
4
14
  * Retry more errors when using Trilogy.
5
15
 
data/Gemfile.lock CHANGED
@@ -1,19 +1,19 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- lhm-shopify (4.2.1)
4
+ lhm-shopify (4.3.0)
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 (7.1.3.4)
11
+ activesupport (= 7.1.3.4)
12
+ activerecord (7.1.3.4)
13
+ activemodel (= 7.1.3.4)
14
+ activesupport (= 7.1.3.4)
15
15
  timeout (>= 0.4.0)
16
- activesupport (7.1.1)
16
+ activesupport (7.1.3.4)
17
17
  base64
18
18
  bigdecimal
19
19
  concurrent-ruby (~> 1.0, >= 1.0.2)
@@ -28,22 +28,21 @@ GEM
28
28
  bundler
29
29
  rake
30
30
  thor (>= 0.14.0)
31
- base64 (0.1.1)
32
- bigdecimal (3.1.4)
31
+ base64 (0.2.0)
32
+ bigdecimal (3.1.8)
33
33
  byebug (11.1.3)
34
- concurrent-ruby (1.2.2)
34
+ concurrent-ruby (1.3.3)
35
35
  connection_pool (2.4.1)
36
- docile (1.4.0)
37
- drb (2.1.1)
38
- ruby2_keywords
39
- i18n (1.14.1)
36
+ docile (1.4.1)
37
+ drb (2.2.1)
38
+ i18n (1.14.5)
40
39
  concurrent-ruby (~> 1.0)
41
- minitest (5.22.2)
42
- mocha (2.1.0)
40
+ minitest (5.24.1)
41
+ mocha (2.4.5)
43
42
  ruby2_keywords (>= 0.0.5)
44
- mutex_m (0.1.2)
45
- mysql2 (0.5.5)
46
- rake (13.0.6)
43
+ mutex_m (0.2.0)
44
+ mysql2 (0.5.6)
45
+ rake (13.2.1)
47
46
  retriable (3.1.2)
48
47
  ruby2_keywords (0.0.5)
49
48
  simplecov (0.22.0)
@@ -52,10 +51,10 @@ GEM
52
51
  simplecov_json_formatter (~> 0.1)
53
52
  simplecov-html (0.12.3)
54
53
  simplecov_json_formatter (0.1.4)
55
- thor (1.2.2)
56
- timeout (0.4.0)
54
+ thor (1.3.1)
55
+ timeout (0.4.1)
57
56
  toxiproxy (2.0.2)
58
- trilogy (2.6.0)
57
+ trilogy (2.8.1)
59
58
  tzinfo (2.0.6)
60
59
  concurrent-ruby (~> 1.0)
61
60
 
data/dev.yml CHANGED
@@ -1,11 +1,9 @@
1
1
  name: lhm
2
2
  up:
3
- - homebrew:
4
- - mysql-client@5.7:
5
- or: [mysql@5.7]
6
- conflicts: [shopify/shopify/mysql-client, mysql-connector-c, mysql, mysql-client]
3
+ - packages:
4
+ - mysql-client@5.7
7
5
  - wget
8
- - ruby: 3.2.2
6
+ - ruby
9
7
  - bundler
10
8
  - podman
11
9
  - custom:
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- lhm-shopify (4.2.1)
4
+ lhm-shopify (4.3.0)
5
5
  retriable (>= 3.0.0)
6
6
 
7
7
  GEM
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- lhm-shopify (4.2.1)
4
+ lhm-shopify (4.3.0)
5
5
  retriable (>= 3.0.0)
6
6
 
7
7
  GEM
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ..
3
3
  specs:
4
- lhm-shopify (4.2.1)
4
+ lhm-shopify (4.3.0)
5
5
  retriable (>= 3.0.0)
6
6
 
7
7
  GEM
@@ -0,0 +1,7 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", git: "https://github.com/rails/rails.git", branch: "main"
6
+
7
+ gemspec path: "../"
data/lib/lhm/chunker.rb CHANGED
@@ -23,7 +23,6 @@ module Lhm
23
23
  @chunk_finder = ChunkFinder.new(migration, connection, options)
24
24
  @options = options
25
25
  @raise_on_warnings = options.fetch(:raise_on_warnings, false)
26
- @pk_duplicate_warning_regexp ||= /Duplicate entry .+ for key '(#{@migration.destination_name}\.)?PRIMARY'/
27
26
  @verifier = options[:verifier]
28
27
  if @throttler = options[:throttler]
29
28
  @throttler.connection = @connection if @throttler.respond_to?(:connection=)
@@ -81,7 +80,7 @@ module Lhm
81
80
 
82
81
  def raise_on_non_pk_duplicate_warning
83
82
  @connection.select_all("SHOW WARNINGS", should_retry: true, log_prefix: LOG_PREFIX).each do |row|
84
- next if row["Message"].match?(@pk_duplicate_warning_regexp)
83
+ next if row["Message"].start_with?("Duplicate entry") && row["Message"].match?(/for key '(#{@migration.destination_name}\.)?PRIMARY'\z/)
85
84
 
86
85
  m = "Unexpected warning found for inserted row: #{row["Message"]}"
87
86
  Lhm.logger.warn(m)
data/lib/lhm/migrator.rb CHANGED
@@ -53,7 +53,7 @@ module Lhm
53
53
  # @param [String] name Name of the column to add
54
54
  # @param [String] definition Valid SQL column definition
55
55
  def add_column(name, definition)
56
- ddl('alter table `%s` add column `%s` %s' % [@name, name, definition])
56
+ ddl('alter table `%s` add column `%s` %s, ALGORITHM=INPLACE' % [@name, name, definition])
57
57
  end
58
58
 
59
59
  # Change an existing column to a new definition
@@ -94,7 +94,7 @@ module Lhm
94
94
  definition += " COMMENT #{@connection.quote(col[:comment])}" if col[:comment]
95
95
  definition += " COLLATE #{@connection.quote(col[:collate])}" if col[:collate]
96
96
 
97
- ddl('alter table `%s` change column `%s` `%s` %s' % [@name, old, nu, definition])
97
+ ddl('alter table `%s` change column `%s` `%s` %s, ALGORITHM=INPLACE' % [@name, old, nu, definition])
98
98
  @renames[old.to_s] = nu.to_s
99
99
  end
100
100
 
@@ -108,7 +108,7 @@ module Lhm
108
108
  #
109
109
  # @param [String] name Name of the column to delete
110
110
  def remove_column(name)
111
- ddl('alter table `%s` drop `%s`' % [@name, name])
111
+ ddl('alter table `%s` drop `%s`, ALGORITHM=INPLACE' % [@name, name])
112
112
  end
113
113
 
114
114
  # Add an index to a table
@@ -65,7 +65,7 @@ module Lhm
65
65
  end
66
66
 
67
67
  def struct_key(struct, key)
68
- keys = if struct.is_a? Hash
68
+ keys = if struct.respond_to?(:keys)
69
69
  struct.keys
70
70
  else
71
71
  struct.members
data/lib/lhm/version.rb CHANGED
@@ -2,5 +2,5 @@
2
2
  # Schmidt
3
3
 
4
4
  module Lhm
5
- VERSION = '4.2.1'
5
+ VERSION = '4.3.0'
6
6
  end
@@ -0,0 +1,10 @@
1
+ CREATE TABLE `composite_primary_key_with_varchar_columns` (
2
+ `id` bigint NOT NULL AUTO_INCREMENT,
3
+ `shop_id` bigint NOT NULL,
4
+ `owner_type` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
5
+ `owner_id` bigint NOT NULL,
6
+ `namespace` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
7
+ `key` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
8
+ PRIMARY KEY (`shop_id`,`owner_type`,`owner_id`,`namespace`,`key`),
9
+ UNIQUE KEY `id` (`id`)
10
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC
@@ -0,0 +1,10 @@
1
+ CREATE TABLE `composite_primary_key_with_varchar_columns_dest` (
2
+ `id` bigint NOT NULL AUTO_INCREMENT,
3
+ `shop_id` bigint NOT NULL,
4
+ `owner_type` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
5
+ `owner_id` bigint NOT NULL,
6
+ `namespace` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
7
+ `key` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
8
+ PRIMARY KEY (`shop_id`,`owner_type`,`owner_id`,`namespace`,`key`),
9
+ UNIQUE KEY `id` (`id`)
10
+ ) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_general_ci ROW_FORMAT=DYNAMIC
@@ -61,6 +61,46 @@ describe Lhm::Chunker do
61
61
  end
62
62
  end
63
63
 
64
+ it 'should copy and ignore duplicate composite primary key with line breaks' do
65
+ origin = table_create(:composite_primary_key_with_varchar_columns)
66
+ destination = table_create(:composite_primary_key_with_varchar_columns_dest)
67
+ migration = Lhm::Migration.new(origin, destination)
68
+
69
+ execute("insert into composite_primary_key_with_varchar_columns set id = 1001, shop_id = 1, owner_type = 'Product', owner_id = 1, namespace = '
70
+ 23
71
+
72
+ 23
73
+ ', `key` = '
74
+ 14
75
+
76
+ 1
77
+ '")
78
+ execute("insert into composite_primary_key_with_varchar_columns set id = 1002, shop_id = 1, owner_type = 'Product', owner_id = 1, namespace = '
79
+ 23
80
+
81
+ 22
82
+ ', `key` = '
83
+ 14
84
+
85
+ 1
86
+ '")
87
+ execute("insert into composite_primary_key_with_varchar_columns_dest set id = 1002, shop_id = 1, owner_type = 'Product', owner_id = 1, namespace = '
88
+ 23
89
+
90
+ 22
91
+ ', `key` = '
92
+ 14
93
+
94
+ 1
95
+ '")
96
+
97
+ Lhm::Chunker.new(migration, connection, {raise_on_warning: true, throttler: throttler, printer: printer} ).run
98
+
99
+ replica do
100
+ value(count_all(destination.name)).must_equal(2)
101
+ end
102
+ end
103
+
64
104
  it 'should copy and raise on unexpected warnings' do
65
105
  origin = table_create(:custom_primary_key)
66
106
  destination = table_create(:custom_primary_key_dest)
@@ -2,6 +2,7 @@
2
2
  # Schmidt
3
3
 
4
4
  require File.expand_path(File.dirname(__FILE__)) + '/integration_helper'
5
+ require 'ostruct'
5
6
 
6
7
  describe Lhm, 'cleanup' do
7
8
  include IntegrationHelper
@@ -328,8 +328,7 @@ describe Lhm do
328
328
  :collate => collation,
329
329
  })
330
330
 
331
- result = select_one('SELECT login from users')
332
- result = result['login'] if result.respond_to?(:has_key?)
331
+ result = select_value('SELECT login from users')
333
332
  value(result).must_equal('a user')
334
333
  end
335
334
  end
@@ -353,8 +352,7 @@ describe Lhm do
353
352
  :collate => collation,
354
353
  })
355
354
 
356
- result = select_one('SELECT `fnord` from users')
357
- result = result['fnord'] if result.respond_to?(:has_key?)
355
+ result = select_value('SELECT `fnord` from users')
358
356
  value(result).must_equal('Superfriends')
359
357
  end
360
358
  end
@@ -380,8 +378,7 @@ describe Lhm do
380
378
  :collate => 'utf8mb4_unicode_ci',
381
379
  })
382
380
 
383
- result = select_one('SELECT `user_name` from users')
384
- result = result['user_name'] if result.respond_to?(:has_key?)
381
+ result = select_value('SELECT `user_name` from users')
385
382
  value(result).must_equal('a user')
386
383
  end
387
384
  end
@@ -410,8 +407,7 @@ describe Lhm do
410
407
  :collate => nil,
411
408
  })
412
409
 
413
- result = select_one('SELECT `ref` from users')
414
- result = result['ref'] if result.respond_to?(:has_key?)
410
+ result = select_value('SELECT `ref` from users')
415
411
  value(result).must_equal(10)
416
412
  end
417
413
  end
@@ -437,8 +433,7 @@ describe Lhm do
437
433
  :collate => collation,
438
434
  })
439
435
 
440
- result = select_one('SELECT `fnord` from users')
441
- result = result['fnord'] if result.respond_to?(:has_key?)
436
+ result = select_value('SELECT `fnord` from users')
442
437
  assert_nil(result)
443
438
  end
444
439
  end
@@ -462,8 +457,7 @@ describe Lhm do
462
457
  :collate => collation,
463
458
  })
464
459
 
465
- result = select_one('SELECT `user_name` from users')
466
- result = result['user_name'] if result.respond_to?(:has_key?)
460
+ result = select_value('SELECT `user_name` from users')
467
461
  value(result).must_equal('a user')
468
462
  end
469
463
  end
@@ -489,8 +483,7 @@ describe Lhm do
489
483
  :collate => collation,
490
484
  })
491
485
 
492
- result = select_one('SELECT `user_name` from users')
493
- result = result['user_name'] if result.respond_to?(:has_key?)
486
+ result = select_value('SELECT `user_name` from users')
494
487
  value(result).must_equal('a user')
495
488
  end
496
489
  end
@@ -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)'
100
+ 'alter table `lhmn_alt` add column `logins` INT(12), ALGORITHM=INPLACE'
101
101
  ])
102
102
  end
103
103
 
@@ -105,7 +105,7 @@ describe Lhm::Migrator do
105
105
  @creator.remove_column('logins')
106
106
 
107
107
  value(@creator.statements).must_equal([
108
- 'alter table `lhmn_alt` drop `logins`'
108
+ 'alter table `lhmn_alt` drop `logins`, ALGORITHM=INPLACE'
109
109
  ])
110
110
  end
111
111
 
@@ -151,10 +151,10 @@ describe Lhm::Migrator do
151
151
  value(@creator.statements.length).must_equal(2)
152
152
 
153
153
  value(@creator.statements[0])
154
- .must_equal('alter table `lhmn_alt` add column `first` VARCHAR(64)')
154
+ .must_equal('alter table `lhmn_alt` add column `first` VARCHAR(64), ALGORITHM=INPLACE')
155
155
 
156
156
  value(@creator.statements[1])
157
- .must_equal('alter table `lhmn_alt` add column `last` VARCHAR(64)')
157
+ .must_equal('alter table `lhmn_alt` add column `last` VARCHAR(64), ALGORITHM=INPLACE')
158
158
  end
159
159
  end
160
160
  end
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.2.1
4
+ version: 4.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - SoundCloud
@@ -9,10 +9,10 @@ authors:
9
9
  - Rany Keddo
10
10
  - Tobias Bielohlawek
11
11
  - Tobias Schmidt
12
- autorequire:
12
+ autorequire:
13
13
  bindir: bin
14
14
  cert_chain: []
15
- date: 2024-03-11 00:00:00.000000000 Z
15
+ date: 2024-08-05 00:00:00.000000000 Z
16
16
  dependencies:
17
17
  - !ruby/object:Gem::Dependency
18
18
  name: retriable
@@ -190,9 +190,11 @@ executables: []
190
190
  extensions: []
191
191
  extra_rdoc_files: []
192
192
  files:
193
+ - ".github/dependabot.yml"
193
194
  - ".github/workflows/test.yml"
194
195
  - ".gitignore"
195
196
  - ".rubocop.yml"
197
+ - ".ruby-version"
196
198
  - Appraisals
197
199
  - CHANGELOG.md
198
200
  - Gemfile
@@ -210,6 +212,7 @@ files:
210
212
  - gemfiles/activerecord_7.0.gemfile.lock
211
213
  - gemfiles/activerecord_7.1.gemfile
212
214
  - gemfiles/activerecord_7.1.gemfile.lock
215
+ - gemfiles/activerecord_head.gemfile
213
216
  - lhm.gemspec
214
217
  - lib/lhm-shopify.rb
215
218
  - lib/lhm.rb
@@ -252,6 +255,8 @@ files:
252
255
  - spec/fixtures/bigint_table.ddl
253
256
  - spec/fixtures/composite_primary_key.ddl
254
257
  - spec/fixtures/composite_primary_key_dest.ddl
258
+ - spec/fixtures/composite_primary_key_with_varchar_columns.ddl
259
+ - spec/fixtures/composite_primary_key_with_varchar_columns_dest.ddl
255
260
  - spec/fixtures/custom_primary_key.ddl
256
261
  - spec/fixtures/custom_primary_key_dest.ddl
257
262
  - spec/fixtures/destination.ddl
@@ -305,7 +310,7 @@ licenses:
305
310
  - BSD-3-Clause
306
311
  metadata:
307
312
  allowed_push_host: https://rubygems.org
308
- post_install_message:
313
+ post_install_message:
309
314
  rdoc_options: []
310
315
  require_paths:
311
316
  - lib
@@ -320,8 +325,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
320
325
  - !ruby/object:Gem::Version
321
326
  version: '0'
322
327
  requirements: []
323
- rubygems_version: 3.5.6
324
- signing_key:
328
+ rubygems_version: 3.5.16
329
+ signing_key:
325
330
  specification_version: 4
326
331
  summary: online schema changer for mysql
327
332
  test_files: []