activerecord-spanner-adapter 1.0.1 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (46) hide show
  1. checksums.yaml +4 -4
  2. data/.github/CODEOWNERS +1 -1
  3. data/.github/sync-repo-settings.yaml +2 -2
  4. data/.github/workflows/acceptance-tests-on-emulator.yaml +10 -6
  5. data/.github/workflows/acceptance-tests-on-production.yaml +1 -1
  6. data/.github/workflows/ci.yaml +10 -8
  7. data/.github/workflows/nightly-acceptance-tests-on-emulator.yaml +14 -5
  8. data/.github/workflows/nightly-acceptance-tests-on-production.yaml +2 -2
  9. data/.github/workflows/nightly-unit-tests.yaml +14 -5
  10. data/.github/workflows/release-please.yml +2 -2
  11. data/.github/workflows/rubocop.yaml +3 -3
  12. data/.kokoro/release.sh +1 -3
  13. data/.release-please-manifest.json +1 -1
  14. data/.toys/release.rb +8 -2
  15. data/CHANGELOG.md +18 -0
  16. data/Gemfile +5 -1
  17. data/acceptance/cases/interleaved_associations/has_many_associations_using_interleaved_test.rb +12 -8
  18. data/acceptance/cases/models/insert_all_test.rb +150 -0
  19. data/acceptance/cases/transactions/optimistic_locking_test.rb +5 -0
  20. data/acceptance/cases/type/all_types_test.rb +10 -13
  21. data/acceptance/cases/type/json_test.rb +0 -2
  22. data/acceptance/models/album.rb +7 -2
  23. data/acceptance/models/singer.rb +2 -2
  24. data/acceptance/models/track.rb +5 -2
  25. data/acceptance/schema/schema.rb +2 -4
  26. data/acceptance/test_helper.rb +1 -1
  27. data/activerecord-spanner-adapter.gemspec +1 -1
  28. data/examples/snippets/interleaved-tables/README.md +164 -0
  29. data/examples/snippets/interleaved-tables/Rakefile +13 -0
  30. data/examples/snippets/interleaved-tables/application.rb +126 -0
  31. data/examples/snippets/interleaved-tables/config/database.yml +8 -0
  32. data/examples/snippets/interleaved-tables/db/migrate/01_create_tables.rb +44 -0
  33. data/examples/snippets/interleaved-tables/db/schema.rb +32 -0
  34. data/examples/snippets/interleaved-tables/db/seeds.rb +40 -0
  35. data/examples/snippets/interleaved-tables/models/album.rb +20 -0
  36. data/examples/snippets/interleaved-tables/models/singer.rb +18 -0
  37. data/examples/snippets/interleaved-tables/models/track.rb +28 -0
  38. data/lib/active_record/connection_adapters/spanner/schema_creation.rb +10 -4
  39. data/lib/active_record/connection_adapters/spanner_adapter.rb +64 -31
  40. data/lib/activerecord_spanner_adapter/base.rb +150 -17
  41. data/lib/activerecord_spanner_adapter/connection.rb +1 -1
  42. data/lib/activerecord_spanner_adapter/relation.rb +21 -0
  43. data/lib/activerecord_spanner_adapter/transaction.rb +4 -4
  44. data/lib/activerecord_spanner_adapter/version.rb +1 -1
  45. data/lib/arel/visitors/spanner.rb +10 -0
  46. metadata +25 -7
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: bcc2624f18893422bf8ac9c23d07fff039e79cee5f51b975054314f49820b694
4
- data.tar.gz: 7145b48f67236eb7ee9aac20bd1dfa907268419f262abf82cd6973acba25ab64
3
+ metadata.gz: 5f8199e1af804baf47d382e53404f88329478d35958f71fcaec34f73921de987
4
+ data.tar.gz: b2bc3919e5cc4d675d539806c27e0dda7b16d676ca349aa95a11370c4ec145b7
5
5
  SHA512:
