activerecord-spanner-adapter 0.3.0 → 0.5.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 +5 -5
- data/.github/CODEOWNERS +7 -0
- data/.github/sync-repo-settings.yaml +16 -0
- data/.github/workflows/acceptance-tests-on-emulator.yaml +45 -0
- data/.github/workflows/acceptance-tests-on-production.yaml +36 -0
- data/.github/workflows/ci.yaml +33 -0
- data/.github/workflows/nightly-acceptance-tests-on-emulator.yaml +52 -0
- data/.github/workflows/nightly-acceptance-tests-on-production.yaml +35 -0
- data/.github/workflows/nightly-unit-tests.yaml +40 -0
- data/.github/workflows/release-please-label.yml +25 -0
- data/.github/workflows/release-please.yml +39 -0
- data/.github/workflows/rubocop.yaml +31 -0
- data/.gitignore +67 -5
- data/.kokoro/populate-secrets.sh +77 -0
- data/.kokoro/release.cfg +33 -0
- data/.kokoro/release.sh +15 -0
- data/.kokoro/trampoline_v2.sh +489 -0
- data/.rubocop.yml +46 -0
- data/.toys/release.rb +18 -0
- data/.trampolinerc +48 -0
- data/.yardopts +11 -0
- data/CHANGELOG.md +26 -0
- data/CODE_OF_CONDUCT.md +40 -0
- data/CONTRIBUTING.md +79 -0
- data/Gemfile +9 -4
- data/LICENSE +6 -6
- data/README.md +67 -30
- data/Rakefile +79 -3
- data/SECURITY.md +7 -0
- data/acceptance/cases/associations/has_many_associations_test.rb +119 -0
- data/acceptance/cases/associations/has_many_through_associations_test.rb +63 -0
- data/acceptance/cases/associations/has_one_associations_test.rb +79 -0
- data/acceptance/cases/associations/has_one_through_associations_test.rb +98 -0
- data/acceptance/cases/interleaved_associations/has_many_associations_using_interleaved_test.rb +211 -0
- data/acceptance/cases/migration/change_schema_test.rb +433 -0
- data/acceptance/cases/migration/change_table_test.rb +115 -0
- data/acceptance/cases/migration/column_attributes_test.rb +122 -0
- data/acceptance/cases/migration/column_positioning_test.rb +48 -0
- data/acceptance/cases/migration/columns_test.rb +201 -0
- data/acceptance/cases/migration/command_recorder_test.rb +406 -0
- data/acceptance/cases/migration/create_join_table_test.rb +216 -0
- data/acceptance/cases/migration/ddl_batching_test.rb +80 -0
- data/acceptance/cases/migration/foreign_key_test.rb +297 -0
- data/acceptance/cases/migration/index_test.rb +211 -0
- data/acceptance/cases/migration/references_foreign_key_test.rb +259 -0
- data/acceptance/cases/migration/references_index_test.rb +135 -0
- data/acceptance/cases/migration/references_statements_test.rb +166 -0
- data/acceptance/cases/migration/rename_column_test.rb +96 -0
- data/acceptance/cases/models/calculation_query_test.rb +128 -0
- data/acceptance/cases/models/generated_column_test.rb +126 -0
- data/acceptance/cases/models/mutation_test.rb +122 -0
- data/acceptance/cases/models/query_test.rb +147 -0
- data/acceptance/cases/sessions/session_not_found_test.rb +121 -0
- data/acceptance/cases/transactions/optimistic_locking_test.rb +141 -0
- data/acceptance/cases/transactions/read_only_transactions_test.rb +67 -0
- data/acceptance/cases/transactions/read_write_transactions_test.rb +248 -0
- data/acceptance/cases/type/all_types_test.rb +152 -0
- data/acceptance/cases/type/binary_test.rb +59 -0
- data/acceptance/cases/type/boolean_test.rb +31 -0
- data/acceptance/cases/type/date_test.rb +32 -0
- data/acceptance/cases/type/date_time_test.rb +30 -0
- data/acceptance/cases/type/float_test.rb +27 -0
- data/acceptance/cases/type/integer_test.rb +44 -0
- data/acceptance/cases/type/numeric_test.rb +27 -0
- data/acceptance/cases/type/string_test.rb +79 -0
- data/acceptance/cases/type/text_test.rb +30 -0
- data/acceptance/cases/type/time_test.rb +87 -0
- data/acceptance/models/account.rb +13 -0
- data/acceptance/models/address.rb +9 -0
- data/acceptance/models/album.rb +12 -0
- data/acceptance/models/all_types.rb +8 -0
- data/acceptance/models/author.rb +11 -0
- data/acceptance/models/club.rb +12 -0
- data/acceptance/models/comment.rb +9 -0
- data/acceptance/models/customer.rb +9 -0
- data/acceptance/models/department.rb +9 -0
- data/acceptance/models/firm.rb +10 -0
- data/acceptance/models/member.rb +13 -0
- data/acceptance/models/member_type.rb +9 -0
- data/acceptance/models/membership.rb +10 -0
- data/acceptance/models/organization.rb +9 -0
- data/acceptance/models/post.rb +10 -0
- data/acceptance/models/singer.rb +10 -0
- data/acceptance/models/track.rb +20 -0
- data/acceptance/models/transaction.rb +9 -0
- data/acceptance/schema/schema.rb +143 -0
- data/acceptance/test_helper.rb +260 -0
- data/activerecord-spanner-adapter.gemspec +32 -17
- data/assets/solidus-db.png +0 -0
- data/benchmarks/README.md +17 -0
- data/benchmarks/Rakefile +14 -0
- data/benchmarks/application.rb +308 -0
- data/benchmarks/config/database.yml +8 -0
- data/benchmarks/config/environment.rb +12 -0
- data/benchmarks/db/migrate/01_create_tables.rb +25 -0
- data/benchmarks/db/schema.rb +29 -0
- data/benchmarks/models/album.rb +9 -0
- data/benchmarks/models/singer.rb +9 -0
- data/bin/console +6 -7
- data/examples/rails/README.md +262 -0
- data/examples/snippets/README.md +29 -0
- data/examples/snippets/Rakefile +57 -0
- data/examples/snippets/array-data-type/README.md +45 -0
- data/examples/snippets/array-data-type/Rakefile +13 -0
- data/examples/snippets/array-data-type/application.rb +45 -0
- data/examples/snippets/array-data-type/config/database.yml +8 -0
- data/examples/snippets/array-data-type/db/migrate/01_create_tables.rb +24 -0
- data/examples/snippets/array-data-type/db/schema.rb +26 -0
- data/examples/snippets/array-data-type/db/seeds.rb +5 -0
- data/examples/snippets/array-data-type/models/entity_with_array_types.rb +18 -0
- data/examples/snippets/bin/create_emulator_instance.rb +18 -0
- data/examples/snippets/bulk-insert/README.md +21 -0
- data/examples/snippets/bulk-insert/Rakefile +13 -0
- data/examples/snippets/bulk-insert/application.rb +64 -0
- data/examples/snippets/bulk-insert/config/database.yml +8 -0
- data/examples/snippets/bulk-insert/db/migrate/01_create_tables.rb +21 -0
- data/examples/snippets/bulk-insert/db/schema.rb +26 -0
- data/examples/snippets/bulk-insert/db/seeds.rb +5 -0
- data/examples/snippets/bulk-insert/models/album.rb +9 -0
- data/examples/snippets/bulk-insert/models/singer.rb +9 -0
- data/examples/snippets/commit-timestamp/README.md +18 -0
- data/examples/snippets/commit-timestamp/Rakefile +13 -0
- data/examples/snippets/commit-timestamp/application.rb +53 -0
- data/examples/snippets/commit-timestamp/config/database.yml +8 -0
- data/examples/snippets/commit-timestamp/db/migrate/01_create_tables.rb +26 -0
- data/examples/snippets/commit-timestamp/db/schema.rb +29 -0
- data/examples/snippets/commit-timestamp/db/seeds.rb +5 -0
- data/examples/snippets/commit-timestamp/models/album.rb +9 -0
- data/examples/snippets/commit-timestamp/models/singer.rb +9 -0
- data/examples/snippets/config/environment.rb +21 -0
- data/examples/snippets/create-records/README.md +12 -0
- data/examples/snippets/create-records/Rakefile +13 -0
- data/examples/snippets/create-records/application.rb +42 -0
- data/examples/snippets/create-records/config/database.yml +8 -0
- data/examples/snippets/create-records/db/migrate/01_create_tables.rb +21 -0
- data/examples/snippets/create-records/db/schema.rb +26 -0
- data/examples/snippets/create-records/db/seeds.rb +5 -0
- data/examples/snippets/create-records/models/album.rb +9 -0
- data/examples/snippets/create-records/models/singer.rb +9 -0
- data/examples/snippets/date-data-type/README.md +19 -0
- data/examples/snippets/date-data-type/Rakefile +13 -0
- data/examples/snippets/date-data-type/application.rb +35 -0
- data/examples/snippets/date-data-type/config/database.yml +8 -0
- data/examples/snippets/date-data-type/db/migrate/01_create_tables.rb +20 -0
- data/examples/snippets/date-data-type/db/schema.rb +21 -0
- data/examples/snippets/date-data-type/db/seeds.rb +16 -0
- data/examples/snippets/date-data-type/models/singer.rb +8 -0
- data/examples/snippets/generated-column/README.md +41 -0
- data/examples/snippets/generated-column/Rakefile +13 -0
- data/examples/snippets/generated-column/application.rb +37 -0
- data/examples/snippets/generated-column/config/database.yml +8 -0
- data/examples/snippets/generated-column/db/migrate/01_create_tables.rb +23 -0
- data/examples/snippets/generated-column/db/schema.rb +21 -0
- data/examples/snippets/generated-column/db/seeds.rb +18 -0
- data/examples/snippets/generated-column/models/singer.rb +8 -0
- data/examples/snippets/interleaved-tables/README.md +152 -0
- data/examples/snippets/interleaved-tables/Rakefile +13 -0
- data/examples/snippets/interleaved-tables/application.rb +109 -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 +15 -0
- data/examples/snippets/interleaved-tables/models/singer.rb +20 -0
- data/examples/snippets/interleaved-tables/models/track.rb +25 -0
- data/examples/snippets/migrations/README.md +43 -0
- data/examples/snippets/migrations/Rakefile +13 -0
- data/examples/snippets/migrations/application.rb +26 -0
- data/examples/snippets/migrations/config/database.yml +8 -0
- data/examples/snippets/migrations/db/migrate/01_create_tables.rb +28 -0
- data/examples/snippets/migrations/db/schema.rb +33 -0
- data/examples/snippets/migrations/db/seeds.rb +5 -0
- data/examples/snippets/migrations/models/album.rb +10 -0
- data/examples/snippets/migrations/models/singer.rb +10 -0
- data/examples/snippets/migrations/models/track.rb +9 -0
- data/examples/snippets/mutations/README.md +34 -0
- data/examples/snippets/mutations/Rakefile +13 -0
- data/examples/snippets/mutations/application.rb +47 -0
- data/examples/snippets/mutations/config/database.yml +8 -0
- data/examples/snippets/mutations/db/migrate/01_create_tables.rb +22 -0
- data/examples/snippets/mutations/db/schema.rb +27 -0
- data/examples/snippets/mutations/db/seeds.rb +25 -0
- data/examples/snippets/mutations/models/album.rb +9 -0
- data/examples/snippets/mutations/models/singer.rb +9 -0
- data/examples/snippets/optimistic-locking/README.md +12 -0
- data/examples/snippets/optimistic-locking/Rakefile +13 -0
- data/examples/snippets/optimistic-locking/application.rb +48 -0
- data/examples/snippets/optimistic-locking/config/database.yml +8 -0
- data/examples/snippets/optimistic-locking/db/migrate/01_create_tables.rb +26 -0
- data/examples/snippets/optimistic-locking/db/schema.rb +29 -0
- data/examples/snippets/optimistic-locking/db/seeds.rb +25 -0
- data/examples/snippets/optimistic-locking/models/album.rb +9 -0
- data/examples/snippets/optimistic-locking/models/singer.rb +9 -0
- data/examples/snippets/quickstart/README.md +26 -0
- data/examples/snippets/quickstart/Rakefile +13 -0
- data/examples/snippets/quickstart/application.rb +51 -0
- data/examples/snippets/quickstart/config/database.yml +8 -0
- data/examples/snippets/quickstart/db/migrate/01_create_tables.rb +21 -0
- data/examples/snippets/quickstart/db/schema.rb +26 -0
- data/examples/snippets/quickstart/db/seeds.rb +24 -0
- data/examples/snippets/quickstart/models/album.rb +9 -0
- data/examples/snippets/quickstart/models/singer.rb +9 -0
- data/examples/snippets/read-only-transactions/README.md +13 -0
- data/examples/snippets/read-only-transactions/Rakefile +13 -0
- data/examples/snippets/read-only-transactions/application.rb +49 -0
- data/examples/snippets/read-only-transactions/config/database.yml +8 -0
- data/examples/snippets/read-only-transactions/db/migrate/01_create_tables.rb +21 -0
- data/examples/snippets/read-only-transactions/db/schema.rb +26 -0
- data/examples/snippets/read-only-transactions/db/seeds.rb +24 -0
- data/examples/snippets/read-only-transactions/models/album.rb +9 -0
- data/examples/snippets/read-only-transactions/models/singer.rb +9 -0
- data/examples/snippets/read-write-transactions/README.md +12 -0
- data/examples/snippets/read-write-transactions/Rakefile +13 -0
- data/examples/snippets/read-write-transactions/application.rb +39 -0
- data/examples/snippets/read-write-transactions/config/database.yml +8 -0
- data/examples/snippets/read-write-transactions/db/migrate/01_create_tables.rb +22 -0
- data/examples/snippets/read-write-transactions/db/schema.rb +27 -0
- data/examples/snippets/read-write-transactions/db/seeds.rb +25 -0
- data/examples/snippets/read-write-transactions/models/album.rb +9 -0
- data/examples/snippets/read-write-transactions/models/singer.rb +9 -0
- data/examples/snippets/timestamp-data-type/README.md +17 -0
- data/examples/snippets/timestamp-data-type/Rakefile +13 -0
- data/examples/snippets/timestamp-data-type/application.rb +42 -0
- data/examples/snippets/timestamp-data-type/config/database.yml +8 -0
- data/examples/snippets/timestamp-data-type/db/migrate/01_create_tables.rb +21 -0
- data/examples/snippets/timestamp-data-type/db/schema.rb +21 -0
- data/examples/snippets/timestamp-data-type/db/seeds.rb +6 -0
- data/examples/snippets/timestamp-data-type/models/meeting.rb +19 -0
- data/examples/solidus/README.md +172 -0
- data/lib/active_record/connection_adapters/spanner/database_statements.rb +224 -269
- data/lib/active_record/connection_adapters/spanner/quoting.rb +42 -50
- data/lib/active_record/connection_adapters/spanner/schema_cache.rb +43 -0
- data/lib/active_record/connection_adapters/spanner/schema_creation.rb +125 -9
- data/lib/active_record/connection_adapters/spanner/schema_definitions.rb +122 -0
- data/lib/active_record/connection_adapters/spanner/schema_dumper.rb +19 -0
- data/lib/active_record/connection_adapters/spanner/schema_statements.rb +553 -139
- data/lib/active_record/connection_adapters/spanner/type_metadata.rb +37 -0
- data/lib/active_record/connection_adapters/spanner_adapter.rb +182 -78
- data/lib/active_record/tasks/spanner_database_tasks.rb +74 -0
- data/lib/active_record/type/spanner/array.rb +32 -0
- data/lib/active_record/type/spanner/bytes.rb +26 -0
- data/lib/active_record/type/spanner/spanner_active_record_converter.rb +32 -0
- data/lib/active_record/type/spanner/time.rb +37 -0
- data/lib/activerecord-spanner-adapter.rb +23 -0
- data/lib/activerecord_spanner_adapter/base.rb +217 -0
- data/lib/activerecord_spanner_adapter/connection.rb +324 -0
- data/lib/activerecord_spanner_adapter/errors.rb +13 -0
- data/lib/activerecord_spanner_adapter/foreign_key.rb +29 -0
- data/lib/activerecord_spanner_adapter/index/column.rb +38 -0
- data/lib/activerecord_spanner_adapter/index.rb +80 -0
- data/lib/activerecord_spanner_adapter/information_schema.rb +261 -0
- data/lib/activerecord_spanner_adapter/primary_key.rb +31 -0
- data/lib/activerecord_spanner_adapter/table/column.rb +59 -0
- data/lib/activerecord_spanner_adapter/table.rb +61 -0
- data/lib/activerecord_spanner_adapter/transaction.rb +113 -0
- data/lib/activerecord_spanner_adapter/version.rb +9 -0
- data/lib/arel/visitors/spanner.rb +35 -0
- data/lib/spanner_client_ext.rb +82 -0
- data/renovate.json +5 -0
- metadata +387 -34
- data/.travis.yml +0 -5
- data/lib/active_record/connection_adapters/spanner/client.rb +0 -190
- data/lib/active_record/connection_adapters/spanner.rb +0 -10
- data/lib/activerecord-spanner-adapter/version.rb +0 -3
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# Copyright 2020 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
|
+
class Author < ActiveRecord::Base
|
|
8
|
+
has_many :posts
|
|
9
|
+
has_many :comments, through: :posts
|
|
10
|
+
belongs_to :organization
|
|
11
|
+
end
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
# Copyright 2020 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
|
+
class Club < ActiveRecord::Base
|
|
8
|
+
has_many :memberships
|
|
9
|
+
has_many :members, through: :memberships
|
|
10
|
+
has_many :favourites, -> { where(memberships: { favourite: true }) },
|
|
11
|
+
through: :memberships, source: :member
|
|
12
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Copyright 2020 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
|
+
class Comment < ActiveRecord::Base
|
|
8
|
+
belongs_to :post, counter_cache: true
|
|
9
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Copyright 2020 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
|
+
class Department < ActiveRecord::Base
|
|
8
|
+
belongs_to :resource, polymorphic: true
|
|
9
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Copyright 2020 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
|
+
class Firm < ActiveRecord::Base
|
|
8
|
+
has_one :account
|
|
9
|
+
has_many :departments, as: :resource
|
|
10
|
+
end
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
# Copyright 2020 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
|
+
class Member < ActiveRecord::Base
|
|
8
|
+
has_one :membership
|
|
9
|
+
has_one :club, through: :membership
|
|
10
|
+
has_one :favourite_club, -> { where "memberships.favourite = ?", true },
|
|
11
|
+
through: :membership, source: :club
|
|
12
|
+
belongs_to :member_type
|
|
13
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Copyright 2020 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
|
+
class Membership < ActiveRecord::Base
|
|
8
|
+
belongs_to :member
|
|
9
|
+
belongs_to :club
|
|
10
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Copyright 2020 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
|
+
class Organization < ActiveRecord::Base
|
|
8
|
+
has_many :authors, dependent: :destroy
|
|
9
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Copyright 2020 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
|
+
class Post < ActiveRecord::Base
|
|
8
|
+
belongs_to :author
|
|
9
|
+
has_many :comments
|
|
10
|
+
end
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
# Copyright 2021 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
|
+
class Singer < ActiveRecord::Base
|
|
8
|
+
has_many :albums, foreign_key: "singerid", dependent: :delete_all
|
|
9
|
+
has_many :tracks, foreign_key: "singerid"
|
|
10
|
+
end
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Copyright 2021 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
|
+
class Track < ActiveRecord::Base
|
|
8
|
+
belongs_to :album, foreign_key: "albumid"
|
|
9
|
+
belongs_to :singer, foreign_key: "singerid", counter_cache: true
|
|
10
|
+
|
|
11
|
+
def initialize attributes = nil
|
|
12
|
+
super
|
|
13
|
+
self.singer ||= self.album&.singer
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
def album=value
|
|
17
|
+
super
|
|
18
|
+
self.singer = value&.singer
|
|
19
|
+
end
|
|
20
|
+
end
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
# Copyright 2020 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
|
+
class Transaction < ActiveRecord::Base
|
|
8
|
+
belongs_to :account, counter_cache: true
|
|
9
|
+
end
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
# Copyright 2020 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
|
+
ActiveRecord::Schema.define do
|
|
10
|
+
ActiveRecord::Base.connection.ddl_batch do
|
|
11
|
+
create_table :all_types do |t|
|
|
12
|
+
t.column :col_string, :string
|
|
13
|
+
t.column :col_int64, :bigint
|
|
14
|
+
t.column :col_float64, :float
|
|
15
|
+
t.column :col_numeric, :numeric
|
|
16
|
+
t.column :col_bool, :boolean
|
|
17
|
+
t.column :col_bytes, :binary
|
|
18
|
+
t.column :col_date, :date
|
|
19
|
+
t.column :col_timestamp, :datetime
|
|
20
|
+
|
|
21
|
+
t.column :col_array_string, :string, array: true
|
|
22
|
+
t.column :col_array_int64, :bigint, array: true
|
|
23
|
+
t.column :col_array_float64, :float, array: true
|
|
24
|
+
t.column :col_array_numeric, :numeric, array: true
|
|
25
|
+
t.column :col_array_bool, :boolean, array: true
|
|
26
|
+
t.column :col_array_bytes, :binary, array: true
|
|
27
|
+
t.column :col_array_date, :date, array: true
|
|
28
|
+
t.column :col_array_timestamp, :datetime, array: true
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
create_table :firms do |t|
|
|
32
|
+
t.string :name
|
|
33
|
+
t.integer :rating
|
|
34
|
+
t.string :description
|
|
35
|
+
t.references :account
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
create_table :customers do |t|
|
|
39
|
+
t.string :name
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
create_table :accounts do |t|
|
|
43
|
+
t.references :customer, index: false
|
|
44
|
+
t.references :firm, index: false
|
|
45
|
+
t.string :name
|
|
46
|
+
t.integer :credit_limit
|
|
47
|
+
t.integer :transactions_count
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
create_table :transactions do |t|
|
|
51
|
+
t.float :amount
|
|
52
|
+
t.references :account, index: false
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
create_table :departments do |t|
|
|
56
|
+
t.string :name
|
|
57
|
+
t.references :resource, polymorphic: true
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
create_table :member_types do |t|
|
|
61
|
+
t.string :name
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
create_table :members do |t|
|
|
65
|
+
t.string :name
|
|
66
|
+
t.references :member_type, index: false
|
|
67
|
+
t.references :admittable, polymorphic: true, index: false
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
create_table :memberships do |t|
|
|
71
|
+
t.datetime :joined_on
|
|
72
|
+
t.references :club, index: false
|
|
73
|
+
t.references :member, index: false
|
|
74
|
+
t.boolean :favourite
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
create_table :clubs do |t|
|
|
78
|
+
t.string :name
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
create_table :authors do |t|
|
|
82
|
+
t.string :name, null: false
|
|
83
|
+
t.date :registered_date
|
|
84
|
+
t.references :organization, index: false
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
create_table :posts do |t|
|
|
88
|
+
t.string :title
|
|
89
|
+
t.string :content
|
|
90
|
+
t.references :author
|
|
91
|
+
t.integer :comments_count
|
|
92
|
+
t.date :post_date
|
|
93
|
+
t.time :published_time
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
create_table :comments do |t|
|
|
97
|
+
t.string :comment
|
|
98
|
+
t.references :post, index: false, foreign_key: true
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
create_table :addresses do |t|
|
|
102
|
+
t.string :line1
|
|
103
|
+
t.string :postal_code
|
|
104
|
+
t.string :city
|
|
105
|
+
t.references :author, index: false
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
create_table :organizations do |t|
|
|
109
|
+
t.string :name
|
|
110
|
+
t.datetime :last_updated, allow_commit_timestamp: true
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
create_table :singers, id: false do |t|
|
|
114
|
+
t.primary_key :singerid
|
|
115
|
+
t.column :first_name, :string, limit: 200
|
|
116
|
+
t.string :last_name
|
|
117
|
+
t.integer :tracks_count
|
|
118
|
+
t.integer :lock_version
|
|
119
|
+
t.string :full_name, as: "COALESCE(first_name || ' ', '') || last_name", stored: true
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
create_table :albums, id: false do |t|
|
|
123
|
+
t.interleave_in :singers
|
|
124
|
+
t.primary_key :albumid
|
|
125
|
+
# `singerid` is part of the primary key in the table definition, but it is not visible to ActiveRecord as part of
|
|
126
|
+
# the primary key, to prevent ActiveRecord from considering this to be an entity with a composite primary key.
|
|
127
|
+
t.parent_key :singerid
|
|
128
|
+
t.string :title
|
|
129
|
+
t.integer :lock_version
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
create_table :tracks, id: false do |t|
|
|
133
|
+
# `:cascade` causes all tracks that belong to an album to automatically be deleted when an album is deleted.
|
|
134
|
+
t.interleave_in :albums, :cascade
|
|
135
|
+
t.primary_key :trackid
|
|
136
|
+
t.parent_key :singerid
|
|
137
|
+
t.parent_key :albumid
|
|
138
|
+
t.string :title
|
|
139
|
+
t.numeric :duration
|
|
140
|
+
t.integer :lock_version
|
|
141
|
+
end
|
|
142
|
+
end
|
|
143
|
+
end
|
|
@@ -0,0 +1,260 @@
|
|
|
1
|
+
# Copyright 2020 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
|
+
gem "minitest"
|
|
8
|
+
require "minitest/autorun"
|
|
9
|
+
require "minitest/focus"
|
|
10
|
+
require "minitest/rg"
|
|
11
|
+
require "active_support"
|
|
12
|
+
require "google/cloud/spanner"
|
|
13
|
+
require "active_record"
|
|
14
|
+
require "active_support/testing/stream"
|
|
15
|
+
require "activerecord-spanner-adapter"
|
|
16
|
+
require "active_record/connection_adapters/spanner_adapter"
|
|
17
|
+
require "securerandom"
|
|
18
|
+
|
|
19
|
+
# rubocop:disable Style/GlobalVars
|
|
20
|
+
|
|
21
|
+
$spanner_test_database = "ar-test-#{SecureRandom.hex 4}"
|
|
22
|
+
|
|
23
|
+
def connector_config
|
|
24
|
+
{
|
|
25
|
+
"adapter" => "spanner",
|
|
26
|
+
"emulator_host" => ENV["SPANNER_EMULATOR_HOST"],
|
|
27
|
+
"project" => ENV["SPANNER_TEST_PROJECT"],
|
|
28
|
+
"instance" => ENV["SPANNER_TEST_INSTANCE"],
|
|
29
|
+
"credentials" => ENV["SPANNER_TEST_KEYFILE"],
|
|
30
|
+
"database" => $spanner_test_database
|
|
31
|
+
}
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def spanner
|
|
35
|
+
$spanner ||= Google::Cloud::Spanner.new(
|
|
36
|
+
project_id: ENV["SPANNER_TEST_PROJECT"],
|
|
37
|
+
credentials: ENV["SPANNER_TEST_KEYFILE"]
|
|
38
|
+
)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def spanner_instance
|
|
42
|
+
unless spanner.instance ENV["SPANNER_TEST_INSTANCE"]
|
|
43
|
+
config = ENV["SPANNER_EMULATOR_HOST"] ? "emulator-config" : "regional-us-central1"
|
|
44
|
+
puts "Creating test instance #{ENV["SPANNER_TEST_INSTANCE"]} with config #{config}"
|
|
45
|
+
job = spanner.create_instance ENV["SPANNER_TEST_INSTANCE"],
|
|
46
|
+
name: "ActiveRecord Test Instance",
|
|
47
|
+
config: config,
|
|
48
|
+
nodes: 1
|
|
49
|
+
job.wait_until_done!
|
|
50
|
+
$owned_test_instance = true
|
|
51
|
+
end
|
|
52
|
+
$spanner_instance ||= spanner.instance ENV["SPANNER_TEST_INSTANCE"]
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def create_test_database
|
|
56
|
+
job = spanner_instance.create_database $spanner_test_database
|
|
57
|
+
job.wait_until_done!
|
|
58
|
+
if job.error?
|
|
59
|
+
raise "Error in creating database. Error code#{job.error.message}"
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
puts "'#{$spanner_test_database}' test db created."
|
|
63
|
+
|
|
64
|
+
puts "Loading test schema..."
|
|
65
|
+
ActiveRecord::Base.establish_connection connector_config
|
|
66
|
+
require_relative "schema/schema"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def drop_test_database
|
|
70
|
+
ActiveRecord::Base.connection_pool.disconnect!
|
|
71
|
+
spanner_instance&.delete if $owned_test_instance
|
|
72
|
+
spanner_instance.database($spanner_test_database)&.drop unless $owned_test_instance
|
|
73
|
+
|
|
74
|
+
puts "Test instance #{spanner_instance} deleted" if $owned_test_instance
|
|
75
|
+
puts "#{$spanner_test_database} database deleted" unless $owned_test_instance
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def current_adapter? *names
|
|
79
|
+
names.include? :SpannerAdapter
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
def load_test_schema
|
|
83
|
+
ActiveRecord::Base.establish_connection connector_config
|
|
84
|
+
|
|
85
|
+
require_relative "schema/schema"
|
|
86
|
+
end
|
|
87
|
+
|
|
88
|
+
module SpannerAdapter
|
|
89
|
+
class TestCase < ActiveSupport::TestCase
|
|
90
|
+
def assert_column(model, column_name, msg = nil)
|
|
91
|
+
assert has_column?(model, column_name), msg
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def assert_no_column(model, column_name, msg = nil)
|
|
95
|
+
assert_not has_column?(model, column_name), msg
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
def has_column?(model, column_name)
|
|
99
|
+
model.reset_column_information
|
|
100
|
+
model.column_names.include?(column_name.to_s)
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def capture_sql
|
|
104
|
+
ActiveRecord::Base.connection.materialize_transactions
|
|
105
|
+
SQLCounter.clear_log
|
|
106
|
+
yield
|
|
107
|
+
SQLCounter.log.dup
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def assert_queries(num = 1, options = {})
|
|
111
|
+
ignore_none = options.fetch(:ignore_none) { num == :any }
|
|
112
|
+
ActiveRecord::Base.connection.materialize_transactions
|
|
113
|
+
SQLCounter.clear_log
|
|
114
|
+
x = yield
|
|
115
|
+
the_log = ignore_none ? SQLCounter.log_all : SQLCounter.log
|
|
116
|
+
if num == :any
|
|
117
|
+
assert_operator the_log.size, :>=, 1, "1 or more queries expected, but none were executed."
|
|
118
|
+
else
|
|
119
|
+
mesg = "#{the_log.size} instead of #{num} queries were executed.#{the_log.size == 0 ? '' : "\nQueries:\n#{the_log.join("\n")}"}"
|
|
120
|
+
assert_equal num, the_log.size, mesg
|
|
121
|
+
end
|
|
122
|
+
x
|
|
123
|
+
end
|
|
124
|
+
|
|
125
|
+
def assert_no_queries(options = {}, &block)
|
|
126
|
+
options.reverse_merge! ignore_none: true
|
|
127
|
+
assert_queries(0, options, &block)
|
|
128
|
+
end
|
|
129
|
+
end
|
|
130
|
+
|
|
131
|
+
module Migration
|
|
132
|
+
module TestHelper
|
|
133
|
+
attr_accessor :connection
|
|
134
|
+
|
|
135
|
+
CONNECTION_METHODS = %w[
|
|
136
|
+
add_column remove_column rename_column add_index change_column
|
|
137
|
+
rename_table column_exists? index_exists?
|
|
138
|
+
add_reference add_belongs_to remove_reference remove_references
|
|
139
|
+
remove_belongs_to change_column_default
|
|
140
|
+
].freeze
|
|
141
|
+
|
|
142
|
+
class TestModel < ActiveRecord::Base
|
|
143
|
+
self.table_name = :test_models
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def setup
|
|
147
|
+
ActiveRecord::Base.establish_connection connector_config
|
|
148
|
+
@connection = ActiveRecord::Base.connection
|
|
149
|
+
|
|
150
|
+
unless @skip_test_table_create
|
|
151
|
+
connection.create_table :test_models do |t|
|
|
152
|
+
t.timestamps null: true
|
|
153
|
+
end
|
|
154
|
+
|
|
155
|
+
TestModel.reset_column_information
|
|
156
|
+
end
|
|
157
|
+
super
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def skip_test_table_create!
|
|
161
|
+
@skip_test_table_create = true
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
def teardown
|
|
165
|
+
TestModel.reset_table_name
|
|
166
|
+
|
|
167
|
+
unless @skip_test_table_create
|
|
168
|
+
connection.drop_table :test_models, if_exists: true
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
super
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def generate_id
|
|
175
|
+
connection.next_sequence_value nil
|
|
176
|
+
end
|
|
177
|
+
|
|
178
|
+
delegate *CONNECTION_METHODS, to: :connection
|
|
179
|
+
end
|
|
180
|
+
end
|
|
181
|
+
|
|
182
|
+
module Types
|
|
183
|
+
module TestHelper
|
|
184
|
+
attr_accessor :connection
|
|
185
|
+
|
|
186
|
+
class TestTypeModel < ActiveRecord::Base
|
|
187
|
+
self.table_name = :test_types
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def setup
|
|
191
|
+
super
|
|
192
|
+
|
|
193
|
+
ActiveRecord::Base.establish_connection connector_config
|
|
194
|
+
@connection = ActiveRecord::Base.connection
|
|
195
|
+
|
|
196
|
+
return if connection.table_exists? :test_types
|
|
197
|
+
|
|
198
|
+
connection.create_table :test_types do |t|
|
|
199
|
+
t.string :name, limit: 255
|
|
200
|
+
t.string :description
|
|
201
|
+
t.text :bio
|
|
202
|
+
t.integer :length
|
|
203
|
+
t.float :weight
|
|
204
|
+
t.numeric :price
|
|
205
|
+
t.boolean :active
|
|
206
|
+
t.binary :file
|
|
207
|
+
t.binary :data, limit: 255
|
|
208
|
+
t.date :start_date
|
|
209
|
+
t.datetime :start_datetime
|
|
210
|
+
t.time :start_time
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def teardown
|
|
215
|
+
super
|
|
216
|
+
TestTypeModel.delete_all
|
|
217
|
+
end
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
module Associations
|
|
222
|
+
module TestHelper
|
|
223
|
+
def setup
|
|
224
|
+
ActiveRecord::Base.establish_connection connector_config
|
|
225
|
+
@connection = ActiveRecord::Base.connection
|
|
226
|
+
end
|
|
227
|
+
end
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
class SQLCounter
|
|
231
|
+
class << self
|
|
232
|
+
attr_accessor :ignored_sql, :log, :log_all
|
|
233
|
+
|
|
234
|
+
def clear_log
|
|
235
|
+
self.log = []
|
|
236
|
+
self.log_all = []
|
|
237
|
+
end
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
clear_log
|
|
241
|
+
|
|
242
|
+
def call(name, start, finish, message_id, values)
|
|
243
|
+
return if values[:cached]
|
|
244
|
+
|
|
245
|
+
sql = values[:sql]
|
|
246
|
+
self.class.log_all << sql
|
|
247
|
+
self.class.log << sql unless ["SCHEMA", "TRANSACTION"].include? values[:name]
|
|
248
|
+
end
|
|
249
|
+
end
|
|
250
|
+
|
|
251
|
+
ActiveSupport::Notifications.subscribe("sql.active_record", SQLCounter.new)
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
Minitest.after_run do
|
|
255
|
+
drop_test_database
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
create_test_database
|
|
259
|
+
|
|
260
|
+
# rubocop:enable Style/GlobalVars
|