activerecord-spanner-adapter 1.5.1 → 1.6.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +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 +8 -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/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 +56 -19
- 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,13 @@
|
|
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
|
+
|
3
11
|
### 1.5.1 (2023-12-12)
|
4
12
|
|
5
13
|
#### Bug Fixes
|
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
|
@@ -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
|
|
@@ -14,6 +14,10 @@ module ActiveRecord
|
|
14
14
|
class DatabaseTasksTest < SpannerAdapter::TestCase
|
15
15
|
attr_reader :connector_config, :connection
|
16
16
|
|
17
|
+
def is_7_1_or_higher?
|
18
|
+
ActiveRecord::gem_version >= Gem::Version.create('7.1.0')
|
19
|
+
end
|
20
|
+
|
17
21
|
def setup
|
18
22
|
@database_id = "ar-tasks-test-#{SecureRandom.hex 4}"
|
19
23
|
@connector_config = {
|
@@ -87,8 +91,12 @@ module ActiveRecord
|
|
87
91
|
end
|
88
92
|
ActiveRecord::Tasks::DatabaseTasks.dump_schema db_config, :sql
|
89
93
|
sql = File.read(filename)
|
90
|
-
if ENV["SPANNER_EMULATOR_HOST"]
|
94
|
+
if ENV["SPANNER_EMULATOR_HOST"] && is_7_1_or_higher?
|
95
|
+
assert_equal expected_schema_sql_on_emulator_7_1, sql, msg = sql
|
96
|
+
elsif ENV["SPANNER_EMULATOR_HOST"]
|
91
97
|
assert_equal expected_schema_sql_on_emulator, sql, msg = sql
|
98
|
+
elsif is_7_1_or_higher?
|
99
|
+
assert_equal expected_schema_sql_on_production_7_1, sql, msg = sql
|
92
100
|
else
|
93
101
|
assert_equal expected_schema_sql_on_production, sql, msg = sql
|
94
102
|
end
|
@@ -235,6 +243,168 @@ CREATE TABLE tracks (
|
|
235
243
|
) PRIMARY KEY(singerid, albumid, trackid),
|
236
244
|
INTERLEAVE IN PARENT albums ON DELETE CASCADE;
|
237
245
|
CREATE NULL_FILTERED INDEX index_tracks_on_singerid_and_albumid_and_title ON tracks(singerid, albumid, title), INTERLEAVE IN albums;
|
246
|
+
CREATE TABLE table_with_sequence (
|
247
|
+
id INT64 NOT NULL DEFAULT (FARM_FINGERPRINT(GENERATE_UUID())),
|
248
|
+
name STRING(MAX) NOT NULL,
|
249
|
+
age INT64 NOT NULL,
|
250
|
+
) PRIMARY KEY(id);
|
251
|
+
CREATE TABLE schema_migrations (
|
252
|
+
version STRING(MAX) NOT NULL,
|
253
|
+
) PRIMARY KEY(version);
|
254
|
+
CREATE TABLE ar_internal_metadata (
|
255
|
+
key STRING(MAX) NOT NULL,
|
256
|
+
value STRING(MAX),
|
257
|
+
created_at TIMESTAMP NOT NULL,
|
258
|
+
updated_at TIMESTAMP NOT NULL,
|
259
|
+
) PRIMARY KEY(key);
|
260
|
+
INSERT INTO `schema_migrations` (version) VALUES
|
261
|
+
('1');
|
262
|
+
|
263
|
+
"
|
264
|
+
end
|
265
|
+
|
266
|
+
def expected_schema_sql_on_emulator_7_1
|
267
|
+
"CREATE TABLE all_types (
|
268
|
+
id INT64 NOT NULL,
|
269
|
+
col_string STRING(MAX),
|
270
|
+
col_int64 INT64,
|
271
|
+
col_float64 FLOAT64,
|
272
|
+
col_numeric NUMERIC,
|
273
|
+
col_bool BOOL,
|
274
|
+
col_bytes BYTES(MAX),
|
275
|
+
col_date DATE,
|
276
|
+
col_timestamp TIMESTAMP,
|
277
|
+
col_json JSON,
|
278
|
+
col_array_string ARRAY<STRING(MAX)>,
|
279
|
+
col_array_int64 ARRAY<INT64>,
|
280
|
+
col_array_float64 ARRAY<FLOAT64>,
|
281
|
+
col_array_numeric ARRAY<NUMERIC>,
|
282
|
+
col_array_bool ARRAY<BOOL>,
|
283
|
+
col_array_bytes ARRAY<BYTES(MAX)>,
|
284
|
+
col_array_date ARRAY<DATE>,
|
285
|
+
col_array_timestamp ARRAY<TIMESTAMP>,
|
286
|
+
col_array_json ARRAY<JSON>,
|
287
|
+
) PRIMARY KEY(id);
|
288
|
+
CREATE TABLE firms (
|
289
|
+
id INT64 NOT NULL,
|
290
|
+
name STRING(MAX),
|
291
|
+
rating INT64,
|
292
|
+
description STRING(MAX),
|
293
|
+
account_id INT64,
|
294
|
+
) PRIMARY KEY(id);
|
295
|
+
CREATE INDEX index_firms_on_account_id ON firms(account_id);
|
296
|
+
CREATE TABLE customers (
|
297
|
+
id INT64 NOT NULL,
|
298
|
+
name STRING(MAX),
|
299
|
+
) PRIMARY KEY(id);
|
300
|
+
CREATE TABLE accounts (
|
301
|
+
id INT64 NOT NULL,
|
302
|
+
customer_id INT64,
|
303
|
+
firm_id INT64,
|
304
|
+
name STRING(MAX),
|
305
|
+
credit_limit INT64,
|
306
|
+
transactions_count INT64,
|
307
|
+
) PRIMARY KEY(id);
|
308
|
+
CREATE TABLE transactions (
|
309
|
+
id INT64 NOT NULL,
|
310
|
+
amount FLOAT64,
|
311
|
+
account_id INT64,
|
312
|
+
) PRIMARY KEY(id);
|
313
|
+
CREATE TABLE departments (
|
314
|
+
id INT64 NOT NULL,
|
315
|
+
name STRING(MAX),
|
316
|
+
resource_type STRING(255),
|
317
|
+
resource_id INT64,
|
318
|
+
) PRIMARY KEY(id);
|
319
|
+
CREATE INDEX index_departments_on_resource ON departments(resource_type, resource_id);
|
320
|
+
CREATE TABLE member_types (
|
321
|
+
id INT64 NOT NULL,
|
322
|
+
name STRING(MAX),
|
323
|
+
) PRIMARY KEY(id);
|
324
|
+
CREATE TABLE members (
|
325
|
+
id INT64 NOT NULL,
|
326
|
+
name STRING(MAX),
|
327
|
+
member_type_id INT64,
|
328
|
+
admittable_type STRING(255),
|
329
|
+
admittable_id INT64,
|
330
|
+
) PRIMARY KEY(id);
|
331
|
+
CREATE TABLE memberships (
|
332
|
+
id INT64 NOT NULL,
|
333
|
+
joined_on TIMESTAMP,
|
334
|
+
club_id INT64,
|
335
|
+
member_id INT64,
|
336
|
+
favourite BOOL,
|
337
|
+
) PRIMARY KEY(id);
|
338
|
+
CREATE TABLE clubs (
|
339
|
+
id INT64 NOT NULL,
|
340
|
+
name STRING(MAX),
|
341
|
+
) PRIMARY KEY(id);
|
342
|
+
CREATE TABLE authors (
|
343
|
+
id INT64 NOT NULL,
|
344
|
+
name STRING(MAX) NOT NULL,
|
345
|
+
registered_date DATE,
|
346
|
+
organization_id INT64,
|
347
|
+
) PRIMARY KEY(id);
|
348
|
+
CREATE TABLE posts (
|
349
|
+
id INT64 NOT NULL,
|
350
|
+
title STRING(MAX),
|
351
|
+
content STRING(MAX),
|
352
|
+
author_id INT64,
|
353
|
+
comments_count INT64,
|
354
|
+
post_date DATE,
|
355
|
+
published_time TIMESTAMP,
|
356
|
+
) PRIMARY KEY(id);
|
357
|
+
CREATE INDEX index_posts_on_author_id ON posts(author_id);
|
358
|
+
CREATE TABLE comments (
|
359
|
+
id INT64 NOT NULL,
|
360
|
+
comment STRING(MAX),
|
361
|
+
post_id INT64,
|
362
|
+
CONSTRAINT fk_rails_2fd19c0db7 FOREIGN KEY(post_id) REFERENCES posts(id),
|
363
|
+
) PRIMARY KEY(id);
|
364
|
+
CREATE TABLE addresses (
|
365
|
+
id INT64 NOT NULL,
|
366
|
+
line1 STRING(MAX),
|
367
|
+
postal_code STRING(MAX),
|
368
|
+
city STRING(MAX),
|
369
|
+
author_id INT64,
|
370
|
+
) PRIMARY KEY(id);
|
371
|
+
CREATE TABLE organizations (
|
372
|
+
id INT64 NOT NULL,
|
373
|
+
name STRING(MAX),
|
374
|
+
last_updated TIMESTAMP OPTIONS (
|
375
|
+
allow_commit_timestamp = true
|
376
|
+
),
|
377
|
+
) PRIMARY KEY(id);
|
378
|
+
CREATE TABLE singers (
|
379
|
+
singerid INT64 NOT NULL,
|
380
|
+
first_name STRING(200),
|
381
|
+
last_name STRING(MAX),
|
382
|
+
tracks_count INT64,
|
383
|
+
lock_version INT64,
|
384
|
+
full_name STRING(MAX) AS (COALESCE(first_name || ' ', '') || last_name) STORED,
|
385
|
+
) PRIMARY KEY(singerid);
|
386
|
+
CREATE TABLE albums (
|
387
|
+
singerid INT64 NOT NULL,
|
388
|
+
albumid INT64 NOT NULL,
|
389
|
+
title STRING(MAX),
|
390
|
+
lock_version INT64,
|
391
|
+
) PRIMARY KEY(singerid, albumid),
|
392
|
+
INTERLEAVE IN PARENT singers ON DELETE NO ACTION;
|
393
|
+
CREATE TABLE tracks (
|
394
|
+
singerid INT64 NOT NULL,
|
395
|
+
albumid INT64 NOT NULL,
|
396
|
+
trackid INT64 NOT NULL,
|
397
|
+
title STRING(MAX),
|
398
|
+
duration NUMERIC,
|
399
|
+
lock_version INT64,
|
400
|
+
) PRIMARY KEY(singerid, albumid, trackid),
|
401
|
+
INTERLEAVE IN PARENT albums ON DELETE CASCADE;
|
402
|
+
CREATE NULL_FILTERED INDEX index_tracks_on_singerid_and_albumid_and_title ON tracks(singerid, albumid, title), INTERLEAVE IN albums;
|
403
|
+
CREATE TABLE table_with_sequence (
|
404
|
+
id INT64 NOT NULL DEFAULT (FARM_FINGERPRINT(GENERATE_UUID())),
|
405
|
+
name STRING(MAX) NOT NULL,
|
406
|
+
age INT64 NOT NULL,
|
407
|
+
) PRIMARY KEY(id);
|
238
408
|
CREATE TABLE schema_migrations (
|
239
409
|
version STRING(MAX) NOT NULL,
|
240
410
|
) PRIMARY KEY(version);
|
@@ -251,7 +421,10 @@ INSERT INTO `schema_migrations` (version) VALUES
|
|
251
421
|
end
|
252
422
|
|
253
423
|
def expected_schema_sql_on_production
|
254
|
-
"CREATE
|
424
|
+
"CREATE SEQUENCE test_sequence OPTIONS (
|
425
|
+
sequence_kind = 'bit_reversed_positive'
|
426
|
+
);
|
427
|
+
CREATE TABLE accounts (
|
255
428
|
id INT64 NOT NULL,
|
256
429
|
customer_id INT64,
|
257
430
|
firm_id INT64,
|
@@ -391,6 +564,171 @@ CREATE TABLE tracks (
|
|
391
564
|
) PRIMARY KEY(singerid, albumid, trackid),
|
392
565
|
INTERLEAVE IN PARENT albums ON DELETE CASCADE;
|
393
566
|
CREATE NULL_FILTERED INDEX index_tracks_on_singerid_and_albumid_and_title ON tracks(singerid, albumid, title), INTERLEAVE IN albums;
|
567
|
+
CREATE TABLE table_with_sequence (
|
568
|
+
id INT64 NOT NULL DEFAULT (GET_NEXT_SEQUENCE_VALUE(SEQUENCE test_sequence)),
|
569
|
+
name STRING(MAX) NOT NULL,
|
570
|
+
age INT64 NOT NULL,
|
571
|
+
) PRIMARY KEY(id);
|
572
|
+
CREATE TABLE transactions (
|
573
|
+
id INT64 NOT NULL,
|
574
|
+
amount FLOAT64,
|
575
|
+
account_id INT64,
|
576
|
+
) PRIMARY KEY(id);
|
577
|
+
INSERT INTO `schema_migrations` (version) VALUES
|
578
|
+
('1');
|
579
|
+
|
580
|
+
"
|
581
|
+
end
|
582
|
+
|
583
|
+
def expected_schema_sql_on_production_7_1
|
584
|
+
"CREATE SEQUENCE test_sequence OPTIONS (
|
585
|
+
sequence_kind = 'bit_reversed_positive'
|
586
|
+
);
|
587
|
+
CREATE TABLE accounts (
|
588
|
+
id INT64 NOT NULL,
|
589
|
+
customer_id INT64,
|
590
|
+
firm_id INT64,
|
591
|
+
name STRING(MAX),
|
592
|
+
credit_limit INT64,
|
593
|
+
transactions_count INT64,
|
594
|
+
) PRIMARY KEY(id);
|
595
|
+
CREATE TABLE addresses (
|
596
|
+
id INT64 NOT NULL,
|
597
|
+
line1 STRING(MAX),
|
598
|
+
postal_code STRING(MAX),
|
599
|
+
city STRING(MAX),
|
600
|
+
author_id INT64,
|
601
|
+
) PRIMARY KEY(id);
|
602
|
+
CREATE TABLE all_types (
|
603
|
+
id INT64 NOT NULL,
|
604
|
+
col_string STRING(MAX),
|
605
|
+
col_int64 INT64,
|
606
|
+
col_float64 FLOAT64,
|
607
|
+
col_numeric NUMERIC,
|
608
|
+
col_bool BOOL,
|
609
|
+
col_bytes BYTES(MAX),
|
610
|
+
col_date DATE,
|
611
|
+
col_timestamp TIMESTAMP,
|
612
|
+
col_json JSON,
|
613
|
+
col_array_string ARRAY<STRING(MAX)>,
|
614
|
+
col_array_int64 ARRAY<INT64>,
|
615
|
+
col_array_float64 ARRAY<FLOAT64>,
|
616
|
+
col_array_numeric ARRAY<NUMERIC>,
|
617
|
+
col_array_bool ARRAY<BOOL>,
|
618
|
+
col_array_bytes ARRAY<BYTES(MAX)>,
|
619
|
+
col_array_date ARRAY<DATE>,
|
620
|
+
col_array_timestamp ARRAY<TIMESTAMP>,
|
621
|
+
col_array_json ARRAY<JSON>,
|
622
|
+
) PRIMARY KEY(id);
|
623
|
+
CREATE TABLE ar_internal_metadata (
|
624
|
+
key STRING(MAX) NOT NULL,
|
625
|
+
value STRING(MAX),
|
626
|
+
created_at TIMESTAMP NOT NULL,
|
627
|
+
updated_at TIMESTAMP NOT NULL,
|
628
|
+
) PRIMARY KEY(key);
|
629
|
+
CREATE TABLE authors (
|
630
|
+
id INT64 NOT NULL,
|
631
|
+
name STRING(MAX) NOT NULL,
|
632
|
+
registered_date DATE,
|
633
|
+
organization_id INT64,
|
634
|
+
) PRIMARY KEY(id);
|
635
|
+
CREATE TABLE clubs (
|
636
|
+
id INT64 NOT NULL,
|
637
|
+
name STRING(MAX),
|
638
|
+
) PRIMARY KEY(id);
|
639
|
+
CREATE TABLE comments (
|
640
|
+
id INT64 NOT NULL,
|
641
|
+
comment STRING(MAX),
|
642
|
+
post_id INT64,
|
643
|
+
) PRIMARY KEY(id);
|
644
|
+
CREATE TABLE customers (
|
645
|
+
id INT64 NOT NULL,
|
646
|
+
name STRING(MAX),
|
647
|
+
) PRIMARY KEY(id);
|
648
|
+
CREATE TABLE departments (
|
649
|
+
id INT64 NOT NULL,
|
650
|
+
name STRING(MAX),
|
651
|
+
resource_type STRING(255),
|
652
|
+
resource_id INT64,
|
653
|
+
) PRIMARY KEY(id);
|
654
|
+
CREATE INDEX index_departments_on_resource ON departments(resource_type, resource_id);
|
655
|
+
CREATE TABLE firms (
|
656
|
+
id INT64 NOT NULL,
|
657
|
+
name STRING(MAX),
|
658
|
+
rating INT64,
|
659
|
+
description STRING(MAX),
|
660
|
+
account_id INT64,
|
661
|
+
) PRIMARY KEY(id);
|
662
|
+
CREATE INDEX index_firms_on_account_id ON firms(account_id);
|
663
|
+
CREATE TABLE member_types (
|
664
|
+
id INT64 NOT NULL,
|
665
|
+
name STRING(MAX),
|
666
|
+
) PRIMARY KEY(id);
|
667
|
+
CREATE TABLE members (
|
668
|
+
id INT64 NOT NULL,
|
669
|
+
name STRING(MAX),
|
670
|
+
member_type_id INT64,
|
671
|
+
admittable_type STRING(255),
|
672
|
+
admittable_id INT64,
|
673
|
+
) PRIMARY KEY(id);
|
674
|
+
CREATE TABLE memberships (
|
675
|
+
id INT64 NOT NULL,
|
676
|
+
joined_on TIMESTAMP,
|
677
|
+
club_id INT64,
|
678
|
+
member_id INT64,
|
679
|
+
favourite BOOL,
|
680
|
+
) PRIMARY KEY(id);
|
681
|
+
CREATE TABLE organizations (
|
682
|
+
id INT64 NOT NULL,
|
683
|
+
name STRING(MAX),
|
684
|
+
last_updated TIMESTAMP OPTIONS (
|
685
|
+
allow_commit_timestamp = true
|
686
|
+
),
|
687
|
+
) PRIMARY KEY(id);
|
688
|
+
CREATE TABLE posts (
|
689
|
+
id INT64 NOT NULL,
|
690
|
+
title STRING(MAX),
|
691
|
+
content STRING(MAX),
|
692
|
+
author_id INT64,
|
693
|
+
comments_count INT64,
|
694
|
+
post_date DATE,
|
695
|
+
published_time TIMESTAMP,
|
696
|
+
) PRIMARY KEY(id);
|
697
|
+
ALTER TABLE comments ADD CONSTRAINT fk_rails_2fd19c0db7 FOREIGN KEY(post_id) REFERENCES posts(id);
|
698
|
+
CREATE INDEX index_posts_on_author_id ON posts(author_id);
|
699
|
+
CREATE TABLE schema_migrations (
|
700
|
+
version STRING(MAX) NOT NULL,
|
701
|
+
) PRIMARY KEY(version);
|
702
|
+
CREATE TABLE singers (
|
703
|
+
singerid INT64 NOT NULL,
|
704
|
+
first_name STRING(200),
|
705
|
+
last_name STRING(MAX),
|
706
|
+
tracks_count INT64,
|
707
|
+
lock_version INT64,
|
708
|
+
full_name STRING(MAX) AS (COALESCE(first_name || ' ', '') || last_name) STORED,
|
709
|
+
) PRIMARY KEY(singerid);
|
710
|
+
CREATE TABLE albums (
|
711
|
+
singerid INT64 NOT NULL,
|
712
|
+
albumid INT64 NOT NULL,
|
713
|
+
title STRING(MAX),
|
714
|
+
lock_version INT64,
|
715
|
+
) PRIMARY KEY(singerid, albumid),
|
716
|
+
INTERLEAVE IN PARENT singers ON DELETE NO ACTION;
|
717
|
+
CREATE TABLE tracks (
|
718
|
+
singerid INT64 NOT NULL,
|
719
|
+
albumid INT64 NOT NULL,
|
720
|
+
trackid INT64 NOT NULL,
|
721
|
+
title STRING(MAX),
|
722
|
+
duration NUMERIC,
|
723
|
+
lock_version INT64,
|
724
|
+
) PRIMARY KEY(singerid, albumid, trackid),
|
725
|
+
INTERLEAVE IN PARENT albums ON DELETE CASCADE;
|
726
|
+
CREATE NULL_FILTERED INDEX index_tracks_on_singerid_and_albumid_and_title ON tracks(singerid, albumid, title), INTERLEAVE IN albums;
|
727
|
+
CREATE TABLE table_with_sequence (
|
728
|
+
id INT64 NOT NULL DEFAULT (GET_NEXT_SEQUENCE_VALUE(SEQUENCE test_sequence)),
|
729
|
+
name STRING(MAX) NOT NULL,
|
730
|
+
age INT64 NOT NULL,
|
731
|
+
) PRIMARY KEY(id);
|
394
732
|
CREATE TABLE transactions (
|
395
733
|
id INT64 NOT NULL,
|
396
734
|
amount FLOAT64,
|
@@ -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"
|