6
- metadata.gz: 49aed5257b191aee1e9271c1d04e91c2ff1663c78e9b1e70e89acda430587324991a10cb1b2aabdfd9b1e9d70ab862b3a1579fda5c032023175303fa260deeed
7
- data.tar.gz: 1764369d2a370d4c8d35cbbcd3b9c45130514cc6e76bac67e5a9dafbf2bf020734b973be44f354b13da9acaaffdebaba78e31046da56c6e62efe0546aca30611
6
+ metadata.gz: 22ed1bd5840aa615681a7af2a4f87ceb31a5ec5a772d3260740ed520f99269b1ecdc0022aa1bcbf703afe01d99a04bb6181d546c5d6690bef20c17142281eb47
7
+ data.tar.gz: b9d65faf249175397de04b003a612ed10f89302ba545ffe09208b43414e9e8291feb9240aae3850f5f97d6f6b0bfd9c6134176316ebf6cc520d487e8d9700447
data/.github/CODEOWNERS CHANGED
@@ -4,4 +4,4 @@
4
4
  # For syntax help see:
5
5
  # https://help.github.com/en/github/creating-cloning-and-archiving-repositories/about-code-owners#codeowners-syntax
6
6
 
7
- * @jiren @skuruppu @dazuma @hengfengli @olavloite @xiangshen-dk
7
+ * @googleapis/ruby-team @skuruppu @hengfengli @olavloite @xiangshen-dk
@@ -10,7 +10,7 @@ branchProtectionRules:
10
10
  requiresCodeOwnerReviews: true
11
11
  requiresStrictStatusChecks: true
12
12
  permissionRules:
13
- - team: yoshi-ruby
13
+ - team: ruby-team
14
14
  permission: push
15
- - team: yoshi-ruby-admins
15
+ - team: ruby-admins
16
16
  permission: admin
@@ -19,13 +19,19 @@ jobs:
19
19
  max-parallel: 4
20
20
  matrix:
21
21
  ruby: [2.6, 2.7, 3.0]
22
- ar: [6.0.4, 6.1.4]
23
- # Exclude Ruby 3.0 and ActiveRecord 6.0.x as that combination is not supported.
22
+ ar: [6.0.5.1, 6.1.6.1, 7.0.2.4, 7.0.3.1]
23
+ # Exclude combinations that are not supported.
24
24
  exclude:
25
25
  - ruby: 3.0
26
- ar: 6.0.4
26
+ ar: 6.0.5.1
27
+ - ruby: 2.6
28
+ ar: 7.0.2.4
29
+ - ruby: 2.6
30
+ ar: 7.0.3.1
31
+ env:
32
+ AR_VERSION: ${{ matrix.ar }}
27
33
  steps:
28
- - uses: actions/checkout@v2
34
+ - uses: actions/checkout@v3
29
35
  - name: Set up Ruby
30
36
  # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby
31
37
  # (see https://github.com/ruby/setup-ruby#versioning):
@@ -33,8 +39,6 @@ jobs:
33
39
  with:
34
40
  bundler-cache: false
35
41
  ruby-version: ${{ matrix.ruby }}
36
- - name: Set ActiveRecord version
37
- run: sed -i "s/\"activerecord\", \"~> 6.1.4\"/\"activerecord\", \"${{ matrix.ar }}\"/" activerecord-spanner-adapter.gemspec
38
42
  - name: Install dependencies
39
43
  run: bundle install
40
44
  - name: Run acceptance tests on emulator
@@ -26,7 +26,7 @@ jobs:
26
26
  matrix:
27
27
  ruby: [3.0]
28
28
  steps:
29
- - uses: actions/checkout@v2
29
+ - uses: actions/checkout@v3
30
30
  - name: Set up Ruby
31
31
  # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby
32
32
  # (see https://github.com/ruby/setup-ruby#versioning):
@@ -10,14 +10,18 @@ jobs:
10
10
  strategy:
11
11
  max-parallel: 4
12
12
  matrix:
13
- ruby: [2.6, 2.7, 3.0]
14
- ar: [6.0.4, 6.1.4]
15
- # Exclude Ruby 3.0 and ActiveRecord 6.0.x as that combination is not supported.
13
+ ruby: ["2.6", "2.7", "3.0"]
14
+ ar: ["6.0.4", "6.1.4", "7.0.2.4"]
15
+ # Exclude combinations that are not supported.
16
16
  exclude:
17
- - ruby: 3.0
18
- ar: 6.0.4
17
+ - ruby: "3.0"
18
+ ar: "6.0.4"
19
+ - ruby: "2.6"
20
+ ar: "7.0.2.4"
21
+ env:
22
+ AR_VERSION: ${{ matrix.ar }}
19
23
  steps:
20
- - uses: actions/checkout@v2
24
+ - uses: actions/checkout@v3
21
25
  - name: Set up Ruby
22
26
  # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby
23
27
  # (see https://github.com/ruby/setup-ruby#versioning):
