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,96 @@
|
|
|
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
|
+
require "test_helper"
|
|
10
|
+
|
|
11
|
+
module ActiveRecord
|
|
12
|
+
class Migration
|
|
13
|
+
class RenameColumnsTest < SpannerAdapter::TestCase
|
|
14
|
+
include SpannerAdapter::Migration::TestHelper
|
|
15
|
+
|
|
16
|
+
class RenameColumnPost < ActiveRecord::Base
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
class RenameColumnComment < ActiveRecord::Base
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def setup
|
|
23
|
+
skip_test_table_create!
|
|
24
|
+
super
|
|
25
|
+
|
|
26
|
+
connection.drop_table :rename_column_comments, if_exists: true
|
|
27
|
+
connection.drop_table :rename_column_posts, if_exists: true
|
|
28
|
+
|
|
29
|
+
connection.create_table(:rename_column_posts) do |t|
|
|
30
|
+
t.string :name, limit: 128
|
|
31
|
+
t.integer :comment_count
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
connection.create_table(:rename_column_comments) do |t|
|
|
35
|
+
t.string :comment
|
|
36
|
+
# The Spanner ActiveRecord adapter does not support creating an index on a column that also has a foreign key,
|
|
37
|
+
# as Cloud Spanner automatically creates a managed index for the foreign key. The index is therefore created
|
|
38
|
+
# separately.
|
|
39
|
+
t.references :rename_column_post, foreign_key: true
|
|
40
|
+
t.index :rename_column_post_id
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
RenameColumnPost.reset_column_information
|
|
44
|
+
RenameColumnComment.reset_column_information
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def teardown
|
|
48
|
+
super
|
|
49
|
+
connection.drop_table :rename_column_comments, if_exists: true
|
|
50
|
+
connection.drop_table :rename_column_posts, if_exists: true
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def test_rename_column
|
|
54
|
+
assert connection.column_exists?(:rename_column_posts, :name, :string, limit: 128)
|
|
55
|
+
|
|
56
|
+
RenameColumnPost.create!(name: "Post1", comment_count: 1)
|
|
57
|
+
RenameColumnPost.create!(name: "Post2", comment_count: 2)
|
|
58
|
+
|
|
59
|
+
connection.rename_column :rename_column_posts, :name, :title
|
|
60
|
+
|
|
61
|
+
RenameColumnPost.reset_column_information
|
|
62
|
+
|
|
63
|
+
assert connection.column_exists?(:rename_column_posts, :title, :string, limit: 128)
|
|
64
|
+
|
|
65
|
+
assert_equal ["Post1", "Post2"].sort, RenameColumnPost.pluck(:title).sort
|
|
66
|
+
assert_equal [1, 2], RenameColumnPost.pluck(:comment_count).sort
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def test_rename_column_with_index_and_foreign_key
|
|
70
|
+
assert connection.column_exists?(:rename_column_comments, :rename_column_post_id, :integer)
|
|
71
|
+
assert connection.index_exists?(:rename_column_comments, :rename_column_post_id)
|
|
72
|
+
assert connection.foreign_key_exists?(:rename_column_comments, :rename_column_posts)
|
|
73
|
+
|
|
74
|
+
post = RenameColumnPost.create!(name: "Post1")
|
|
75
|
+
RenameColumnComment.create!(comment: "Comment1", rename_column_post_id: post.id)
|
|
76
|
+
RenameColumnComment.create!(comment: "Comment2", rename_column_post_id: post.id)
|
|
77
|
+
|
|
78
|
+
connection.rename_column :rename_column_comments, :rename_column_post_id, :post_id
|
|
79
|
+
|
|
80
|
+
RenameColumnComment.reset_column_information
|
|
81
|
+
|
|
82
|
+
assert connection.column_exists?(:rename_column_comments, :post_id, :integer)
|
|
83
|
+
assert connection.index_exists?(:rename_column_comments, :post_id)
|
|
84
|
+
|
|
85
|
+
foreign_keys = connection.foreign_keys("rename_column_comments")
|
|
86
|
+
assert_equal 1, foreign_keys.length
|
|
87
|
+
|
|
88
|
+
fk = foreign_keys.first
|
|
89
|
+
assert_equal "rename_column_comments", fk.from_table
|
|
90
|
+
assert_equal "post_id", fk.column
|
|
91
|
+
|
|
92
|
+
assert_equal [post.id, post.id].sort, RenameColumnComment.pluck(:post_id)
|
|
93
|
+
end
|
|
94
|
+
end
|
|
95
|
+
end
|
|
96
|
+
end
|
|
@@ -0,0 +1,128 @@
|
|
|
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
|
+
require "test_helper"
|
|
10
|
+
require "models/account"
|
|
11
|
+
require "models/customer"
|
|
12
|
+
require "models/firm"
|
|
13
|
+
|
|
14
|
+
module ActiveRecord
|
|
15
|
+
module Model
|
|
16
|
+
class CalculationQueryTest < SpannerAdapter::TestCase
|
|
17
|
+
include SpannerAdapter::Associations::TestHelper
|
|
18
|
+
|
|
19
|
+
attr_accessor :customer, :accounts
|
|
20
|
+
|
|
21
|
+
def setup
|
|
22
|
+
super
|
|
23
|
+
|
|
24
|
+
@customer = Customer.new name: "Customer - 1"
|
|
25
|
+
@accounts = []
|
|
26
|
+
|
|
27
|
+
[10, 21, 1007, 3].each_with_index do |credit_limit, i|
|
|
28
|
+
@accounts << Account.create!(
|
|
29
|
+
name: "Account#{i}", customer: customer, credit_limit: credit_limit
|
|
30
|
+
)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def teardown
|
|
35
|
+
super
|
|
36
|
+
|
|
37
|
+
Account.delete_all
|
|
38
|
+
Customer.delete_all
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def test_pluck_single_field
|
|
42
|
+
expected_ids = @accounts.map(&:id).sort
|
|
43
|
+
ids = Account.pluck(:id).sort
|
|
44
|
+
assert_equal expected_ids, ids
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def test_pluck_multi_fields
|
|
48
|
+
expected_values = @accounts.sort_by{|a| a.id }.map{|a| [a.id, a.name]}
|
|
49
|
+
|
|
50
|
+
values = Account.pluck(:id, :name).sort_by{|v| v.first }
|
|
51
|
+
assert_equal expected_values, values
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def test_get_ids
|
|
55
|
+
expected_ids = @accounts.map(&:id).sort
|
|
56
|
+
|
|
57
|
+
assert_equal expected_ids, Account.ids.sort
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def test_pick_one_field
|
|
61
|
+
assert_equal "Account0", Account.order(:name).pick(:name)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def test_pick_two_field
|
|
65
|
+
assert_equal ["Account0", 10], Account.order(:name).pick(:name, :credit_limit)
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def test_count_all
|
|
69
|
+
assert_equal 4, Account.count(:all)
|
|
70
|
+
assert_equal 4, Account.count(:all)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def test_distinct_count
|
|
74
|
+
Account.create name: "Account-101", credit_limit: 3
|
|
75
|
+
assert_equal 4, Account.distinct.count(:credit_limit)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def test_group_count
|
|
79
|
+
Account.create name: "Account-101", credit_limit: 3
|
|
80
|
+
|
|
81
|
+
expected_values = { 3 => 2, 10 => 1, 21 => 1, 1007 => 1}
|
|
82
|
+
assert_equal expected_values, Account.group(:credit_limit).count
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def test_sum_field
|
|
86
|
+
assert_equal 1041, Account.sum(:credit_limit)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def test_resolve_aliased_attributes
|
|
90
|
+
assert_equal 1041, Account.sum(:available_credit)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def test_average_field
|
|
94
|
+
assert_equal 260.25, Account.average(:credit_limit)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def test_get_maximum_of_field
|
|
98
|
+
assert_equal 1007, Account.maximum(:credit_limit)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def test_get_maximum_of_field_with_include
|
|
102
|
+
customer2 = Customer.create! name: "Customer - 2"
|
|
103
|
+
firm = Firm.create name: "Firm - 1"
|
|
104
|
+
Account.create!(customer: customer2, credit_limit: 103, firm: firm)
|
|
105
|
+
Account.create!(customer: customer2, credit_limit: 24, firm: firm)
|
|
106
|
+
|
|
107
|
+
assert_equal 103, Account.where("customer_id = ?", customer2.id).includes(:firm).maximum(:credit_limit)
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def test_get_minimum_of_field
|
|
111
|
+
assert_equal 3, Account.minimum(:credit_limit)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def test_calculate_count
|
|
115
|
+
assert_equal 4, Account.calculate(:count, "*")
|
|
116
|
+
assert_equal 4, Account.calculate(:count, :all)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def test_caclulate_sum
|
|
120
|
+
assert_equal 1041, Account.calculate(:sum, :credit_limit)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def test_caclulate_average
|
|
124
|
+
assert_equal 260.25, Account.calculate(:average, :credit_limit)
|
|
125
|
+
end
|
|
126
|
+
end
|
|
127
|
+
end
|
|
128
|
+
end
|
|
@@ -0,0 +1,126 @@
|
|
|
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
|
+
# frozen_string_literal: true
|
|
8
|
+
|
|
9
|
+
require "test_helper"
|
|
10
|
+
require "models/singer"
|
|
11
|
+
|
|
12
|
+
module ActiveRecord
|
|
13
|
+
module Model
|
|
14
|
+
class GeneratedColumnTest < SpannerAdapter::TestCase
|
|
15
|
+
include SpannerAdapter::Associations::TestHelper
|
|
16
|
+
|
|
17
|
+
# Runs the given block in a transaction with the given isolation level, or without a transaction if isolation is
|
|
18
|
+
# nil.
|
|
19
|
+
def run_in_transaction isolation
|
|
20
|
+
if isolation
|
|
21
|
+
Base.transaction isolation: isolation do
|
|
22
|
+
yield
|
|
23
|
+
end
|
|
24
|
+
else
|
|
25
|
+
yield
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def test_create_non_null
|
|
30
|
+
[nil, :serializable, :buffered_mutations].each do |isolation|
|
|
31
|
+
singer = nil
|
|
32
|
+
run_in_transaction isolation do
|
|
33
|
+
singer = Singer.create first_name: "Pete", last_name: "Allison"
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
singer.reload
|
|
37
|
+
assert_equal "Pete Allison", singer.full_name
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def test_create_null
|
|
42
|
+
[nil, :serializable, :buffered_mutations].each do |isolation|
|
|
43
|
+
singer = nil
|
|
44
|
+
run_in_transaction isolation do
|
|
45
|
+
singer = Singer.create last_name: "Allison"
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
singer.reload
|
|
49
|
+
assert_equal "Allison", singer.full_name
|
|
50
|
+
end
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def test_update_non_null
|
|
54
|
+
[nil, :serializable, :buffered_mutations].each do |isolation|
|
|
55
|
+
singer = Singer.create first_name: "Pete", last_name: "Allison"
|
|
56
|
+
singer.reload # reload to ensure the full_name attribute is populated.
|
|
57
|
+
run_in_transaction isolation do
|
|
58
|
+
singer.update first_name: "Alice"
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
singer.reload
|
|
62
|
+
assert_equal "Alice Allison", singer.full_name
|
|
63
|
+
end
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def test_update_null
|
|
67
|
+
[nil, :serializable, :buffered_mutations].each do |isolation|
|
|
68
|
+
singer = Singer.create first_name: "Pete", last_name: "Allison"
|
|
69
|
+
singer.reload # reload to ensure the full_name attribute is populated.
|
|
70
|
+
run_in_transaction isolation do
|
|
71
|
+
singer.update first_name: nil
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
singer.reload
|
|
75
|
+
assert_equal "Allison", singer.full_name
|
|
76
|
+
end
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
def test_create_with_value_for_generated_column
|
|
80
|
+
# Note: The statement itself will not fail for an explicit transaction that uses buffered transactions.
|
|
81
|
+
# Instead, the commit will fail. That is tested in a separate test case.
|
|
82
|
+
[nil, :serializable].each do |isolation|
|
|
83
|
+
run_in_transaction isolation do
|
|
84
|
+
assert_raises ActiveRecord::StatementInvalid do
|
|
85
|
+
Singer.create first_name: "Pete", last_name: "Allison", full_name: "Alice Peterson"
|
|
86
|
+
end
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def test_create_with_value_for_generated_column_buffered_mutations
|
|
92
|
+
# The transaction itself will raise an error, as the failure occurs during the commit.
|
|
93
|
+
assert_raises ActiveRecord::StatementInvalid do
|
|
94
|
+
Singer.transaction isolation: :buffered_mutations do
|
|
95
|
+
Singer.create first_name: "Pete", last_name: "Allison", full_name: "Alice Peterson"
|
|
96
|
+
end
|
|
97
|
+
end
|
|
98
|
+
end
|
|
99
|
+
|
|
100
|
+
def test_update_with_value_for_generated_column
|
|
101
|
+
# Note: The statement itself will not fail for an explicit transaction that uses buffered transactions.
|
|
102
|
+
# Instead, the commit will fail. That is tested in a separate test case.
|
|
103
|
+
[nil, :serializable].each do |isolation|
|
|
104
|
+
singer = Singer.create first_name: "Pete", last_name: "Allison"
|
|
105
|
+
singer.reload # reload to ensure the full_name attribute is populated.
|
|
106
|
+
run_in_transaction isolation do
|
|
107
|
+
assert_raises ActiveRecord::StatementInvalid do
|
|
108
|
+
Singer.update full_name: "Alice Peterson"
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def test_update_with_value_for_generated_column_buffered_mutations
|
|
115
|
+
singer = Singer.create first_name: "Pete", last_name: "Allison"
|
|
116
|
+
singer.reload # reload to ensure the full_name attribute is populated.
|
|
117
|
+
# The transaction itself will raise an error, as the failure occurs during the commit.
|
|
118
|
+
assert_raises ActiveRecord::StatementInvalid do
|
|
119
|
+
Singer.transaction isolation: :buffered_mutations do
|
|
120
|
+
Singer.update full_name: "Alice Peterson"
|
|
121
|
+
end
|
|
122
|
+
end
|
|
123
|
+
end
|
|
124
|
+
end
|
|
125
|
+
end
|
|
126
|
+
end
|
|
@@ -0,0 +1,122 @@
|
|
|
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
|
+
require "test_helper"
|
|
10
|
+
require "models/author"
|
|
11
|
+
require "models/post"
|
|
12
|
+
require "models/comment"
|
|
13
|
+
require "models/address"
|
|
14
|
+
require "models/organization"
|
|
15
|
+
|
|
16
|
+
module ActiveRecord
|
|
17
|
+
module Model
|
|
18
|
+
class MutationTest < SpannerAdapter::TestCase
|
|
19
|
+
include SpannerAdapter::Associations::TestHelper
|
|
20
|
+
|
|
21
|
+
attr_accessor :author, :post, :comment
|
|
22
|
+
|
|
23
|
+
def setup
|
|
24
|
+
super
|
|
25
|
+
|
|
26
|
+
@author = Author.create name: "David"
|
|
27
|
+
@post = Post.create title: "Title - 1", author: author
|
|
28
|
+
@comment = Comment.create comment: "Comment - 1", post: post
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def teardown
|
|
32
|
+
super
|
|
33
|
+
Comment.destroy_all
|
|
34
|
+
Post.destroy_all
|
|
35
|
+
Author.destroy_all
|
|
36
|
+
Organization.destroy_all
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def test_update_all
|
|
40
|
+
organization = Organization.create name: "Org - 1"
|
|
41
|
+
organization.authors << author
|
|
42
|
+
organization.authors << Author.new(name: "John")
|
|
43
|
+
|
|
44
|
+
organization.reload
|
|
45
|
+
|
|
46
|
+
assert_equal 2, organization.authors.where(registered_date: nil).count
|
|
47
|
+
|
|
48
|
+
date = Date.new(2020, 01, 31)
|
|
49
|
+
organization.authors.update_all(registered_date: date)
|
|
50
|
+
|
|
51
|
+
assert_equal 0, organization.authors.where(registered_date: nil).count
|
|
52
|
+
assert_equal 2, organization.authors.where(registered_date: date).count
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
def test_offset_and_limit_update
|
|
56
|
+
post = Post.create title: "Title - 1", author: author
|
|
57
|
+
5.times.each do |i|
|
|
58
|
+
Comment.create comment: "Comment - #{i+1}", post: post
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
assert_equal 5, post.comments.count
|
|
62
|
+
assert_equal 3, post.comments.offset(1).limit(3).update_all(comment: "New Comment")
|
|
63
|
+
|
|
64
|
+
post.reload
|
|
65
|
+
assert_equal 3, post.comments.where(comment: "New Comment").count
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def test_update_all_with_joins
|
|
69
|
+
post = Post.create title: "Title - 1", author: author
|
|
70
|
+
post.comments << Comment.new(comment: "Comment - 1")
|
|
71
|
+
|
|
72
|
+
posts = Post.joins(:comments).where(comments: { comment: "Comment - 1" })
|
|
73
|
+
|
|
74
|
+
assert_equal true, posts.exists?
|
|
75
|
+
assert_equal posts.count, posts.update_all(title: "Title - 1 Update")
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def test_update_counters_with_joins
|
|
79
|
+
post = Post.create title: "Title - 1", author: author
|
|
80
|
+
assert_nil post.comments_count
|
|
81
|
+
|
|
82
|
+
post.comments << Comment.new(comment: "Comment - 201")
|
|
83
|
+
assert_equal 1, post.reload.comments_count
|
|
84
|
+
|
|
85
|
+
Post.joins(:comments).where(comments: { comment: "Comment - 201" }).update_counters(comments_count: 10)
|
|
86
|
+
|
|
87
|
+
assert_equal 11, post.reload.comments_count
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def test_destroy_all
|
|
91
|
+
authors = Author.where name: "David"
|
|
92
|
+
|
|
93
|
+
assert_equal [author], authors.to_a
|
|
94
|
+
|
|
95
|
+
authors.destroy_all
|
|
96
|
+
assert_equal 0, Author.count
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def test_dependent_destroy
|
|
100
|
+
organization = Organization.create name: "Org - 1"
|
|
101
|
+
organization.authors << author
|
|
102
|
+
organization.authors << Author.new(name: "John")
|
|
103
|
+
|
|
104
|
+
organization.reload
|
|
105
|
+
assert_equal 2, organization.authors.count
|
|
106
|
+
|
|
107
|
+
organization.destroy
|
|
108
|
+
|
|
109
|
+
assert_nil Organization.find_by(id: organization.id)
|
|
110
|
+
assert_equal 0, Author.count
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
def test_delete_all
|
|
114
|
+
assert_equal 1, Author.count
|
|
115
|
+
|
|
116
|
+
Author.delete_all
|
|
117
|
+
|
|
118
|
+
assert_equal 0, Author.count
|
|
119
|
+
end
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
end
|