activerecord-spanner-adapter 1.0.1 → 1.2.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/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
|
|