@@ -25,8 +29,6 @@ jobs:
25
29
  with:
26
30
  bundler-cache: false
27
31
  ruby-version: ${{ matrix.ruby }}
28
- - name: Set ActiveRecord version
29
- run: sed -i "s/\"activerecord\", \"~> 6.1.4\"/\"activerecord\", \"${{ matrix.ar }}\"/" activerecord-spanner-adapter.gemspec
30
32
  - name: Install dependencies
31
33
  run: bundle install
32
34
  - name: Run tests
@@ -2,6 +2,7 @@ on:
2
2
  schedule:
3
3
  # 06:00 UTC
4
4
  - cron: '0 6 * * *'
5
+ workflow_dispatch:
5
6
  name: nightly acceptance tests on emulator
6
7
  jobs:
7
8
  test:
@@ -19,8 +20,8 @@ jobs:
19
20
  matrix:
20
21
  # Run acceptance tests all supported combinations of Ruby and ActiveRecord.
21
22
  ruby: [2.5, 2.6, 2.7, 3.0]
22
- ar: [6.0.0, 6.0.1, 6.0.2.2, 6.0.3.7, 6.0.4, 6.1.0, 6.1.1, 6.1.2.1, 6.1.3.2, 6.1.4]
23
- # Exclude Ruby 3.0 and ActiveRecord 6.0.x as that combination is not supported.
23
+ ar: [6.0.0, 6.0.1, 6.0.2.2, 6.0.3.7, 6.0.4, 6.1.3.2, 6.1.4.7, 6.1.5.1, 6.1.6.1, 7.0.2.4, 7.0.3.1]
24
+ # Exclude combinations that are not supported.
24
25
  exclude:
25
26
  - ruby: 3.0
26
27
  ar: 6.0.0
@@ -32,16 +33,24 @@ jobs:
32
33
  ar: 6.0.3.7
33
34
  - ruby: 3.0
34
35
  ar: 6.0.4
36
+ - ruby: 2.5
37
+ ar: 7.0.2.4
38
+ - ruby: 2.6
39
+ ar: 7.0.2.4
40
+ - ruby: 2.5
41
+ ar: 7.0.3.1
42
+ - ruby: 2.6
43
+ ar: 7.0.3.1
44
+ env:
45
+ AR_VERSION: ${{ matrix.ar }}
35
46
  steps:
36
- - uses: actions/checkout@v2
47
+ - uses: actions/checkout@v3
37
48
  - name: Set up Ruby
38
49
  uses: ruby/setup-ruby@v1
39
50
  with:
40
51
  # Disable caching as we are overriding the ActiveRecord below.
41
52
  bundler-cache: false
42
53
  ruby-version: ${{ matrix.ruby }}
43
- - name: Set ActiveRecord version
44
- run: sed -i "s/\"activerecord\", \"~> 6.1.4\"/\"activerecord\", \"${{ matrix.ar }}\"/" activerecord-spanner-adapter.gemspec
45
54
  - name: Install dependencies
46
55
  run: bundle install
47
56
  - name: Run acceptance tests on emulator
@@ -12,7 +12,7 @@ jobs:
12
12
  matrix:
13
13
  ruby: [3.0]
14
14
  steps:
15
- - uses: actions/checkout@v2
15
+ - uses: actions/checkout@v3
16
16
  - name: Set up Ruby
17
17
  # To automatically get bug fixes and new Ruby versions for ruby/setup-ruby
18
18
  # (see https://github.com/ruby/setup-ruby#versioning):
@@ -21,7 +21,7 @@ jobs:
21
21
  bundler-cache: true
22
22
  ruby-version: ${{ matrix.ruby }}
23
23
  - name: Setup GCloud
24
- uses: google-github-actions/setup-gcloud@master
24
+ uses: google-github-actions/setup-gcloud@v0
25
25
  with:
26
26
  project_id: ${{ secrets.GCP_PROJECT_ID }}
27
27
  service_account_key: ${{ secrets.GCP_SA_KEY }}
@@ -2,6 +2,7 @@ on:
2
2
  schedule:
3
3
  # 05:30 UTC
4
4
  - cron: '30 5 * * *'
5
+ workflow_dispatch:
5
6
  name: nightly-unit-tests
6
7
  jobs:
7
8
  test:
@@ -11,8 +12,8 @@ jobs:
11
12
  matrix:
12
13
  # Run unit tests all supported combinations of Ruby and ActiveRecord.
