activerecord-spanner-adapter 1.5.0 → 1.6.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.github/workflows/acceptance-tests-on-emulator.yaml +1 -1
- data/.github/workflows/acceptance-tests-on-production.yaml +5 -3
- data/.github/workflows/ci.yaml +1 -1
- data/.github/workflows/nightly-acceptance-tests-on-emulator.yaml +1 -1
- data/.github/workflows/nightly-acceptance-tests-on-production.yaml +5 -3
- data/.github/workflows/nightly-unit-tests.yaml +1 -1
- data/.github/workflows/release-please-label.yml +1 -1
- data/.release-please-manifest.json +1 -1
- data/CHANGELOG.md +14 -0
- data/Gemfile +5 -2
- data/README.md +10 -10
- data/acceptance/cases/interleaved_associations/has_many_associations_using_interleaved_test.rb +6 -0
- data/acceptance/cases/migration/change_schema_test.rb +19 -3
- data/acceptance/cases/migration/schema_dumper_test.rb +10 -1
- data/acceptance/cases/models/insert_all_test.rb +22 -0
- data/acceptance/cases/models/interleave_test.rb +6 -0
- data/acceptance/cases/tasks/database_tasks_test.rb +340 -2
- data/acceptance/cases/transactions/optimistic_locking_test.rb +6 -0
- data/acceptance/cases/transactions/read_write_transactions_test.rb +24 -0
- data/acceptance/models/table_with_sequence.rb +10 -0
- data/acceptance/schema/schema.rb +65 -19
- data/acceptance/test_helper.rb +1 -1
- data/activerecord-spanner-adapter.gemspec +1 -1
- data/examples/snippets/bit-reversed-sequence/README.md +103 -0
- data/examples/snippets/bit-reversed-sequence/Rakefile +13 -0
- data/examples/snippets/bit-reversed-sequence/application.rb +68 -0
- data/examples/snippets/bit-reversed-sequence/config/database.yml +8 -0
- data/examples/snippets/bit-reversed-sequence/db/migrate/01_create_tables.rb +33 -0
- data/examples/snippets/bit-reversed-sequence/db/schema.rb +31 -0
- data/examples/snippets/bit-reversed-sequence/db/seeds.rb +31 -0
- data/examples/snippets/bit-reversed-sequence/models/album.rb +11 -0
- data/examples/snippets/bit-reversed-sequence/models/singer.rb +15 -0
- data/examples/snippets/interleaved-tables/README.md +44 -53
- data/examples/snippets/interleaved-tables/Rakefile +2 -2
- data/examples/snippets/interleaved-tables/application.rb +2 -2
- data/examples/snippets/interleaved-tables/db/migrate/01_create_tables.rb +12 -18
- data/examples/snippets/interleaved-tables/db/schema.rb +9 -7
- data/examples/snippets/interleaved-tables/db/seeds.rb +1 -1
- data/examples/snippets/interleaved-tables/models/album.rb +3 -7
- data/examples/snippets/interleaved-tables/models/singer.rb +1 -1
- data/examples/snippets/interleaved-tables/models/track.rb +6 -7
- data/examples/snippets/interleaved-tables-before-7.1/README.md +167 -0
- data/examples/snippets/interleaved-tables-before-7.1/Rakefile +13 -0
- data/examples/snippets/interleaved-tables-before-7.1/application.rb +126 -0
- data/examples/snippets/interleaved-tables-before-7.1/config/database.yml +8 -0
- data/examples/snippets/interleaved-tables-before-7.1/db/migrate/01_create_tables.rb +44 -0
- data/examples/snippets/interleaved-tables-before-7.1/db/schema.rb +37 -0
- data/examples/snippets/interleaved-tables-before-7.1/db/seeds.rb +40 -0
- data/examples/snippets/interleaved-tables-before-7.1/models/album.rb +20 -0
- data/examples/snippets/interleaved-tables-before-7.1/models/singer.rb +18 -0
- data/examples/snippets/interleaved-tables-before-7.1/models/track.rb +28 -0
- data/examples/snippets/query-logs/README.md +43 -0
- data/examples/snippets/query-logs/Rakefile +13 -0
- data/examples/snippets/query-logs/application.rb +63 -0
- data/examples/snippets/query-logs/config/database.yml +8 -0
- data/examples/snippets/query-logs/db/migrate/01_create_tables.rb +21 -0
- data/examples/snippets/query-logs/db/schema.rb +31 -0
- data/examples/snippets/query-logs/db/seeds.rb +24 -0
- data/examples/snippets/query-logs/models/album.rb +9 -0
- data/examples/snippets/query-logs/models/singer.rb +9 -0
- data/lib/active_record/connection_adapters/spanner/column.rb +13 -0
- data/lib/active_record/connection_adapters/spanner/database_statements.rb +144 -35
- data/lib/active_record/connection_adapters/spanner/schema_cache.rb +3 -21
- data/lib/active_record/connection_adapters/spanner/schema_creation.rb +11 -0
- data/lib/active_record/connection_adapters/spanner/schema_definitions.rb +4 -0
- data/lib/active_record/connection_adapters/spanner/schema_statements.rb +3 -2
- data/lib/active_record/connection_adapters/spanner_adapter.rb +28 -9
- data/lib/activerecord_spanner_adapter/base.rb +58 -21
- data/lib/activerecord_spanner_adapter/information_schema.rb +33 -24
- data/lib/activerecord_spanner_adapter/primary_key.rb +1 -1
- data/lib/activerecord_spanner_adapter/table/column.rb +4 -9
- data/lib/activerecord_spanner_adapter/version.rb +1 -1
- data/lib/arel/visitors/spanner.rb +3 -1
- metadata +33 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2ad2384bb1890bb224c89a146c42f615f89c6e2892848da5e701a091d90fa95b
|
4
|
+
data.tar.gz: 0e8a9c608068ff30011bc9bca68b10ab0d22b910260a37a6d4a492365adf78b0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1894765bbc1e3dfac270d73199a4f235ae95724ca18145d6850cce27c38ef2018b59e9035cf2fa91bc30d3f650e080b8eea58c3e91a66035db3a4d07c35ca1be
|
7
|
+
data.tar.gz: 4a9b93d7990fa78f901864bed816e75ff5d0f9da34a530c7107f475d8fd06dc71817fbf8b2c1e0262e4656bf7ab363917ecf7b7c82315b6d5fa84cce0d22489d
|
@@ -34,12 +34,14 @@ jobs:
|
|
34
34
|
with:
|
35
35
|
bundler-cache: true
|
36
36
|
ruby-version: ${{ matrix.ruby }}
|
37
|
+
- name: Authenticate Google Cloud
|
38
|
+
uses: google-github-actions/auth@v2
|
39
|
+
with:
|
40
|
+
credentials_json: ${{ secrets.GCP_SA_KEY }}
|
37
41
|
- name: Setup GCloud
|
38
|
-
uses: google-github-actions/setup-gcloud@
|
42
|
+
uses: google-github-actions/setup-gcloud@v2
|
39
43
|
with:
|
40
44
|
project_id: ${{ secrets.GCP_PROJECT_ID }}
|
41
|
-
service_account_key: ${{ secrets.GCP_SA_KEY }}
|
42
|
-
export_default_credentials: true
|
43
45
|
- name: Install dependencies
|
44
46
|
run: bundle install
|
45
47
|
- name: Run acceptance tests on production
|
data/.github/workflows/ci.yaml
CHANGED
@@ -20,7 +20,7 @@ jobs:
|
|
20
20
|
matrix:
|
21
21
|
# Run acceptance tests all supported combinations of Ruby and ActiveRecord.
|
22
22
|
ruby: [2.7, 3.0, 3.1, 3.2]
|
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, 7.0.4, 7.0.5, 7.0.6, 7.0.7]
|
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, 7.0.4, 7.0.5, 7.0.6, 7.0.7, 7.1.0, 7.1.1, 7.1.2]
|
24
24
|
# Exclude combinations that are not supported.
|
25
25
|
exclude:
|
26
26
|
- ruby: 3.0
|
@@ -20,12 +20,14 @@ jobs:
|
|
20
20
|
with:
|
21
21
|
bundler-cache: true
|
22
22
|
ruby-version: ${{ matrix.ruby }}
|
23
|
+
- name: Authenticate Google Cloud
|
24
|
+
uses: google-github-actions/auth@v2
|
25
|
+
with:
|
26
|
+
credentials_json: ${{ secrets.GCP_SA_KEY }}
|
23
27
|
- name: Setup GCloud
|
24
|
-
uses: google-github-actions/setup-gcloud@
|
28
|
+
uses: google-github-actions/setup-gcloud@v2
|
25
29
|
with:
|
26
30
|
project_id: ${{ secrets.GCP_PROJECT_ID }}
|
27
|
-
service_account_key: ${{ secrets.GCP_SA_KEY }}
|
28
|
-
export_default_credentials: true
|
29
31
|
- name: Install dependencies
|
30
32
|
run: bundle install
|
31
33
|
- name: Run acceptance tests on production
|
@@ -12,7 +12,7 @@ jobs:
|
|
12
12
|
matrix:
|
13
13
|
# Run unit tests all supported combinations of Ruby and ActiveRecord.
|
14
14
|
ruby: [2.7, 3.0, 3.1, 3.2]
|
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, 7.0.4, 7.0.5]
|
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, 7.0.4, 7.0.5, 7.1.0, 7.1.1, 7.1.2]
|
16
16
|
# Exclude combinations that are not supported.
|
17
17
|
exclude:
|
18
18
|
- ruby: 3.0
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,19 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
### 1.6.0 (2023-12-20)
|
4
|
+
|
5
|
+
#### Features
|
6
|
+
|
7
|
+
* interleaved tables with built-in composite pk ([#282](https://github.com/googleapis/ruby-spanner-activerecord/issues/282))
|
8
|
+
* support Query Logs ([#291](https://github.com/googleapis/ruby-spanner-activerecord/issues/291))
|
9
|
+
* support Rails 7.1 ([#278](https://github.com/googleapis/ruby-spanner-activerecord/issues/278))
|
10
|
+
|
11
|
+
### 1.5.1 (2023-12-12)
|
12
|
+
|
13
|
+
#### Bug Fixes
|
14
|
+
|
15
|
+
* more permissive arg passthrough for insert_all and upsert_all ([#283](https://github.com/googleapis/ruby-spanner-activerecord/issues/283))
|
16
|
+
|
3
17
|
### 1.5.0 (2023-11-03)
|
4
18
|
|
5
19
|
#### Features
|
data/Gemfile
CHANGED
@@ -4,12 +4,15 @@ source "https://rubygems.org"
|
|
4
4
|
gemspec
|
5
5
|
|
6
6
|
gem "activerecord", ENV.fetch("AR_VERSION", "~> 6.1.6.1")
|
7
|
-
gem "minitest", "~> 5.
|
7
|
+
gem "minitest", "~> 5.20.0"
|
8
|
+
gem "minitest-rg", "~> 5.3.0"
|
8
9
|
gem "pry", "~> 0.13.0"
|
9
10
|
gem "pry-byebug", "~> 3.9.0"
|
10
11
|
|
11
12
|
# Required for samples and testing.
|
12
|
-
|
13
|
+
install_if -> { ENV.fetch("AR_VERSION", "~> 6.1.6.1").dup.to_s.sub!("~>", "").strip < "7.1.0" && !ENV["SKIP_COMPOSITE_PK"] } do
|
14
|
+
gem "composite_primary_keys"
|
15
|
+
end
|
13
16
|
|
14
17
|
# Required for samples
|
15
18
|
gem "docker-api"
|
data/README.md
CHANGED
@@ -84,19 +84,19 @@ Some noteworthy examples in the snippets directory:
|
|
84
84
|
for inserting, updating and deleting data in a Cloud Spanner database. Mutations can have a significant performance
|
85
85
|
advantage compared to DML statements, but do not allow read-your-writes semantics during a transaction.
|
86
86
|
- [array-data-type](examples/snippets/array-data-type): Shows how to work with `ARRAY` data types.
|
87
|
-
- [interleaved-tables](examples/snippets/interleaved-tables): Shows how to work with [Interleaved Tables](https://cloud.google.com/spanner/docs/schema-and-data-model#create-interleaved-tables).
|
87
|
+
- [interleaved-tables](examples/snippets/interleaved-tables-before-7.1): Shows how to work with [Interleaved Tables](https://cloud.google.com/spanner/docs/schema-and-data-model#create-interleaved-tables).
|
88
88
|
|
89
89
|
## Limitations
|
90
90
|
|
91
|
-
Limitation|Comment|Resolution
|
92
|
-
|
93
|
-
Interleaved tables require composite primary keys| Cloud Spanner requires composite primary keys for interleaved tables. See {file:examples/snippets/interleaved-tables/README.md this example} for an example on how to use interleaved tables with ActiveRecord
|
94
|
-
Lack of sequential
|
95
|
-
Table without Primary Key| Cloud Spanner support does not support tables without a primary key
|
96
|
-
Table names CANNOT have spaces within them whether back-ticked or not|Cloud Spanner DOES NOT support tables with spaces in them for example `Entity ID
|
97
|
-
Table names CANNOT have punctuation marks and MUST contain valid UTF-8|Cloud Spanner DOES NOT support punctuation marks e.g. periods ".", question marks "?" in table names|Ensure that your table names don't contain punctuation marks.
|
98
|
-
Index with fields length [add_index](https://apidock.com/rails/v5.2.3/ActiveRecord/ConnectionAdapters/SchemaStatements/add_index)|Cloud Spanner does not support index with fields length
|
99
|
-
Only GoogleSQL-dialect databases| Cloud Spanner supports both GoogleSQL- and PostgreSQL-dialect databases. This adapter only supports GoogleSQL-dialect databases.
|
91
|
+
| Limitation | Comment | Resolution |
|
92
|
+
|-----------------------------------------------------------------------------------------------------------------------------------|-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------|
|
93
|
+
| Interleaved tables require composite primary keys | Cloud Spanner requires composite primary keys for interleaved tables. See {file:examples/snippets/interleaved-tables/README.md this example} for an example on how to use interleaved tables with ActiveRecord | Use composite primary keys. |
|
94
|
+
| Lack of sequential IDs | Cloud Spanner uses either using bit-reversed sequences or UUID4 to generated primary keys to avoid [hotspotting](https://cloud.google.com/spanner/docs/schema-design#uuid_primary_key) so you SHOULD NOT rely on IDs being sorted | Use either UUID4s or bit-reversed sequences to automatically generate primary keys. |
|
95
|
+
| Table without Primary Key | Cloud Spanner support does not support tables without a primary key. | Always define a primary key for your table. |
|
96
|
+
| Table names CANNOT have spaces within them whether back-ticked or not | Cloud Spanner DOES NOT support tables with spaces in them for example `Entity ID` | Ensure that your table names don't contain spaces. |
|
97
|
+
| Table names CANNOT have punctuation marks and MUST contain valid UTF-8 | Cloud Spanner DOES NOT support punctuation marks e.g. periods ".", question marks "?" in table names | Ensure that your table names don't contain punctuation marks. |
|
98
|
+
| Index with fields length [add_index](https://apidock.com/rails/v5.2.3/ActiveRecord/ConnectionAdapters/SchemaStatements/add_index) | Cloud Spanner does not support index with fields length | Ensure that your database definition does not include index definitions with field lengths. |
|
99
|
+
| Only GoogleSQL-dialect databases | Cloud Spanner supports both GoogleSQL- and PostgreSQL-dialect databases. This adapter only supports GoogleSQL-dialect databases. | Ensure that your database uses the GoogleSQL dialect. |
|
100
100
|
|
101
101
|
## Contributing
|
102
102
|
|
data/acceptance/cases/interleaved_associations/has_many_associations_using_interleaved_test.rb
CHANGED
@@ -6,6 +6,12 @@
|
|
6
6
|
|
7
7
|
# frozen_string_literal: true
|
8
8
|
|
9
|
+
# ActiveRecord 7.1 introduced native support for composite primary keys.
|
10
|
+
# This deprecates the https://github.com/composite-primary-keys/composite_primary_keys gem that was previously used in
|
11
|
+
# this library to support composite primary keys, which again are needed for interleaved tables. These tests use the
|
12
|
+
# third-party composite primary key gem and are therefore not executed for Rails 7.1 and higher.
|
13
|
+
return if ActiveRecord::gem_version >= Gem::Version.create('7.1.0')
|
14
|
+
|
9
15
|
require "test_helper"
|
10
16
|
require "models/singer"
|
11
17
|
require "models/album"
|
@@ -196,8 +196,14 @@ module ActiveRecord
|
|
196
196
|
end
|
197
197
|
end
|
198
198
|
end
|
199
|
+
expected = if ActiveRecord::gem_version < Gem::Version.create('7.1.0')
|
200
|
+
"you can't redefine the primary key column 'id'. To define a custom primary key, pass { id: false } to create_table."
|
201
|
+
else
|
202
|
+
"you can't redefine the primary key column 'id' on 'testings'. To define a custom primary key, pass { id: false } to create_table."
|
203
|
+
end
|
204
|
+
|
199
205
|
|
200
|
-
assert_equal
|
206
|
+
assert_equal expected, error.message
|
201
207
|
end
|
202
208
|
|
203
209
|
def test_create_table_raises_when_redefining_custom_primary_key_column
|
@@ -209,7 +215,12 @@ module ActiveRecord
|
|
209
215
|
end
|
210
216
|
end
|
211
217
|
|
212
|
-
|
218
|
+
expected = if ActiveRecord::gem_version < Gem::Version.create('7.1.0')
|
219
|
+
"you can't redefine the primary key column 'testing_id'. To define a custom primary key, pass { id: false } to create_table."
|
220
|
+
else
|
221
|
+
"you can't redefine the primary key column 'testing_id' on 'testings'. To define a custom primary key, pass { id: false } to create_table."
|
222
|
+
end
|
223
|
+
assert_equal expected, error.message
|
213
224
|
end
|
214
225
|
|
215
226
|
def test_create_table_raises_when_defining_existing_column
|
@@ -222,7 +233,12 @@ module ActiveRecord
|
|
222
233
|
end
|
223
234
|
end
|
224
235
|
|
225
|
-
|
236
|
+
expected = if ActiveRecord::gem_version < Gem::Version.create('7.1.0')
|
237
|
+
"you can't define an already defined column 'testing_column'."
|
238
|
+
else
|
239
|
+
"you can't define an already defined column 'testing_column' on 'testings'."
|
240
|
+
end
|
241
|
+
assert_equal expected, error.message
|
226
242
|
end
|
227
243
|
|
228
244
|
def test_create_table_with_timestamps_should_create_datetime_columns
|
@@ -13,6 +13,10 @@ module ActiveRecord
|
|
13
13
|
class IndexTest < SpannerAdapter::TestCase
|
14
14
|
include SpannerAdapter::Migration::TestHelper
|
15
15
|
|
16
|
+
def is_7_1_or_higher?
|
17
|
+
ActiveRecord::gem_version >= Gem::Version.create('7.1.0')
|
18
|
+
end
|
19
|
+
|
16
20
|
def test_dump_schema_contains_start_batch_ddl
|
17
21
|
connection = ActiveRecord::Base.connection
|
18
22
|
schema = StringIO.new
|
@@ -34,7 +38,12 @@ module ActiveRecord
|
|
34
38
|
connection = ActiveRecord::Base.connection
|
35
39
|
schema = StringIO.new
|
36
40
|
ActiveRecord::SchemaDumper.dump connection, schema
|
37
|
-
|
41
|
+
sql = schema.string
|
42
|
+
if is_7_1_or_higher?
|
43
|
+
assert schema.string.include?("create_table \"albums\", primary_key: [\"singerid\", \"albumid\"]"), sql
|
44
|
+
else
|
45
|
+
assert schema.string.include?("create_table \"albums\", primary_key: \"albumid\""), sql
|
46
|
+
end
|
38
47
|
end
|
39
48
|
|
40
49
|
def test_dump_schema_contains_interleaved_index
|
@@ -33,6 +33,12 @@ module ActiveRecord
|
|
33
33
|
assert_raise(NotImplementedError) { Author.insert_all(values) }
|
34
34
|
end
|
35
35
|
|
36
|
+
def test_insert
|
37
|
+
value = { id: Author.next_sequence_value, name: "Alice" }
|
38
|
+
|
39
|
+
assert_raise(NotImplementedError) { Author.insert(value) }
|
40
|
+
end
|
41
|
+
|
36
42
|
def test_insert_all!
|
37
43
|
values = [
|
38
44
|
{ id: Author.next_sequence_value, name: "Alice" },
|
@@ -85,6 +91,22 @@ module ActiveRecord
|
|
85
91
|
assert_equal "Carol", authors[2].name
|
86
92
|
end
|
87
93
|
|
94
|
+
def test_upsert
|
95
|
+
Author.create id: 1, name: "David"
|
96
|
+
authors = Author.all.order(:name)
|
97
|
+
assert_equal 1, authors.length
|
98
|
+
assert_equal "David", authors[0].name
|
99
|
+
|
100
|
+
value = { id: 1, name: "Alice" }
|
101
|
+
|
102
|
+
Author.upsert(value)
|
103
|
+
|
104
|
+
authors = Author.all.order(:name)
|
105
|
+
|
106
|
+
assert_equal 1, authors.length
|
107
|
+
assert_equal "Alice", authors[0].name
|
108
|
+
end
|
109
|
+
|
88
110
|
def test_upsert_all
|
89
111
|
Author.create id: 1, name: "David"
|
90
112
|
authors = Author.all.order(:name)
|
@@ -6,6 +6,12 @@
|
|
6
6
|
|
7
7
|
# frozen_string_literal: true
|
8
8
|
|
9
|
+
# ActiveRecord 7.1 introduced native support for composite primary keys.
|
10
|
+
# This deprecates the https://github.com/composite-primary-keys/composite_primary_keys gem that was previously used in
|
11
|
+
# this library to support composite primary keys, which again are needed for interleaved tables. These tests use the
|
12
|
+
# third-party composite primary key gem and are therefore not executed for Rails 7.1 and higher.
|
13
|
+
return if ActiveRecord::gem_version >= Gem::Version.create('7.1.0')
|
14
|
+
|
9
15
|
require "test_helper"
|
10
16
|
require "test_helpers/with_separate_database"
|
11
17
|
|