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.
- checksums.yaml +4 -4
- data/.github/CODEOWNERS +1 -1
- data/.github/sync-repo-settings.yaml +2 -2
- data/.github/workflows/acceptance-tests-on-emulator.yaml +10 -6
- data/.github/workflows/acceptance-tests-on-production.yaml +1 -1
- data/.github/workflows/ci.yaml +10 -8
- data/.github/workflows/nightly-acceptance-tests-on-emulator.yaml +14 -5
- data/.github/workflows/nightly-acceptance-tests-on-production.yaml +2 -2
- data/.github/workflows/nightly-unit-tests.yaml +14 -5
- data/.github/workflows/release-please.yml +2 -2
- data/.github/workflows/rubocop.yaml +3 -3
- data/.kokoro/release.sh +1 -3
- data/.release-please-manifest.json +1 -1
- data/.toys/release.rb +8 -2
- data/CHANGELOG.md +18 -0
- data/Gemfile +5 -1
- data/acceptance/cases/interleaved_associations/has_many_associations_using_interleaved_test.rb +12 -8
- data/acceptance/cases/models/insert_all_test.rb +150 -0
- data/acceptance/cases/transactions/optimistic_locking_test.rb +5 -0
- data/acceptance/cases/type/all_types_test.rb +10 -13
- data/acceptance/cases/type/json_test.rb +0 -2
- data/acceptance/models/album.rb +7 -2
- data/acceptance/models/singer.rb +2 -2
- data/acceptance/models/track.rb +5 -2
- data/acceptance/schema/schema.rb +2 -4
- data/acceptance/test_helper.rb +1 -1
- data/activerecord-spanner-adapter.gemspec +1 -1
- data/examples/snippets/interleaved-tables/README.md +164 -0
- data/examples/snippets/interleaved-tables/Rakefile +13 -0
- data/examples/snippets/interleaved-tables/application.rb +126 -0
- data/examples/snippets/interleaved-tables/config/database.yml +8 -0
- data/examples/snippets/interleaved-tables/db/migrate/01_create_tables.rb +44 -0
- data/examples/snippets/interleaved-tables/db/schema.rb +32 -0
- data/examples/snippets/interleaved-tables/db/seeds.rb +40 -0
- data/examples/snippets/interleaved-tables/models/album.rb +20 -0
- data/examples/snippets/interleaved-tables/models/singer.rb +18 -0
- data/examples/snippets/interleaved-tables/models/track.rb +28 -0
- data/lib/active_record/connection_adapters/spanner/schema_creation.rb +10 -4
- data/lib/active_record/connection_adapters/spanner_adapter.rb +64 -31
- data/lib/activerecord_spanner_adapter/base.rb +150 -17
- data/lib/activerecord_spanner_adapter/connection.rb +1 -1
- data/lib/activerecord_spanner_adapter/relation.rb +21 -0
- data/lib/activerecord_spanner_adapter/transaction.rb +4 -4
- data/lib/activerecord_spanner_adapter/version.rb +1 -1
- data/lib/arel/visitors/spanner.rb +10 -0
- metadata +25 -7
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 5f8199e1af804baf47d382e53404f88329478d35958f71fcaec34f73921de987
|
4
|
+
data.tar.gz: b2bc3919e5cc4d675d539806c27e0dda7b16d676ca349aa95a11370c4ec145b7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
-
* @
|
7
|
+
* @googleapis/ruby-team @skuruppu @hengfengli @olavloite @xiangshen-dk
|
@@ -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.
|
23
|
-
# Exclude
|
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.
|
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@
|
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@
|
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):
|
data/.github/workflows/ci.yaml
CHANGED
@@ -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
|
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@
|
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.
|
23
|
-
# Exclude
|
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@
|
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@
|
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@
|
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.
|
15
|
-
# Exclude
|
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@
|
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@
|
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@
|
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@
|
15
|
+
- uses: actions/checkout@v3
|
16
16
|
- name: setup ruby
|
17
17
|
uses: ruby/setup-ruby@v1
|
18
18
|
with:
|
19
|
-
ruby-version: '2.
|
19
|
+
ruby-version: '2.7'
|
20
20
|
- name: cache gems
|
21
|
-
uses: actions/cache@
|
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
|
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
|
-
|
18
|
-
|
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
|
15
|
+
gem "docker-api"
|
12
16
|
gem "sinatra-activerecord"
|
data/acceptance/cases/interleaved_associations/has_many_associations_using_interleaved_test.rb
CHANGED
@@ -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:
|
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:
|
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
|
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"
|
88
|
-
record.col_array_json
|
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:
|
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:
|
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
|
-
|
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
|
137
|
+
record.col_array_json
|
141
138
|
end
|
142
139
|
end
|
143
140
|
|