13
14
  ruby: [2.5, 2.6, 2.7, 3.0]
14
- ar: [6.0.0, 6.0.1, 6.0.2.2, 6.0.3.7, 6.0.4, 6.1.0, 6.1.1, 6.1.2.1, 6.1.3.2, 6.1.4]
15
- # Exclude Ruby 3.0 and ActiveRecord 6.0.x as that combination is not supported.
15
+ ar: [6.0.0, 6.0.1, 6.0.2.2, 6.0.3.7, 6.0.4, 6.1.3.2, 6.1.4.7, 6.1.5.1, 6.1.6.1, 7.0.2.4, 7.0.3.1]
16
+ # Exclude combinations that are not supported.
16
17
  exclude:
17
18
  - ruby: 3.0
18
19
  ar: 6.0.0
@@ -24,16 +25,24 @@ jobs:
24
25
  ar: 6.0.3.7
25
26
  - ruby: 3.0
26
27
  ar: 6.0.4
28
+ - ruby: 2.5
29
+ ar: 7.0.2.4
30
+ - ruby: 2.6
31
+ ar: 7.0.2.4
32
+ - ruby: 2.5
33
+ ar: 7.0.3.1
34
+ - ruby: 2.6
35
+ ar: 7.0.3.1
36
+ env:
37
+ AR_VERSION: ${{ matrix.ar }}
27
38
  steps:
28
- - uses: actions/checkout@v2
39
+ - uses: actions/checkout@v3
29
40
  - name: Set up Ruby
30
41
  uses: ruby/setup-ruby@v1
31
42
  with:
32
43
  # Disable caching as we are overriding the ActiveRecord below.
33
44
  bundler-cache: false
34
45
  ruby-version: ${{ matrix.ruby }}
35
- - name: Set ActiveRecord version
36
- run: sed -i "s/\"activerecord\", \"~> 6.1.4\"/\"activerecord\", \"${{ matrix.ar }}\"/" activerecord-spanner-adapter.gemspec
37
46
  - name: Install dependencies
38
47
  run: bundle install
39
48
  - name: Run tests
@@ -20,13 +20,13 @@ jobs:
20
20
  RELEASE_PLEASE_DISABLE: ${{ secrets.RELEASE_PLEASE_DISABLE }}
21
21
  steps:
22
22
  - name: Checkout repo
23
- uses: actions/checkout@v2
23
+ uses: actions/checkout@v3
24
24
  - name: Install Ruby 3.0
25
25
  uses: ruby/setup-ruby@v1
26
26
  with:
27
27
  ruby-version: "3.0"
28
28
  - name: Install NodeJS 16.x
29
- uses: actions/setup-node@v2
29
+ uses: actions/setup-node@v3
30
30
  with:
31
31
  node-version: "16.x"
32
32
  - name: Install tools
@@ -12,13 +12,13 @@ jobs:
12
12
  timeout-minutes: 10
13
13
 
14
14
  steps:
15
- - uses: actions/checkout@v2
15
+ - uses: actions/checkout@v3
16
16
  - name: setup ruby
17
17
  uses: ruby/setup-ruby@v1
18
18
  with:
19
- ruby-version: '2.5'
19
+ ruby-version: '2.7'
20
20
  - name: cache gems
21
- uses: actions/cache@v2
21
+ uses: actions/cache@v3
22
22
  with:
23
23
  path: vendor/bundle
24
24
  key: ${{ runner.os }}-rubocop-${{ hashFiles('**/Gemfile.lock') }}
data/.kokoro/release.sh CHANGED
@@ -7,9 +7,7 @@ set -eo pipefail
7
7
  export GEM_HOME=$HOME/.gem
8
8
  export PATH=$GEM_HOME/bin:$PATH
9
9
 
10
- python3 -m pip install git+https://github.com/googleapis/releasetool
11
- python3 -m pip install gcp-docuploader
12
10
  gem install --no-document toys
13
-
11
+ toys release install-python-tools -v
14
12
  python3 -m releasetool publish-reporter-script > /tmp/publisher-script; source /tmp/publisher-script
15
13
  toys release perform -v --enable-docs < /dev/null
@@ -1,3 +1,3 @@
1
1
  {
2
- ".": "1.0.1"
2
+ ".": "1.2.1"
3
3
  }
data/.toys/release.rb CHANGED
@@ -14,5 +14,11 @@
14
14
  # See the License for the specific language governing permissions and
