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,216 @@
|
|
|
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 CreateJoinTableTest < SpannerAdapter::TestCase
|
|
14
|
+
include SpannerAdapter::Migration::TestHelper
|
|
15
|
+
|
|
16
|
+
def setup
|
|
17
|
+
skip_test_table_create!
|
|
18
|
+
super
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def teardown
|
|
22
|
+
connection.ddl_batch do
|
|
23
|
+
%w(artists_musics musics_videos catalog).each do |table_name|
|
|
24
|
+
connection.drop_table table_name, if_exists: true
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def test_create_join_table
|
|
30
|
+
connection.ddl_batch do
|
|
31
|
+
connection.create_join_table :artists, :musics
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
assert_equal %w(artist_id music_id), connection.columns(:artists_musics).map(&:name).sort
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def test_create_join_table_set_not_null_by_default
|
|
38
|
+
connection.ddl_batch do
|
|
39
|
+
connection.create_join_table :artists, :musics
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
assert_equal [false, false], connection.columns(:artists_musics).map(&:null)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def test_create_join_table_with_strings
|
|
46
|
+
connection.ddl_batch do
|
|
47
|
+
connection.create_join_table "artists", "musics"
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
assert_equal %w(artist_id music_id), connection.columns(:artists_musics).map(&:name).sort
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def test_create_join_table_with_symbol_and_string
|
|
54
|
+
connection.ddl_batch do
|
|
55
|
+
connection.create_join_table :artists, "musics"
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
assert_equal %w(artist_id music_id), connection.columns(:artists_musics).map(&:name).sort
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def test_create_join_table_with_the_proper_order
|
|
62
|
+
connection.ddl_batch do
|
|
63
|
+
connection.create_join_table :videos, :musics
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
assert_equal %w(music_id video_id), connection.columns(:musics_videos).map(&:name).sort
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def test_create_join_table_with_the_table_name
|
|
70
|
+
connection.ddl_batch do
|
|
71
|
+
connection.create_join_table :artists, :musics, table_name: :catalog
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
assert_equal %w(artist_id music_id), connection.columns(:catalog).map(&:name).sort
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def test_create_join_table_with_the_table_name_as_string
|
|
78
|
+
connection.ddl_batch do
|
|
79
|
+
connection.create_join_table :artists, :musics, table_name: "catalog"
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
assert_equal %w(artist_id music_id), connection.columns(:catalog).map(&:name).sort
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def test_create_join_table_with_column_options
|
|
86
|
+
connection.ddl_batch do
|
|
87
|
+
connection.create_join_table :artists, :musics, column_options: { null: true }
|
|
88
|
+
end
|
|
89
|
+
|
|
90
|
+
assert_equal [true, true], connection.columns(:artists_musics).map(&:null)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def test_create_join_table_without_indexes
|
|
94
|
+
connection.ddl_batch do
|
|
95
|
+
connection.create_join_table :artists, :musics
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
assert_predicate connection.indexes(:artists_musics), :blank?
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
def test_create_join_table_with_index
|
|
102
|
+
connection.ddl_batch do
|
|
103
|
+
connection.create_join_table :artists, :musics do |t|
|
|
104
|
+
t.index [:artist_id, :music_id]
|
|
105
|
+
end
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
assert_equal [%w(artist_id music_id)], connection.indexes(:artists_musics).map(&:columns)
|
|
109
|
+
end
|
|
110
|
+
|
|
111
|
+
def test_create_join_table_respects_reference_key_type
|
|
112
|
+
connection.ddl_batch do
|
|
113
|
+
connection.create_join_table :artists, :musics do |t|
|
|
114
|
+
t.references :video
|
|
115
|
+
end
|
|
116
|
+
end
|
|
117
|
+
|
|
118
|
+
artist_id, music_id, video_id = connection.columns(:artists_musics).sort_by(&:name)
|
|
119
|
+
|
|
120
|
+
assert_equal video_id.sql_type, artist_id.sql_type
|
|
121
|
+
assert_equal video_id.sql_type, music_id.sql_type
|
|
122
|
+
end
|
|
123
|
+
|
|
124
|
+
def test_drop_join_table
|
|
125
|
+
connection.ddl_batch do
|
|
126
|
+
connection.create_join_table :artists, :musics
|
|
127
|
+
end
|
|
128
|
+
connection.ddl_batch do
|
|
129
|
+
connection.drop_join_table :artists, :musics
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
assert_not connection.table_exists?("artists_musics")
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def test_drop_join_table_with_strings
|
|
136
|
+
connection.ddl_batch do
|
|
137
|
+
connection.create_join_table :artists, :musics
|
|
138
|
+
end
|
|
139
|
+
connection.ddl_batch do
|
|
140
|
+
connection.drop_join_table "artists", "musics"
|
|
141
|
+
end
|
|
142
|
+
|
|
143
|
+
assert_not connection.table_exists?("artists_musics")
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
def test_drop_join_table_with_the_proper_order
|
|
147
|
+
connection.ddl_batch do
|
|
148
|
+
connection.create_join_table :videos, :musics
|
|
149
|
+
end
|
|
150
|
+
connection.ddl_batch do
|
|
151
|
+
connection.drop_join_table :videos, :musics
|
|
152
|
+
end
|
|
153
|
+
|
|
154
|
+
assert_not connection.table_exists?("musics_videos")
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def test_drop_join_table_with_the_table_name
|
|
158
|
+
connection.ddl_batch do
|
|
159
|
+
connection.create_join_table :artists, :musics, table_name: :catalog
|
|
160
|
+
end
|
|
161
|
+
connection.ddl_batch do
|
|
162
|
+
connection.drop_join_table :artists, :musics, table_name: :catalog
|
|
163
|
+
end
|
|
164
|
+
|
|
165
|
+
assert_not connection.table_exists?("catalog")
|
|
166
|
+
end
|
|
167
|
+
|
|
168
|
+
def test_drop_join_table_with_the_table_name_as_string
|
|
169
|
+
connection.ddl_batch do
|
|
170
|
+
connection.create_join_table :artists, :musics, table_name: "catalog"
|
|
171
|
+
end
|
|
172
|
+
connection.ddl_batch do
|
|
173
|
+
connection.drop_join_table :artists, :musics, table_name: "catalog"
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
assert_not connection.table_exists?("catalog")
|
|
177
|
+
end
|
|
178
|
+
|
|
179
|
+
def test_drop_join_table_with_column_options
|
|
180
|
+
connection.ddl_batch do
|
|
181
|
+
connection.create_join_table :artists, :musics, column_options: { null: true }
|
|
182
|
+
end
|
|
183
|
+
connection.ddl_batch do
|
|
184
|
+
connection.drop_join_table :artists, :musics, column_options: { null: true }
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
assert_not connection.table_exists?("artists_musics")
|
|
188
|
+
end
|
|
189
|
+
|
|
190
|
+
def test_create_and_drop_join_table_with_common_prefix
|
|
191
|
+
with_table_cleanup do
|
|
192
|
+
connection.create_join_table "audio_artists", "audio_musics"
|
|
193
|
+
assert connection.table_exists?("audio_artists_musics")
|
|
194
|
+
|
|
195
|
+
connection.drop_join_table "audio_artists", "audio_musics"
|
|
196
|
+
assert_not connection.table_exists?("audio_artists_musics"), "Should have dropped join table, but didn't"
|
|
197
|
+
end
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
private
|
|
201
|
+
def with_table_cleanup
|
|
202
|
+
tables_before = connection.data_sources
|
|
203
|
+
|
|
204
|
+
yield
|
|
205
|
+
ensure
|
|
206
|
+
tables_after = connection.data_sources - tables_before
|
|
207
|
+
|
|
208
|
+
connection.ddl_batch do
|
|
209
|
+
tables_after.each do |table|
|
|
210
|
+
connection.drop_table table
|
|
211
|
+
end
|
|
212
|
+
end
|
|
213
|
+
end
|
|
214
|
+
end
|
|
215
|
+
end
|
|
216
|
+
end
|
|
@@ -0,0 +1,80 @@
|
|
|
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 DDLBatchingTest < SpannerAdapter::TestCase
|
|
14
|
+
include SpannerAdapter::Migration::TestHelper
|
|
15
|
+
include ActiveSupport::Testing::Stream
|
|
16
|
+
|
|
17
|
+
class Box < ActiveRecord::Base
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class CreateBoxMigration < ActiveRecord::Migration::Current
|
|
21
|
+
def change
|
|
22
|
+
connection.ddl_batch do
|
|
23
|
+
create_table("boxes") do |t|
|
|
24
|
+
t.string :name
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
add_column :boxes, :length, :integer
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
Box.create(name: "Box1", length: 10)
|
|
31
|
+
end
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def setup
|
|
35
|
+
skip_test_table_create!
|
|
36
|
+
|
|
37
|
+
super
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def teardown
|
|
41
|
+
super
|
|
42
|
+
|
|
43
|
+
connection.ddl_batch do
|
|
44
|
+
[:boxes, :ddl_batch_test].each do |name|
|
|
45
|
+
if connection.table_exists?(name)
|
|
46
|
+
connection.drop_table name
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def test_ddl_batching
|
|
53
|
+
information_schema = connection.send :information_schema
|
|
54
|
+
|
|
55
|
+
connection.ddl_batch do
|
|
56
|
+
connection.create_table("ddl_batch_test") do |t|
|
|
57
|
+
t.string :name
|
|
58
|
+
end
|
|
59
|
+
connection.add_column :ddl_batch_test, :created_at, :time
|
|
60
|
+
|
|
61
|
+
assert_not information_schema.table(:ddl_batch_test)
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
assert information_schema.table(:ddl_batch_test)
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def test_ddl_batching_with_dml_statement
|
|
68
|
+
migration = CreateBoxMigration.new
|
|
69
|
+
silence_stream($stdout) { migration.migrate(:up) }
|
|
70
|
+
|
|
71
|
+
assert connection.table_exists?(:boxes)
|
|
72
|
+
assert connection.column_exists?(:boxes, :length, :integer)
|
|
73
|
+
|
|
74
|
+
assert_equal 1, Box.count
|
|
75
|
+
box = Box.first
|
|
76
|
+
assert_equal 10, box.length
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
80
|
+
end
|
|
@@ -0,0 +1,297 @@
|
|
|
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 ForeignKeyTest < SpannerAdapter::TestCase
|
|
14
|
+
include SpannerAdapter::Migration::TestHelper
|
|
15
|
+
include ActiveSupport::Testing::Stream
|
|
16
|
+
|
|
17
|
+
class Rocket < ActiveRecord::Base
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
class Astronaut < ActiveRecord::Base
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
def setup
|
|
24
|
+
skip_test_table_create!
|
|
25
|
+
super
|
|
26
|
+
|
|
27
|
+
connection.ddl_batch do
|
|
28
|
+
connection.create_table "rockets", force: true do |t|
|
|
29
|
+
t.string :name
|
|
30
|
+
end
|
|
31
|
+
|
|
32
|
+
connection.create_table "astronauts", force: true do |t|
|
|
33
|
+
t.string :name
|
|
34
|
+
t.references :rocket
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
|
|
39
|
+
def teardown
|
|
40
|
+
connection.ddl_batch do
|
|
41
|
+
connection.drop_table "astronauts", if_exists: true
|
|
42
|
+
connection.drop_table "rockets", if_exists: true
|
|
43
|
+
connection.drop_table "fk_test_has_fk", if_exists: true
|
|
44
|
+
connection.drop_table "fk_test_has_pk", if_exists: true
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def test_foreign_keys
|
|
49
|
+
connection.ddl_batch do
|
|
50
|
+
connection.create_table :fk_test_has_pk, primary_key: "pk_id", force: :cascade do |t|
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
connection.create_table :fk_test_has_fk, force: true do |t|
|
|
54
|
+
t.references :fk, null: false
|
|
55
|
+
t.foreign_key :fk_test_has_pk, column: "fk_id", name: "fk_name", primary_key: "pk_id"
|
|
56
|
+
end
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
foreign_keys = connection.foreign_keys("fk_test_has_fk")
|
|
60
|
+
assert_equal 1, foreign_keys.size
|
|
61
|
+
|
|
62
|
+
fk = foreign_keys.first
|
|
63
|
+
assert_equal "fk_test_has_fk", fk.from_table
|
|
64
|
+
assert_equal "fk_test_has_pk", fk.to_table
|
|
65
|
+
assert_equal "fk_id", fk.column
|
|
66
|
+
assert_equal "pk_id", fk.primary_key
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def test_add_foreign_key_inferes_column
|
|
70
|
+
connection.ddl_batch do
|
|
71
|
+
connection.add_foreign_key :astronauts, :rockets
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
foreign_keys = connection.foreign_keys("astronauts")
|
|
75
|
+
assert_equal 1, foreign_keys.size
|
|
76
|
+
|
|
77
|
+
fk = foreign_keys.first
|
|
78
|
+
assert_equal "astronauts", fk.from_table
|
|
79
|
+
assert_equal "rockets", fk.to_table
|
|
80
|
+
assert_equal "rocket_id", fk.column
|
|
81
|
+
assert_equal "id", fk.primary_key
|
|
82
|
+
end
|
|
83
|
+
|
|
84
|
+
def test_add_foreign_key_with_column
|
|
85
|
+
connection.ddl_batch do
|
|
86
|
+
connection.add_foreign_key :astronauts, :rockets, column: "rocket_id"
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
foreign_keys = connection.foreign_keys("astronauts")
|
|
90
|
+
assert_equal 1, foreign_keys.size
|
|
91
|
+
|
|
92
|
+
fk = foreign_keys.first
|
|
93
|
+
assert_equal "astronauts", fk.from_table
|
|
94
|
+
assert_equal "rockets", fk.to_table
|
|
95
|
+
assert_equal "rocket_id", fk.column
|
|
96
|
+
assert_equal "id", fk.primary_key
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
def test_add_foreign_key_with_non_standard_primary_key
|
|
100
|
+
connection.ddl_batch do
|
|
101
|
+
connection.create_table :space_shuttles, id: false, force: true do |t|
|
|
102
|
+
t.integer :pk, primary_key: true
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
connection.add_foreign_key(:astronauts, :space_shuttles,
|
|
106
|
+
column: "rocket_id", primary_key: "pk", name: "custom_pk")
|
|
107
|
+
end
|
|
108
|
+
|
|
109
|
+
foreign_keys = connection.foreign_keys("astronauts")
|
|
110
|
+
assert_equal 1, foreign_keys.size
|
|
111
|
+
|
|
112
|
+
fk = foreign_keys.first
|
|
113
|
+
assert_equal "astronauts", fk.from_table
|
|
114
|
+
assert_equal "space_shuttles", fk.to_table
|
|
115
|
+
assert_equal "pk", fk.primary_key
|
|
116
|
+
ensure
|
|
117
|
+
connection.ddl_batch do
|
|
118
|
+
connection.remove_foreign_key :astronauts, name: "custom_pk", to_table: "space_shuttles"
|
|
119
|
+
connection.drop_table :space_shuttles
|
|
120
|
+
end
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def test_foreign_key_exists
|
|
124
|
+
connection.ddl_batch do
|
|
125
|
+
connection.add_foreign_key :astronauts, :rockets
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
assert connection.foreign_key_exists?(:astronauts, :rockets)
|
|
129
|
+
assert_not connection.foreign_key_exists?(:astronauts, :stars)
|
|
130
|
+
end
|
|
131
|
+
|
|
132
|
+
def test_foreign_key_exists_by_column
|
|
133
|
+
connection.ddl_batch do
|
|
134
|
+
connection.add_foreign_key :astronauts, :rockets, column: "rocket_id"
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
assert connection.foreign_key_exists?(:astronauts, column: "rocket_id")
|
|
138
|
+
assert_not connection.foreign_key_exists?(:astronauts, column: "star_id")
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def test_foreign_key_exists_by_name
|
|
142
|
+
connection.ddl_batch do
|
|
143
|
+
connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", name: "fancy_named_fk"
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
assert connection.foreign_key_exists?(:astronauts, name: "fancy_named_fk")
|
|
147
|
+
assert_not connection.foreign_key_exists?(:astronauts, name: "other_fancy_named_fk")
|
|
148
|
+
end
|
|
149
|
+
|
|
150
|
+
def test_foreign_key_exists_in_change_table
|
|
151
|
+
connection.change_table(:astronauts) do |t|
|
|
152
|
+
t.foreign_key :rockets, column: "rocket_id", name: "fancy_named_fk"
|
|
153
|
+
|
|
154
|
+
assert t.foreign_key_exists?(column: "rocket_id")
|
|
155
|
+
assert_not t.foreign_key_exists?(column: "star_id")
|
|
156
|
+
end
|
|
157
|
+
end
|
|
158
|
+
|
|
159
|
+
def test_remove_foreign_key_inferes_column
|
|
160
|
+
connection.ddl_batch do
|
|
161
|
+
connection.add_foreign_key :astronauts, :rockets
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
assert_equal 1, connection.foreign_keys("astronauts").size
|
|
165
|
+
connection.ddl_batch do
|
|
166
|
+
@connection.remove_foreign_key :astronauts, :rockets
|
|
167
|
+
end
|
|
168
|
+
assert_equal [], connection.foreign_keys("astronauts")
|
|
169
|
+
end
|
|
170
|
+
|
|
171
|
+
def test_remove_foreign_key_by_column
|
|
172
|
+
connection.ddl_batch do
|
|
173
|
+
connection.add_foreign_key :astronauts, :rockets, column: "rocket_id"
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
assert_equal 1, connection.foreign_keys("astronauts").size
|
|
177
|
+
connection.ddl_batch do
|
|
178
|
+
@connection.remove_foreign_key :astronauts, column: "rocket_id"
|
|
179
|
+
end
|
|
180
|
+
assert_equal [], connection.foreign_keys("astronauts")
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def test_remove_foreign_key_by_symbol_column
|
|
184
|
+
connection.ddl_batch do
|
|
185
|
+
connection.add_foreign_key :astronauts, :rockets, column: :rocket_id
|
|
186
|
+
end
|
|
187
|
+
|
|
188
|
+
assert_equal 1, connection.foreign_keys("astronauts").size
|
|
189
|
+
connection.ddl_batch do
|
|
190
|
+
connection.remove_foreign_key :astronauts, column: :rocket_id
|
|
191
|
+
end
|
|
192
|
+
assert_equal [], connection.foreign_keys("astronauts")
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
def test_remove_foreign_key_by_name
|
|
196
|
+
connection.ddl_batch do
|
|
197
|
+
connection.add_foreign_key :astronauts, :rockets, column: "rocket_id", name: "fancy_named_fk"
|
|
198
|
+
end
|
|
199
|
+
|
|
200
|
+
assert_equal 1, connection.foreign_keys("astronauts").size
|
|
201
|
+
connection.ddl_batch do
|
|
202
|
+
connection.remove_foreign_key :astronauts, name: "fancy_named_fk"
|
|
203
|
+
end
|
|
204
|
+
assert_equal [], connection.foreign_keys("astronauts")
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def test_remove_foreign_non_existing_foreign_key_raises
|
|
208
|
+
e = assert_raises ArgumentError do
|
|
209
|
+
connection.remove_foreign_key :astronauts, :rockets
|
|
210
|
+
end
|
|
211
|
+
assert_equal "Table 'astronauts' has no foreign key for rockets", e.message
|
|
212
|
+
end
|
|
213
|
+
|
|
214
|
+
def test_remove_foreign_key_by_the_select_one_on_the_same_table
|
|
215
|
+
connection.ddl_batch do
|
|
216
|
+
connection.add_foreign_key :astronauts, :rockets
|
|
217
|
+
connection.add_reference :astronauts, :myrocket, foreign_key: { to_table: :rockets }
|
|
218
|
+
end
|
|
219
|
+
|
|
220
|
+
assert_equal 2, connection.foreign_keys("astronauts").size
|
|
221
|
+
|
|
222
|
+
connection.ddl_batch do
|
|
223
|
+
connection.remove_foreign_key :astronauts, :rockets, column: "myrocket_id"
|
|
224
|
+
end
|
|
225
|
+
|
|
226
|
+
assert_equal [["astronauts", "rockets", "rocket_id"]],
|
|
227
|
+
connection.foreign_keys("astronauts").map { |fk| [fk.from_table, fk.to_table, fk.column] }
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
class CreateCitiesAndHousesMigration < ActiveRecord::Migration::Current
|
|
231
|
+
def change
|
|
232
|
+
connection.ddl_batch do
|
|
233
|
+
create_table("cities") { |t| }
|
|
234
|
+
|
|
235
|
+
create_table("houses") do |t|
|
|
236
|
+
t.references :city
|
|
237
|
+
end
|
|
238
|
+
add_foreign_key :houses, :cities, column: "city_id"
|
|
239
|
+
end
|
|
240
|
+
|
|
241
|
+
# remove and re-add to test that schema is updated and not accidentally cached
|
|
242
|
+
remove_foreign_key :houses, :cities
|
|
243
|
+
add_foreign_key :houses, :cities, column: "city_id"
|
|
244
|
+
end
|
|
245
|
+
end
|
|
246
|
+
|
|
247
|
+
def test_add_foreign_key_is_reversible
|
|
248
|
+
migration = CreateCitiesAndHousesMigration.new
|
|
249
|
+
silence_stream($stdout) { migration.migrate(:up) }
|
|
250
|
+
assert_equal 1, connection.foreign_keys("houses").size
|
|
251
|
+
ensure
|
|
252
|
+
silence_stream($stdout) { migration.migrate(:down) }
|
|
253
|
+
end
|
|
254
|
+
|
|
255
|
+
class CreateSchoolsAndClassesMigration < ActiveRecord::Migration::Current
|
|
256
|
+
def up
|
|
257
|
+
connection.ddl_batch do
|
|
258
|
+
create_table(:schools)
|
|
259
|
+
|
|
260
|
+
create_table(:classes) do |t|
|
|
261
|
+
t.references :school
|
|
262
|
+
end
|
|
263
|
+
add_foreign_key :classes, :schools
|
|
264
|
+
end
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def down
|
|
268
|
+
connection.ddl_batch do
|
|
269
|
+
drop_table :classes, if_exists: true
|
|
270
|
+
drop_table :schools, if_exists: true
|
|
271
|
+
end
|
|
272
|
+
end
|
|
273
|
+
end
|
|
274
|
+
|
|
275
|
+
def test_add_foreign_key_with_prefix
|
|
276
|
+
ActiveRecord::Base.table_name_prefix = "p_"
|
|
277
|
+
migration = CreateSchoolsAndClassesMigration.new
|
|
278
|
+
silence_stream($stdout) { migration.migrate(:up) }
|
|
279
|
+
assert_equal 1, connection.foreign_keys("p_classes").size
|
|
280
|
+
ensure
|
|
281
|
+
silence_stream($stdout) { migration.migrate(:down) }
|
|
282
|
+
ActiveRecord::Base.table_name_prefix = nil
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
def test_add_foreign_key_with_suffix
|
|
286
|
+
ActiveRecord::Base.table_name_suffix = "_s"
|
|
287
|
+
migration = CreateSchoolsAndClassesMigration.new
|
|
288
|
+
silence_stream($stdout) { migration.migrate(:up) }
|
|
289
|
+
assert_equal 1, connection.foreign_keys("classes_s").size
|
|
290
|
+
ensure
|
|
291
|
+
silence_stream($stdout) { migration.migrate(:down) }
|
|
292
|
+
ActiveRecord::Base.table_name_suffix = nil
|
|
293
|
+
end
|
|
294
|
+
end
|
|
295
|
+
end
|
|
296
|
+
end
|
|
297
|
+
|