activerecord-spanner-adapter 0.3.0 → 1.0.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 +49 -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 +55 -0
- data/CODE_OF_CONDUCT.md +40 -0
- data/CONTRIBUTING.md +79 -0
- data/Gemfile +9 -4
- data/LICENSE +6 -6
- data/README.md +66 -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 +171 -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 +130 -0
- data/acceptance/cases/transactions/read_write_transactions_test.rb +248 -0
- data/acceptance/cases/type/all_types_test.rb +172 -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/json_test.rb +34 -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 +147 -0
- data/acceptance/test_helper.rb +261 -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/hints/README.md +19 -0
- data/examples/snippets/hints/Rakefile +13 -0
- data/examples/snippets/hints/application.rb +47 -0
- data/examples/snippets/hints/config/database.yml +8 -0
- data/examples/snippets/hints/db/migrate/01_create_tables.rb +23 -0
- data/examples/snippets/hints/db/schema.rb +28 -0
- data/examples/snippets/hints/db/seeds.rb +29 -0
- data/examples/snippets/hints/models/album.rb +9 -0
- data/examples/snippets/hints/models/singer.rb +9 -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/partitioned-dml/README.md +16 -0
- data/examples/snippets/partitioned-dml/Rakefile +13 -0
- data/examples/snippets/partitioned-dml/application.rb +48 -0
- data/examples/snippets/partitioned-dml/config/database.yml +8 -0
- data/examples/snippets/partitioned-dml/db/migrate/01_create_tables.rb +21 -0
- data/examples/snippets/partitioned-dml/db/schema.rb +26 -0
- data/examples/snippets/partitioned-dml/db/seeds.rb +29 -0
- data/examples/snippets/partitioned-dml/models/album.rb +9 -0
- data/examples/snippets/partitioned-dml/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 +77 -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/stale-reads/README.md +27 -0
- data/examples/snippets/stale-reads/Rakefile +13 -0
- data/examples/snippets/stale-reads/application.rb +63 -0
- data/examples/snippets/stale-reads/config/database.yml +8 -0
- data/examples/snippets/stale-reads/db/migrate/01_create_tables.rb +21 -0
- data/examples/snippets/stale-reads/db/schema.rb +26 -0
- data/examples/snippets/stale-reads/db/seeds.rb +24 -0
- data/examples/snippets/stale-reads/models/album.rb +9 -0
- data/examples/snippets/stale-reads/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 +244 -266
- 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 +185 -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 +33 -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 +238 -0
- data/lib/activerecord_spanner_adapter/connection.rb +350 -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 +262 -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 +154 -0
- data/lib/activerecord_spanner_adapter/version.rb +9 -0
- data/lib/arel/visitors/spanner.rb +111 -0
- data/lib/spanner_client_ext.rb +107 -0
- data/renovate.json +5 -0
- metadata +405 -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,248 @@
|
|
|
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/author"
|
|
11
|
+
require "models/post"
|
|
12
|
+
require "models/comment"
|
|
13
|
+
require "models/organization"
|
|
14
|
+
|
|
15
|
+
module ActiveRecord
|
|
16
|
+
module Transactions
|
|
17
|
+
class ReadWriteTransactionsTest < SpannerAdapter::TestCase
|
|
18
|
+
include SpannerAdapter::Associations::TestHelper
|
|
19
|
+
|
|
20
|
+
attr_accessor :organization, :author, :post, :comment
|
|
21
|
+
|
|
22
|
+
def create_test_records
|
|
23
|
+
@organization = Organization.create name: "Organization 1"
|
|
24
|
+
@author = Author.create name: "David", organization: organization
|
|
25
|
+
@post = Post.create title: "Title - 1", author: author
|
|
26
|
+
@comment = Comment.create comment: "Comment - 1", post: post
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def teardown
|
|
30
|
+
super
|
|
31
|
+
|
|
32
|
+
delete_test_records
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def delete_test_records
|
|
36
|
+
Comment.destroy_all
|
|
37
|
+
Post.destroy_all
|
|
38
|
+
Author.destroy_all
|
|
39
|
+
Organization.destroy_all
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
# Runs the given block in a transaction with the given isolation level, or without a transaction if isolation is
|
|
43
|
+
# nil.
|
|
44
|
+
def run_in_transaction isolation
|
|
45
|
+
if isolation
|
|
46
|
+
Base.transaction isolation: isolation do
|
|
47
|
+
yield
|
|
48
|
+
end
|
|
49
|
+
else
|
|
50
|
+
yield
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def test_create_multiple_records
|
|
55
|
+
[nil, :serializable, :buffered_mutations].each do |isolation|
|
|
56
|
+
initial_author_count = Author.count
|
|
57
|
+
initial_posts_count = Post.count
|
|
58
|
+
initial_comment_count = Comment.count
|
|
59
|
+
|
|
60
|
+
run_in_transaction isolation do
|
|
61
|
+
author = Author.create name: "Author 1", organization: organization
|
|
62
|
+
posts = Post.create [{title: "Post 1", author: author}, {title: "Post 2", author: author}]
|
|
63
|
+
Comment.create [
|
|
64
|
+
{comment: "Comment 1", post: posts[0]},
|
|
65
|
+
{comment: "Comment 2", post: posts[1]}
|
|
66
|
+
]
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
# Verify that all the records were created.
|
|
70
|
+
assert_equal initial_author_count + 1, Author.count
|
|
71
|
+
assert_equal initial_posts_count + 2, Post.count
|
|
72
|
+
assert_equal initial_comment_count + 2, Comment.count
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
def test_update_multiple_records
|
|
77
|
+
[nil, :serializable, :buffered_mutations].each do |isolation|
|
|
78
|
+
create_test_records
|
|
79
|
+
|
|
80
|
+
run_in_transaction isolation do
|
|
81
|
+
organization.update name: "Updated name #{isolation}"
|
|
82
|
+
author.update name: "Updated name #{isolation}"
|
|
83
|
+
post.update title: "Updated title #{isolation}"
|
|
84
|
+
comment.update comment: "Updated comment #{isolation}"
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
assert_equal "Updated name #{isolation}", organization.reload.name
|
|
88
|
+
assert_equal "Updated name #{isolation}", author.reload.name
|
|
89
|
+
assert_equal "Updated title #{isolation}", post.reload.title
|
|
90
|
+
assert_equal "Updated comment #{isolation}", comment.reload.comment
|
|
91
|
+
end
|
|
92
|
+
end
|
|
93
|
+
|
|
94
|
+
def test_destroy_multiple_records
|
|
95
|
+
[nil, :serializable, :buffered_mutations].each do |isolation|
|
|
96
|
+
create_test_records
|
|
97
|
+
|
|
98
|
+
run_in_transaction isolation do
|
|
99
|
+
comment.destroy
|
|
100
|
+
post.destroy
|
|
101
|
+
author.destroy
|
|
102
|
+
organization.destroy
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
assert_equal 0, Organization.count
|
|
106
|
+
assert_equal 0, Author.count
|
|
107
|
+
assert_equal 0, Post.count
|
|
108
|
+
assert_equal 0, Comment.count
|
|
109
|
+
end
|
|
110
|
+
end
|
|
111
|
+
|
|
112
|
+
def test_delete_multiple_records
|
|
113
|
+
[nil, :serializable, :buffered_mutations].each do |isolation|
|
|
114
|
+
create_test_records
|
|
115
|
+
|
|
116
|
+
run_in_transaction isolation do
|
|
117
|
+
comment.delete
|
|
118
|
+
post.delete
|
|
119
|
+
author.delete
|
|
120
|
+
organization.delete
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
assert_equal 0, Organization.count
|
|
124
|
+
assert_equal 0, Author.count
|
|
125
|
+
assert_equal 0, Post.count
|
|
126
|
+
assert_equal 0, Comment.count
|
|
127
|
+
end
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def test_destroy_parent_record
|
|
131
|
+
[nil, :serializable, :buffered_mutations].each do |isolation|
|
|
132
|
+
create_test_records
|
|
133
|
+
|
|
134
|
+
run_in_transaction isolation do
|
|
135
|
+
# Only destroy the top-level record. This should cascade to the author records, as those are
|
|
136
|
+
# marked with `dependent: destroy`. The dependants of Author are however not marked with
|
|
137
|
+
# `dependent: destroy`, which means that those will not be deleted, but the reference to Author will
|
|
138
|
+
# be set to nil.
|
|
139
|
+
organization.destroy
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
assert_equal 0, Organization.count
|
|
143
|
+
assert_equal 0, Author.count
|
|
144
|
+
assert_equal 1, Post.count # These are not marked with `dependent: destroy`
|
|
145
|
+
assert_nil Post.find(post.id).author # The author is set to NULL instead of deleting the posts.
|
|
146
|
+
assert_equal 1, Comment.count
|
|
147
|
+
|
|
148
|
+
# Delete all remaining test records to make sure the next iteration starts clean.
|
|
149
|
+
delete_test_records
|
|
150
|
+
end
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def test_multiple_consecutive_transactions
|
|
154
|
+
isolation_levels = [nil, :serializable, :buffered_mutations]
|
|
155
|
+
isolation_levels.each do |isolation|
|
|
156
|
+
|
|
157
|
+
run_in_transaction isolation do
|
|
158
|
+
create_test_records
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
isolation_levels.each do |isolation|
|
|
162
|
+
run_in_transaction isolation do
|
|
163
|
+
create_test_records
|
|
164
|
+
end
|
|
165
|
+
end
|
|
166
|
+
|
|
167
|
+
transaction_count = isolation_levels.length + 1
|
|
168
|
+
assert_equal transaction_count, Organization.count
|
|
169
|
+
assert_equal transaction_count, Author.count
|
|
170
|
+
assert_equal transaction_count, Post.count
|
|
171
|
+
assert_equal transaction_count, Comment.count
|
|
172
|
+
|
|
173
|
+
delete_test_records
|
|
174
|
+
end
|
|
175
|
+
end
|
|
176
|
+
|
|
177
|
+
def test_read_your_writes
|
|
178
|
+
[nil, :serializable, :buffered_mutations].each do |isolation|
|
|
179
|
+
initial_author_count = Author.count
|
|
180
|
+
initial_posts_count = Post.count
|
|
181
|
+
initial_comment_count = Comment.count
|
|
182
|
+
|
|
183
|
+
run_in_transaction isolation do
|
|
184
|
+
author = Author.create name: "Author 1", organization: organization
|
|
185
|
+
posts = Post.create [{title: "Post 1", author: author}, {title: "Post 2", author: author}]
|
|
186
|
+
Comment.create [
|
|
187
|
+
{comment: "Comment 1", post: posts[0]},
|
|
188
|
+
{comment: "Comment 2", post: posts[1]}
|
|
189
|
+
]
|
|
190
|
+
|
|
191
|
+
# Verify that the new records are visible, unless we are working with an actual transaction that
|
|
192
|
+
# uses buffered mutations. Implicit transactions (isolation = nil) will also use mutations, but each
|
|
193
|
+
# create call will automatically be committed, and the changes will be visible here.
|
|
194
|
+
unless isolation == :buffered_mutations
|
|
195
|
+
assert_equal initial_author_count + 1, Author.count
|
|
196
|
+
assert_equal initial_posts_count + 2, Post.count
|
|
197
|
+
assert_equal initial_comment_count + 2, Comment.count
|
|
198
|
+
else
|
|
199
|
+
assert_equal initial_author_count, Author.count
|
|
200
|
+
assert_equal initial_posts_count, Post.count
|
|
201
|
+
assert_equal initial_comment_count, Comment.count
|
|
202
|
+
end
|
|
203
|
+
end
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def test_create_commit_timestamp
|
|
208
|
+
[nil, :serializable, :buffered_mutations].each do |isolation|
|
|
209
|
+
current_timestamp = Organization.connection.select_all("SELECT CURRENT_TIMESTAMP() AS t").to_a[0]["t"]
|
|
210
|
+
organization = nil
|
|
211
|
+
run_in_transaction isolation do
|
|
212
|
+
organization = Organization.create name: "Org with commit timestamp", last_updated: :commit_timestamp
|
|
213
|
+
end
|
|
214
|
+
|
|
215
|
+
organization.reload
|
|
216
|
+
assert organization.last_updated
|
|
217
|
+
assert organization.last_updated > current_timestamp
|
|
218
|
+
end
|
|
219
|
+
end
|
|
220
|
+
|
|
221
|
+
def test_update_commit_timestamp
|
|
222
|
+
[nil, :serializable, :buffered_mutations].each do |isolation|
|
|
223
|
+
organization = Organization.create name: "Org without commit timestamp"
|
|
224
|
+
current_timestamp = Organization.connection.select_all("SELECT CURRENT_TIMESTAMP() AS t").to_a[0]["t"]
|
|
225
|
+
|
|
226
|
+
run_in_transaction isolation do
|
|
227
|
+
organization.update last_updated: :commit_timestamp
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
organization.reload
|
|
231
|
+
assert organization.last_updated
|
|
232
|
+
assert organization.last_updated > current_timestamp
|
|
233
|
+
end
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def test_pdml
|
|
237
|
+
create_test_records
|
|
238
|
+
assert Comment.count > 0
|
|
239
|
+
|
|
240
|
+
Comment.transaction isolation: :pdml do
|
|
241
|
+
Comment.delete_all
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
assert_equal 0, Comment.count
|
|
245
|
+
end
|
|
246
|
+
end
|
|
247
|
+
end
|
|
248
|
+
end
|
|
@@ -0,0 +1,172 @@
|
|
|
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/all_types"
|
|
11
|
+
|
|
12
|
+
module ActiveRecord
|
|
13
|
+
module Type
|
|
14
|
+
class AllTypesTest < 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 create_test_record
|
|
30
|
+
AllTypes.create col_string: "string", col_int64: 100, col_float64: 3.14, col_numeric: 6.626, col_bool: true,
|
|
31
|
+
col_bytes: StringIO.new("bytes"), col_date: ::Date.new(2021, 6, 23),
|
|
32
|
+
col_timestamp: ::Time.new(2021, 6, 23, 17, 8, 21, "+02:00"),
|
|
33
|
+
col_json: ENV["SPANNER_EMULATOR_HOST"] ? "" : { kind: "user_renamed", change: %w[jack john]},
|
|
34
|
+
col_array_string: ["string1", nil, "string2"],
|
|
35
|
+
col_array_int64: [100, nil, 200],
|
|
36
|
+
col_array_float64: [3.14, nil, 2.0/3.0],
|
|
37
|
+
col_array_numeric: [6.626, nil, 3.20],
|
|
38
|
+
col_array_bool: [true, nil, false],
|
|
39
|
+
col_array_bytes: [StringIO.new("bytes1"), nil, StringIO.new("bytes2")],
|
|
40
|
+
col_array_date: [::Date.new(2021, 6, 23), nil, ::Date.new(2021, 6, 24)],
|
|
41
|
+
col_array_timestamp: [::Time.new(2021, 6, 23, 17, 8, 21, "+02:00"), nil, \
|
|
42
|
+
::Time.new(2021, 6, 24, 17, 8, 21, "+02:00")],
|
|
43
|
+
col_array_json: ENV["SPANNER_EMULATOR_HOST"] ? [""] : \
|
|
44
|
+
[{ kind: "user_renamed", change: %w[jack john]}, nil, \
|
|
45
|
+
{ kind: "user_renamed", change: %w[alice meredith]}]
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def test_create_record
|
|
49
|
+
[nil, :serializable, :buffered_mutations].each do |isolation|
|
|
50
|
+
initial_count = AllTypes.count
|
|
51
|
+
record = nil
|
|
52
|
+
run_in_transaction isolation do
|
|
53
|
+
record = create_test_record
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
# Verify that the record was created and that the data can be read back.
|
|
57
|
+
assert_equal initial_count + 1, AllTypes.count
|
|
58
|
+
|
|
59
|
+
record = AllTypes.find record.id
|
|
60
|
+
assert_equal "string", record.col_string
|
|
61
|
+
assert_equal 100, record.col_int64
|
|
62
|
+
assert_equal 3.14, record.col_float64
|
|
63
|
+
assert_equal 6.626, record.col_numeric
|
|
64
|
+
assert_equal true, record.col_bool
|
|
65
|
+
assert_equal StringIO.new("bytes").read, record.col_bytes.read
|
|
66
|
+
assert_equal ::Date.new(2021, 6, 23), record.col_date
|
|
67
|
+
assert_equal ::Time.new(2021, 6, 23, 17, 8, 21, "+02:00").utc, record.col_timestamp.utc
|
|
68
|
+
assert_equal ({"kind" => "user_renamed", "change" => %w[jack john]}),
|
|
69
|
+
record.col_json unless ENV["SPANNER_EMULATOR_HOST"]
|
|
70
|
+
|
|
71
|
+
assert_equal ["string1", nil, "string2"], record.col_array_string
|
|
72
|
+
assert_equal [100, nil, 200], record.col_array_int64
|
|
73
|
+
assert_equal [3.14, nil, 2.0/3.0], record.col_array_float64
|
|
74
|
+
assert_equal [6.626, nil, 3.20], record.col_array_numeric
|
|
75
|
+
assert_equal [true, nil, false], record.col_array_bool
|
|
76
|
+
assert_equal [StringIO.new("bytes1"), nil, StringIO.new("bytes2")].map { |bytes| bytes&.read },
|
|
77
|
+
record.col_array_bytes.map { |bytes| bytes&.read }
|
|
78
|
+
assert_equal [::Date.new(2021, 6, 23), nil, ::Date.new(2021, 6, 24)], record.col_array_date
|
|
79
|
+
assert_equal [::Time.new(2021, 6, 23, 17, 8, 21, "+02:00"), \
|
|
80
|
+
nil, \
|
|
81
|
+
::Time.new(2021, 6, 24, 17, 8, 21, "+02:00")].map { |timestamp| timestamp&.utc },
|
|
82
|
+
record.col_array_timestamp.map { |timestamp| timestamp&.utc}
|
|
83
|
+
assert_equal [{"kind" => "user_renamed", "change" => %w[jack john]}, \
|
|
84
|
+
nil, \
|
|
85
|
+
{"kind" => "user_renamed", "change" => %w[alice meredith]}],
|
|
86
|
+
record.col_array_json unless ENV["SPANNER_EMULATOR_HOST"]
|
|
87
|
+
end
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
def test_update_record
|
|
91
|
+
[nil, :serializable, :buffered_mutations].each do |isolation|
|
|
92
|
+
# First create a test record outside a transaction.
|
|
93
|
+
record = create_test_record
|
|
94
|
+
|
|
95
|
+
run_in_transaction isolation do
|
|
96
|
+
# Update the record in a transaction using different isolation levels.
|
|
97
|
+
record.update col_string: "new string", col_int64: 200, col_float64: 6.28, col_numeric: 10.1,
|
|
98
|
+
col_bool: false, col_bytes: StringIO.new("new bytes"),
|
|
99
|
+
col_date: ::Date.new(2021, 6, 28),
|
|
100
|
+
col_timestamp: ::Time.new(2021, 6, 28, 11, 22, 21, "+02:00"),
|
|
101
|
+
col_json: ENV["SPANNER_EMULATOR_HOST"] ? "" : { kind: "user_created", change: %w[jack alice]},
|
|
102
|
+
col_array_string: ["new string 1", "new string 2"],
|
|
103
|
+
col_array_int64: [300, 200, 100],
|
|
104
|
+
col_array_float64: [1.1, 2.2, 3.3],
|
|
105
|
+
col_array_numeric: [3.3, 2.2, 1.1],
|
|
106
|
+
col_array_bool: [false, true, false],
|
|
107
|
+
col_array_bytes: [StringIO.new("new bytes 1"), StringIO.new("new bytes 2")],
|
|
108
|
+
col_array_date: [::Date.new(2021, 6, 28)],
|
|
109
|
+
col_array_timestamp: [::Time.utc(2020, 12, 31, 0, 0, 0)],
|
|
110
|
+
col_array_json: ENV["SPANNER_EMULATOR_HOST"] ?
|
|
111
|
+
[""] : \
|
|
112
|
+
[{ kind: "user_created", change: %w[jack alice]}]
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
# Verify that the record was updated.
|
|
116
|
+
record = AllTypes.find record.id
|
|
117
|
+
assert_equal "new string", record.col_string
|
|
118
|
+
assert_equal 200, record.col_int64
|
|
119
|
+
assert_equal 6.28, record.col_float64
|
|
120
|
+
assert_equal 10.1, record.col_numeric
|
|
121
|
+
assert_equal false, record.col_bool
|
|
122
|
+
assert_equal StringIO.new("new bytes").read, record.col_bytes.read
|
|
123
|
+
assert_equal ::Date.new(2021, 6, 28), record.col_date
|
|
124
|
+
assert_equal ::Time.new(2021, 6, 28, 11, 22, 21, "+02:00").utc, record.col_timestamp.utc
|
|
125
|
+
assert_equal ({"kind" => "user_created", "change" => %w[jack alice]}),
|
|
126
|
+
record.col_json unless ENV["SPANNER_EMULATOR_HOST"]
|
|
127
|
+
|
|
128
|
+
assert_equal ["new string 1", "new string 2"], record.col_array_string
|
|
129
|
+
assert_equal [300, 200, 100], record.col_array_int64
|
|
130
|
+
assert_equal [1.1, 2.2, 3.3], record.col_array_float64
|
|
131
|
+
assert_equal [3.3, 2.2, 1.1], record.col_array_numeric
|
|
132
|
+
assert_equal [false, true, false], record.col_array_bool
|
|
133
|
+
assert_equal [StringIO.new("new bytes 1"), StringIO.new("new bytes 2")].map(&:read),
|
|
134
|
+
record.col_array_bytes.map(&:read)
|
|
135
|
+
assert_equal [::Date.new(2021, 6, 28)], record.col_array_date
|
|
136
|
+
assert_equal [::Time.utc(2020, 12, 31, 0, 0, 0)], record.col_array_timestamp.map(&:utc)
|
|
137
|
+
assert_equal [{"kind" => "user_created", "change" => %w[jack alice]}],
|
|
138
|
+
record.col_array_json unless ENV["SPANNER_EMULATOR_HOST"]
|
|
139
|
+
end
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def test_create_empty_arrays
|
|
143
|
+
[nil, :serializable, :buffered_mutations].each do |isolation|
|
|
144
|
+
record = nil
|
|
145
|
+
run_in_transaction isolation do
|
|
146
|
+
record = AllTypes.create \
|
|
147
|
+
col_array_string: [],
|
|
148
|
+
col_array_int64: [],
|
|
149
|
+
col_array_float64: [],
|
|
150
|
+
col_array_numeric: [],
|
|
151
|
+
col_array_bool: [],
|
|
152
|
+
col_array_bytes: [],
|
|
153
|
+
col_array_date: [],
|
|
154
|
+
col_array_timestamp: [],
|
|
155
|
+
col_array_json: []
|
|
156
|
+
end
|
|
157
|
+
|
|
158
|
+
record = AllTypes.find record.id
|
|
159
|
+
assert_equal [], record.col_array_string
|
|
160
|
+
assert_equal [], record.col_array_int64
|
|
161
|
+
assert_equal [], record.col_array_float64
|
|
162
|
+
assert_equal [], record.col_array_numeric
|
|
163
|
+
assert_equal [], record.col_array_bool
|
|
164
|
+
assert_equal [], record.col_array_bytes
|
|
165
|
+
assert_equal [], record.col_array_date
|
|
166
|
+
assert_equal [], record.col_array_timestamp
|
|
167
|
+
assert_equal [], record.col_array_json
|
|
168
|
+
end
|
|
169
|
+
end
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
|
@@ -0,0 +1,59 @@
|
|
|
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
|
+
module Type
|
|
13
|
+
class BinaryTest < SpannerAdapter::TestCase
|
|
14
|
+
include SpannerAdapter::Types::TestHelper
|
|
15
|
+
|
|
16
|
+
def test_convert_to_sql_type
|
|
17
|
+
assert_equal "BYTES(MAX)", connection.type_to_sql(:binary)
|
|
18
|
+
assert_equal "BYTES(1024)", connection.type_to_sql(:binary, limit: 1024)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def test_set_binary_data_io_in_create
|
|
22
|
+
data = StringIO.new "hello"
|
|
23
|
+
|
|
24
|
+
record = TestTypeModel.create(data: data)
|
|
25
|
+
record.reload
|
|
26
|
+
|
|
27
|
+
assert_equal "hello", record.data.read
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def test_set_binary_data_byte_string_in_create
|
|
31
|
+
data = StringIO.new "hello1"
|
|
32
|
+
|
|
33
|
+
record = TestTypeModel.create(data: data.read)
|
|
34
|
+
record.reload
|
|
35
|
+
|
|
36
|
+
assert_equal "hello1", record.data.read
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def test_check_max_limit
|
|
40
|
+
str = "a" * 256
|
|
41
|
+
|
|
42
|
+
assert_raise(ActiveRecord::StatementInvalid) {
|
|
43
|
+
TestTypeModel.create(name: str)
|
|
44
|
+
}
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def test_set_binary_data_from_file
|
|
48
|
+
Tempfile.create do |f|
|
|
49
|
+
f << "hello 123"
|
|
50
|
+
|
|
51
|
+
record = TestTypeModel.create(file: f)
|
|
52
|
+
record.reload
|
|
53
|
+
|
|
54
|
+
assert_equal "hello 123", record.file.read
|
|
55
|
+
end
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
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
|
+
module Type
|
|
13
|
+
class BooleanTest < SpannerAdapter::TestCase
|
|
14
|
+
include SpannerAdapter::Types::TestHelper
|
|
15
|
+
|
|
16
|
+
def test_convert_to_sql_type
|
|
17
|
+
assert_equal "BOOL", connection.type_to_sql(:boolean)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def test_set_boolean_value_in_create
|
|
21
|
+
record = TestTypeModel.create(active: true)
|
|
22
|
+
record.reload
|
|
23
|
+
assert_equal true, record.active
|
|
24
|
+
|
|
25
|
+
record = TestTypeModel.create(active: false)
|
|
26
|
+
record.reload
|
|
27
|
+
assert_equal false, record.active
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,32 @@
|
|
|
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
|
+
module Type
|
|
13
|
+
class DateTest < SpannerAdapter::TestCase
|
|
14
|
+
include SpannerAdapter::Types::TestHelper
|
|
15
|
+
|
|
16
|
+
def test_convert_to_sql_type
|
|
17
|
+
assert_equal "DATE", connection.type_to_sql(:date)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def test_set_date
|
|
21
|
+
expected_date = ::Date.new 2020, 1, 31
|
|
22
|
+
record = TestTypeModel.new start_date: expected_date
|
|
23
|
+
|
|
24
|
+
assert_equal expected_date, record.start_date
|
|
25
|
+
|
|
26
|
+
record.save!
|
|
27
|
+
record.reload
|
|
28
|
+
assert_equal expected_date, record.start_date
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
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
|
+
module Type
|
|
13
|
+
class DateTimeTest < SpannerAdapter::TestCase
|
|
14
|
+
include SpannerAdapter::Types::TestHelper
|
|
15
|
+
|
|
16
|
+
def test_convert_to_sql_type
|
|
17
|
+
assert_equal "TIMESTAMP", connection.type_to_sql(:datetime)
|
|
18
|
+
assert_equal "TIMESTAMP", connection.type_to_sql(:datetime, limit: 128)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def test_datetime_seconds_precision_applied_to_timestamp
|
|
22
|
+
expected_time = ::Time.now
|
|
23
|
+
record = TestTypeModel.new start_datetime: expected_time
|
|
24
|
+
|
|
25
|
+
assert_equal expected_time, record.start_datetime
|
|
26
|
+
assert_equal expected_time.usec, record.start_datetime.usec
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,27 @@
|
|
|
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
|
+
module Type
|
|
13
|
+
class FloatTest < SpannerAdapter::TestCase
|
|
14
|
+
include SpannerAdapter::Types::TestHelper
|
|
15
|
+
|
|
16
|
+
def test_convert_to_sql_type
|
|
17
|
+
assert_equal "FLOAT64", connection.type_to_sql(:float)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def test_set_float_value_in_create
|
|
21
|
+
record = TestTypeModel.create(weight: 123.32199)
|
|
22
|
+
record.reload
|
|
23
|
+
assert_equal 123.32199, record.weight
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
@@ -0,0 +1,44 @@
|
|
|
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
|
+
module Type
|
|
13
|
+
class IntegerTest < SpannerAdapter::TestCase
|
|
14
|
+
include SpannerAdapter::Types::TestHelper
|
|
15
|
+
|
|
16
|
+
def test_convert_to_sql_type
|
|
17
|
+
assert_equal "INT64", connection.type_to_sql(:integer)
|
|
18
|
+
assert_equal "INT64", connection.type_to_sql(:primary_key)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def test_set_integer_value_in_create
|
|
22
|
+
record = TestTypeModel.create(length: 123)
|
|
23
|
+
|
|
24
|
+
record.reload
|
|
25
|
+
assert_equal 123, record.length
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def test_casting_models
|
|
29
|
+
type = Type::Integer.new
|
|
30
|
+
|
|
31
|
+
record = TestTypeModel.create(name: "Google")
|
|
32
|
+
assert_nil type.cast(record)
|
|
33
|
+
end
|
|
34
|
+
|
|
35
|
+
def test_values_out_of_range_can_re_assigned
|
|
36
|
+
model = TestTypeModel.new
|
|
37
|
+
model.length = 2147483648
|
|
38
|
+
model.length = 1
|
|
39
|
+
|
|
40
|
+
assert_equal 1, model.length
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
44
|
+
end
|
|
@@ -0,0 +1,34 @@
|
|
|
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
|
+
|
|
11
|
+
module ActiveRecord
|
|
12
|
+
module Type
|
|
13
|
+
class DateTest < SpannerAdapter::TestCase
|
|
14
|
+
include SpannerAdapter::Types::TestHelper
|
|
15
|
+
|
|
16
|
+
def test_convert_to_sql_type
|
|
17
|
+
assert_equal "JSON", connection.type_to_sql(:json)
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
def test_set_json
|
|
21
|
+
return if ENV["SPANNER_EMULATOR_HOST"]
|
|
22
|
+
|
|
23
|
+
expected_hash = {"key"=>"value", "array_key"=>%w[value1 value2]}
|
|
24
|
+
record = TestTypeModel.new details: {key: "value", array_key: %w[value1 value2]}
|
|
25
|
+
|
|
26
|
+
assert_equal expected_hash, record.details
|
|
27
|
+
|
|
28
|
+
record.save!
|
|
29
|
+
record.reload
|
|
30
|
+
assert_equal expected_hash, record.details
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
end
|
|
34
|
+
end
|