15
15
  # limitations under the License.
16
16
 
17
- load_git remote: "https://github.com/googleapis/ruby-common-tools.git",
18
- path: "toys/release"
17
+ if ENV["RUBY_COMMON_TOOLS"]
18
+ common_tools_dir = File.expand_path ENV["RUBY_COMMON_TOOLS"]
19
+ load File.join(common_tools_dir, "toys", "release")
20
+ else
21
+ load_git remote: "https://github.com/googleapis/ruby-common-tools.git",
22
+ path: "toys/release",
23
+ update: true
24
+ end
data/CHANGELOG.md CHANGED
@@ -1,5 +1,23 @@
1
1
  # Changelog
2
2
 
3
+ ### 1.2.1 (2022-08-28)
4
+
5
+ #### Bug Fixes
6
+
7
+ * Corrected the namespace for the transaction selector class ([#187](https://github.com/googleapis/ruby-spanner-activerecord/issues/187))
8
+
9
+ ### 1.2.0 (2022-08-03)
10
+
11
+ #### Features
12
+
13
+ * support composite primary keys for interleaved tables ([#175](https://github.com/googleapis/ruby-spanner-activerecord/issues/175))
14
+
15
+ ### 1.1.0 (2022-06-24)
16
+
17
+ #### Features
18
+
19
+ * Support insert_all and upsert_all with DML and mutations
20
+
3
21
  ### 1.0.1 (2022-04-21)
4
22
 
5
23
  #### Bug Fixes
data/Gemfile CHANGED
@@ -3,10 +3,14 @@ source "https://rubygems.org"
3
3
  # Specify your gem's dependencies in activerecord-spanner.gemspec
4
4
  gemspec
5
5
 
6
+ gem "activerecord", ENV.fetch("AR_VERSION", "~> 6.1.6.1")
6
7
  gem "minitest", "~> 5.15.0"
7
8
  gem "pry", "~> 0.13.0"
8
9
  gem "pry-byebug", "~> 3.9.0"
9
10
 
11
+ # Required for samples and testing.
12
+ gem "composite_primary_keys"
13
+
10
14
  # Required for samples
11
- gem 'docker-api'
15
+ gem "docker-api"
12
16
  gem "sinatra-activerecord"
@@ -20,6 +20,8 @@ module ActiveRecord
20
20
 
21
21
  def setup
22
22
  super
23
+ @original_verbosity = $VERBOSE
24
+ $VERBOSE = nil
23
25
 
24
26
  @singer = Singer.create first_name: "FirstName1", last_name: "LastName1"
25
27
 
@@ -35,6 +37,8 @@ module ActiveRecord
35
37
  def teardown
36
38
  Album.destroy_all
37
39
  Singer.destroy_all
40
+
41
+ $VERBOSE = @original_verbosity
38
42
  end
39
43
 
40
44
  def test_has_many
@@ -73,8 +77,8 @@ module ActiveRecord
73
77
 
74
78
  def test_create_and_destroy_associated_records
75
79
  singer2 = Singer.new first_name: "First", last_name: "Last"
76
- singer2.albums.build title: "New Title 1"
77
- singer2.albums.build title: "New Title 2"
80
+ singer2.albums.build title: "New Title 1", albumid: Album.next_sequence_value
81
+ singer2.albums.build title: "New Title 2", albumid: Album.next_sequence_value
78
82
  singer2.save!
79
83
 
80
84
  singer2.reload
@@ -91,8 +95,8 @@ module ActiveRecord
91
95
 
92
96
  def test_create_and_destroy_nested_associated_records
93
97
  album3 = Album.new singer: singer, title: "Title 3"
94
- album3.tracks.build title: "Title3_1", duration: 2.5, singer: singer
95
- album3.tracks.build title: "Title3_2", singer: singer
98
+ album3.tracks.build title: "Title3_1", duration: 2.5, singer: singer, trackid: Track.next_sequence_value
99
+ album3.tracks.build title: "Title3_2", singer: singer, trackid: Track.next_sequence_value
96
100
  album3.save!
97
101
 
98
102
  album3.reload
@@ -110,8 +114,8 @@ module ActiveRecord
110
114
 
111
115
  def test_create_and_delete_associated_records
112
116
  singer2 = Singer.new first_name: "First", last_name: "Last"
113
- singer2.albums.build title: "Album - 11"
114
- singer2.albums.build title: "Album - 12"
117
+ singer2.albums.build title: "Album - 11", albumid: Album.next_sequence_value
118
+ singer2.albums.build title: "Album - 12", albumid: Album.next_sequence_value
115
119
  singer2.save!
116
120
 
117
121
  singer2.reload
@@ -128,8 +132,8 @@ module ActiveRecord
128
132
 
129
133
  def test_create_and_delete_nested_associated_records
130
134
  album3 = Album.new title: "Album 3", singer: singer
131
- album3.tracks.build title: "Track - 31", singer: singer
132
- album3.tracks.build title: "Track - 32", singer: singer
135
+ album3.tracks.build title: "Track - 31", singer: singer, trackid: Track.next_sequence_value
136
+ album3.tracks.build title: "Track - 32", singer: singer, trackid: Track.next_sequence_value
133
137
  album3.save!
134
138
 
135
139
  album3.reload
@@ -0,0 +1,150 @@
1
+ # Copyright 2022 Google LLC
2
+ #
3
+ # Use of this source code is governed by an MIT-style
4
+ # license that can be found in the LICENSE file or at
5
+ # https://opensource.org/licenses/MIT.
6
+
7
+ # frozen_string_literal: true
8
+
9
+ require "test_helper"
10
+ require "models/author"
11
+
12
+ module ActiveRecord
13
+ module Model
14
+ class InsertAllTest < SpannerAdapter::TestCase
15
+ include SpannerAdapter::Associations::TestHelper
16
+
17
+ def setup
18
+ super
19
+ end
20
+
21
+ def teardown
22
+ super
23
+ Author.destroy_all
24
+ end
25
+
26
+ def test_insert_all
27
+ values = [
28
+ { id: Author.next_sequence_value, name: "Alice" },
29
+ { id: Author.next_sequence_value, name: "Bob" },
30
+ { id: Author.next_sequence_value, name: "Carol" },
31
+ ]
32
+
33
+ assert_raise(NotImplementedError) { Author.insert_all(values) }
34
+ end
35
+
36
+ def test_insert_all!
37
+ values = [
38
+ { id: Author.next_sequence_value, name: "Alice" },
39
+ { id: Author.next_sequence_value, name: "Bob" },
40
+ { id: Author.next_sequence_value, name: "Carol" },
41
+ ]
42
+
43
+ Author.insert_all!(values)
44
+
45
+ authors = Author.all.order(:name)
46
+
47
+ assert_equal "Alice", authors[0].name
48
+ assert_equal "Bob", authors[1].name
49
+ assert_equal "Carol", authors[2].name
50
+ end
51
+
52
+ def test_insert_all_with_transaction
53
+ values = [
54
+ { id: Author.next_sequence_value, name: "Alice" },
55
+ { id: Author.next_sequence_value, name: "Bob" },
56
+ { id: Author.next_sequence_value, name: "Carol" },
57
+ ]
58
+
59
+ ActiveRecord::Base.transaction do
60
+ Author.insert_all!(values)
61
+ end
62
+
63
+ authors = Author.all.order(:name)
64
+
65
+ assert_equal "Alice", authors[0].name
66
+ assert_equal "Bob", authors[1].name
67
+ assert_equal "Carol", authors[2].name
68
+ end
69
+
70
+ def test_insert_all_with_buffered_mutation_transaction
71
+ values = [
72
+ { id: Author.next_sequence_value, name: "Alice" },
73
+ { id: Author.next_sequence_value, name: "Bob" },
74
+ { id: Author.next_sequence_value, name: "Carol" },
75
+ ]
76
+
77
+ ActiveRecord::Base.transaction isolation: :buffered_mutations do
78
+ Author.insert_all!(values)
79
+ end
80
+
81
+ authors = Author.all.order(:name)
82
+
83
+ assert_equal "Alice", authors[0].name
84
+ assert_equal "Bob", authors[1].name
85
+ assert_equal "Carol", authors[2].name
86
+ end
87
+
88
+ def test_upsert_all
89
+ Author.create id: 1, name: "David"
90
+ authors = Author.all.order(:name)
91
+ assert_equal 1, authors.length
92
+ assert_equal "David", authors[0].name
93
+
94
+ values = [
95
+ { id: 1, name: "Alice" },
96
+ { id: 2, name: "Bob" },
97
+ { id: 3, name: "Carol" },
98
+ ]
99
+
100
+ Author.upsert_all(values)
101
+
102
+ authors = Author.all.order(:name)
103
+
104
+ assert_equal 3, authors.length
105
+ assert_equal "Alice", authors[0].name
106
+ assert_equal "Bob", authors[1].name
107
+ assert_equal "Carol", authors[2].name
108
+ end
109
+
110
+ def test_upsert_all_with_transaction
111
+ values = [
112
+ { id: Author.next_sequence_value, name: "Alice" },
113
+ { id: Author.next_sequence_value, name: "Bob" },
114
+ { id: Author.next_sequence_value, name: "Carol" },
115
+ ]
116
+
117
+ err = assert_raise(NotImplementedError) do
118
+ ActiveRecord::Base.transaction do
119
+ Author.upsert_all(values)
120
+ end
121
+ end
122
+ assert_match "Use upsert outside a transaction block", err.message
123
+ end
124
+
125
+ def test_upsert_all_with_buffered_mutation_transaction
126
+ Author.create id: 1, name: "David"
127
+ authors = Author.all.order(:name)
128
+ assert_equal 1, authors.length
129
+ assert_equal "David", authors[0].name
130
+
131
+ values = [
132
+ { id: 1, name: "Alice" },
133
+ { id: 2, name: "Bob" },
134
+ { id: 3, name: "Carol" },
135
+ ]
136
+
137
+ ActiveRecord::Base.transaction isolation: :buffered_mutations do
138
+ Author.upsert_all(values)
139
+ end
140
+
141
+ authors = Author.all.order(:name)
142
+
143
+ assert_equal 3, authors.length
144
+ assert_equal "Alice", authors[0].name
145
+ assert_equal "Bob", authors[1].name
146
+ assert_equal "Carol", authors[2].name
147
+ end
148
+ end
149
+ end
150
+ end
@@ -19,6 +19,9 @@ module ActiveRecord
19
19
  def setup
20
20
  super
21
21
 
22
+ @original_verbosity = $VERBOSE
23
+ $VERBOSE = nil
24
+
22
25
  singer = Singer.create first_name: "Pete", last_name: "Allison"
23
26
  album = Album.create title: "Musical Jeans", singer: singer
24
27
  Track.create title: "Increased Headline", album: album, singer: singer
@@ -30,6 +33,8 @@ module ActiveRecord
30
33
  Track.delete_all
31
34
  Album.delete_all
32
35
  Singer.delete_all
36
+
37
+ $VERBOSE = @original_verbosity
33
38
  end
34
39
 
35
40
  # Runs the given block in a transaction with the given isolation level, or without a transaction if isolation is
@@ -30,7 +30,7 @@ module ActiveRecord
30
30
  AllTypes.create col_string: "string", col_int64: 100, col_float64: 3.14, col_numeric: 6.626, col_bool: true,
31
31
  col_bytes: StringIO.new("bytes"), col_date: ::Date.new(2021, 6, 23),
32
32
  col_timestamp: ::Time.new(2021, 6, 23, 17, 8, 21, "+02:00"),
33
- col_json: ENV["SPANNER_EMULATOR_HOST"] ? "" : { kind: "user_renamed", change: %w[jack john]},
33
+ col_json: { kind: "user_renamed", change: %w[jack john]},
34
34
  col_array_string: ["string1", nil, "string2"],
35
35
  col_array_int64: [100, nil, 200, "300"],
36
36
  col_array_float64: [3.14, nil, 2.0/3.0, "3.14"],
@@ -40,8 +40,7 @@ module ActiveRecord
40
40
  col_array_date: [::Date.new(2021, 6, 23), nil, ::Date.new(2021, 6, 24), "2021-06-25"],
41
41
  col_array_timestamp: [::Time.new(2021, 6, 23, 17, 8, 21, "+02:00"), nil, \
42
42
  ::Time.new(2021, 6, 24, 17, 8, 21, "+02:00"), "2021-06-25 17:08:21 +02:00"],
43
- col_array_json: ENV["SPANNER_EMULATOR_HOST"] ? [""] : \
44
- [{ kind: "user_renamed", change: %w[jack john]}, nil, \
43
+ col_array_json: [{ kind: "user_renamed", change: %w[jack john]}, nil, \
45
44
  { kind: "user_renamed", change: %w[alice meredith]},
46
45
  "{\"kind\":\"user_renamed\",\"change\":[\"bob\",\"carol\"]}"]
47
46
  end
@@ -67,7 +66,7 @@ module ActiveRecord
67
66
  assert_equal ::Date.new(2021, 6, 23), record.col_date
68
67
  assert_equal ::Time.new(2021, 6, 23, 17, 8, 21, "+02:00").utc, record.col_timestamp.utc
69
68
  assert_equal ({"kind" => "user_renamed", "change" => %w[jack john]}),
70
- record.col_json unless ENV["SPANNER_EMULATOR_HOST"]
69
+ record.col_json
71
70
 
72
71
  assert_equal ["string1", nil, "string2"], record.col_array_string
73
72
  assert_equal [100, nil, 200, 300], record.col_array_int64
@@ -83,9 +82,9 @@ module ActiveRecord
83
82
  record.col_array_timestamp.map { |timestamp| timestamp&.utc}
84
83
  assert_equal [{"kind" => "user_renamed", "change" => %w[jack john]}, \
85
84
  nil, \
86
- {"kind" => "user_renamed", "change" => %w[alice meredith]},
87
- {"kind" => "user_renamed", "change" => %w[bob carol]}],
88
- record.col_array_json unless ENV["SPANNER_EMULATOR_HOST"]
85
+ {"kind" => "user_renamed", "change" => %w[alice meredith]}, \
86
+ "{\"kind\":\"user_renamed\",\"change\":[\"bob\",\"carol\"]}"],
87
+ record.col_array_json
89
88
  end
90
89
  end
91
90
 
@@ -100,7 +99,7 @@ module ActiveRecord
100
99
  col_bool: false, col_bytes: StringIO.new("new bytes"),
101
100
  col_date: ::Date.new(2021, 6, 28),
102
101
  col_timestamp: ::Time.new(2021, 6, 28, 11, 22, 21, "+02:00"),
103
- col_json: ENV["SPANNER_EMULATOR_HOST"] ? "" : { kind: "user_created", change: %w[jack alice]},
102
+ col_json: { kind: "user_created", change: %w[jack alice]},
104
103
  col_array_string: ["new string 1", "new string 2"],
105
104
  col_array_int64: [300, 200, 100],
106
105
  col_array_float64: [1.1, 2.2, 3.3],
@@ -109,9 +108,7 @@ module ActiveRecord
109
108
  col_array_bytes: [StringIO.new("new bytes 1"), StringIO.new("new bytes 2")],
110
109
  col_array_date: [::Date.new(2021, 6, 28)],
111
110
  col_array_timestamp: [::Time.utc(2020, 12, 31, 0, 0, 0)],
112
- col_array_json: ENV["SPANNER_EMULATOR_HOST"] ?
113
- [""] : \
114
- [{ kind: "user_created", change: %w[jack alice]}]
111
+ col_array_json: [{ kind: "user_created", change: %w[jack alice]}]
115
112
  end
116
113
 
117
114
  # Verify that the record was updated.
@@ -125,7 +122,7 @@ module ActiveRecord
125
122
  assert_equal ::Date.new(2021, 6, 28), record.col_date
126
123
  assert_equal ::Time.new(2021, 6, 28, 11, 22, 21, "+02:00").utc, record.col_timestamp.utc
127
124
  assert_equal ({"kind" => "user_created", "change" => %w[jack alice]}),
128
- record.col_json unless ENV["SPANNER_EMULATOR_HOST"]
125
+ record.col_json
129
126
 
130
127
  assert_equal ["new string 1", "new string 2"], record.col_array_string
131
128
  assert_equal [300, 200, 100], record.col_array_int64
@@ -137,7 +134,7 @@ module ActiveRecord
137
134
  assert_equal [::Date.new(2021, 6, 28)], record.col_array_date
138
135
  assert_equal [::Time.utc(2020, 12, 31, 0, 0, 0)], record.col_array_timestamp.map(&:utc)
139
136
  assert_equal [{"kind" => "user_created", "change" => %w[jack alice]}],
140
- record.col_array_json unless ENV["SPANNER_EMULATOR_HOST"]
137
+ record.col_array_json
141
138
  end
142
139
  end
143
140
 
@@ -18,8 +18,6 @@ module ActiveRecord
18
18
  end
19
19
 
20
20
  def test_set_json
21
- return if ENV["SPANNER_EMULATOR_HOST"]
22
-
23
21
  expected_hash = {"key"=>"value", "array_key"=>%w[value1 value2]}
24
22
  record = TestTypeModel.new details: {key: "value", array_key: %w[value1 value2]}
25
23