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.
Files changed (264) hide show
  1. checksums.yaml +5 -5
  2. data/.github/CODEOWNERS +7 -0
  3. data/.github/sync-repo-settings.yaml +16 -0
  4. data/.github/workflows/acceptance-tests-on-emulator.yaml +45 -0
  5. data/.github/workflows/acceptance-tests-on-production.yaml +36 -0
  6. data/.github/workflows/ci.yaml +33 -0
  7. data/.github/workflows/nightly-acceptance-tests-on-emulator.yaml +52 -0
  8. data/.github/workflows/nightly-acceptance-tests-on-production.yaml +35 -0
  9. data/.github/workflows/nightly-unit-tests.yaml +40 -0
  10. data/.github/workflows/release-please-label.yml +25 -0
  11. data/.github/workflows/release-please.yml +39 -0
  12. data/.github/workflows/rubocop.yaml +31 -0
  13. data/.gitignore +67 -5
  14. data/.kokoro/populate-secrets.sh +77 -0
  15. data/.kokoro/release.cfg +33 -0
  16. data/.kokoro/release.sh +15 -0
  17. data/.kokoro/trampoline_v2.sh +489 -0
  18. data/.rubocop.yml +46 -0
  19. data/.toys/release.rb +18 -0
  20. data/.trampolinerc +48 -0
  21. data/.yardopts +11 -0
  22. data/CHANGELOG.md +26 -0
  23. data/CODE_OF_CONDUCT.md +40 -0
  24. data/CONTRIBUTING.md +79 -0
  25. data/Gemfile +9 -4
  26. data/LICENSE +6 -6
  27. data/README.md +67 -30
  28. data/Rakefile +79 -3
  29. data/SECURITY.md +7 -0
  30. data/acceptance/cases/associations/has_many_associations_test.rb +119 -0
  31. data/acceptance/cases/associations/has_many_through_associations_test.rb +63 -0
  32. data/acceptance/cases/associations/has_one_associations_test.rb +79 -0
  33. data/acceptance/cases/associations/has_one_through_associations_test.rb +98 -0
  34. data/acceptance/cases/interleaved_associations/has_many_associations_using_interleaved_test.rb +211 -0
  35. data/acceptance/cases/migration/change_schema_test.rb +433 -0
  36. data/acceptance/cases/migration/change_table_test.rb +115 -0
  37. data/acceptance/cases/migration/column_attributes_test.rb +122 -0
  38. data/acceptance/cases/migration/column_positioning_test.rb +48 -0
  39. data/acceptance/cases/migration/columns_test.rb +201 -0
  40. data/acceptance/cases/migration/command_recorder_test.rb +406 -0
  41. data/acceptance/cases/migration/create_join_table_test.rb +216 -0
  42. data/acceptance/cases/migration/ddl_batching_test.rb +80 -0
  43. data/acceptance/cases/migration/foreign_key_test.rb +297 -0
  44. data/acceptance/cases/migration/index_test.rb +211 -0
  45. data/acceptance/cases/migration/references_foreign_key_test.rb +259 -0
  46. data/acceptance/cases/migration/references_index_test.rb +135 -0
  47. data/acceptance/cases/migration/references_statements_test.rb +166 -0
  48. data/acceptance/cases/migration/rename_column_test.rb +96 -0
  49. data/acceptance/cases/models/calculation_query_test.rb +128 -0
  50. data/acceptance/cases/models/generated_column_test.rb +126 -0
  51. data/acceptance/cases/models/mutation_test.rb +122 -0
  52. data/acceptance/cases/models/query_test.rb +147 -0
  53. data/acceptance/cases/sessions/session_not_found_test.rb +121 -0
  54. data/acceptance/cases/transactions/optimistic_locking_test.rb +141 -0
  55. data/acceptance/cases/transactions/read_only_transactions_test.rb +67 -0
  56. data/acceptance/cases/transactions/read_write_transactions_test.rb +248 -0
  57. data/acceptance/cases/type/all_types_test.rb +152 -0
  58. data/acceptance/cases/type/binary_test.rb +59 -0
  59. data/acceptance/cases/type/boolean_test.rb +31 -0
  60. data/acceptance/cases/type/date_test.rb +32 -0
  61. data/acceptance/cases/type/date_time_test.rb +30 -0
  62. data/acceptance/cases/type/float_test.rb +27 -0
  63. data/acceptance/cases/type/integer_test.rb +44 -0
  64. data/acceptance/cases/type/numeric_test.rb +27 -0
  65. data/acceptance/cases/type/string_test.rb +79 -0
  66. data/acceptance/cases/type/text_test.rb +30 -0
  67. data/acceptance/cases/type/time_test.rb +87 -0
  68. data/acceptance/models/account.rb +13 -0
  69. data/acceptance/models/address.rb +9 -0
  70. data/acceptance/models/album.rb +12 -0
  71. data/acceptance/models/all_types.rb +8 -0
  72. data/acceptance/models/author.rb +11 -0
  73. data/acceptance/models/club.rb +12 -0
  74. data/acceptance/models/comment.rb +9 -0
  75. data/acceptance/models/customer.rb +9 -0
  76. data/acceptance/models/department.rb +9 -0
  77. data/acceptance/models/firm.rb +10 -0
  78. data/acceptance/models/member.rb +13 -0
  79. data/acceptance/models/member_type.rb +9 -0
  80. data/acceptance/models/membership.rb +10 -0
  81. data/acceptance/models/organization.rb +9 -0
  82. data/acceptance/models/post.rb +10 -0
  83. data/acceptance/models/singer.rb +10 -0
  84. data/acceptance/models/track.rb +20 -0
  85. data/acceptance/models/transaction.rb +9 -0
  86. data/acceptance/schema/schema.rb +143 -0
  87. data/acceptance/test_helper.rb +260 -0
  88. data/activerecord-spanner-adapter.gemspec +32 -17
  89. data/assets/solidus-db.png +0 -0
  90. data/benchmarks/README.md +17 -0
  91. data/benchmarks/Rakefile +14 -0
  92. data/benchmarks/application.rb +308 -0
  93. data/benchmarks/config/database.yml +8 -0
  94. data/benchmarks/config/environment.rb +12 -0
  95. data/benchmarks/db/migrate/01_create_tables.rb +25 -0
  96. data/benchmarks/db/schema.rb +29 -0
  97. data/benchmarks/models/album.rb +9 -0
  98. data/benchmarks/models/singer.rb +9 -0
  99. data/bin/console +6 -7
  100. data/examples/rails/README.md +262 -0
  101. data/examples/snippets/README.md +29 -0
  102. data/examples/snippets/Rakefile +57 -0
  103. data/examples/snippets/array-data-type/README.md +45 -0
  104. data/examples/snippets/array-data-type/Rakefile +13 -0
  105. data/examples/snippets/array-data-type/application.rb +45 -0
  106. data/examples/snippets/array-data-type/config/database.yml +8 -0
  107. data/examples/snippets/array-data-type/db/migrate/01_create_tables.rb +24 -0
  108. data/examples/snippets/array-data-type/db/schema.rb +26 -0
  109. data/examples/snippets/array-data-type/db/seeds.rb +5 -0
  110. data/examples/snippets/array-data-type/models/entity_with_array_types.rb +18 -0
  111. data/examples/snippets/bin/create_emulator_instance.rb +18 -0
  112. data/examples/snippets/bulk-insert/README.md +21 -0
  113. data/examples/snippets/bulk-insert/Rakefile +13 -0
  114. data/examples/snippets/bulk-insert/application.rb +64 -0
  115. data/examples/snippets/bulk-insert/config/database.yml +8 -0
  116. data/examples/snippets/bulk-insert/db/migrate/01_create_tables.rb +21 -0
  117. data/examples/snippets/bulk-insert/db/schema.rb +26 -0
  118. data/examples/snippets/bulk-insert/db/seeds.rb +5 -0
  119. data/examples/snippets/bulk-insert/models/album.rb +9 -0
  120. data/examples/snippets/bulk-insert/models/singer.rb +9 -0
  121. data/examples/snippets/commit-timestamp/README.md +18 -0
  122. data/examples/snippets/commit-timestamp/Rakefile +13 -0
  123. data/examples/snippets/commit-timestamp/application.rb +53 -0
  124. data/examples/snippets/commit-timestamp/config/database.yml +8 -0
  125. data/examples/snippets/commit-timestamp/db/migrate/01_create_tables.rb +26 -0
  126. data/examples/snippets/commit-timestamp/db/schema.rb +29 -0
  127. data/examples/snippets/commit-timestamp/db/seeds.rb +5 -0
  128. data/examples/snippets/commit-timestamp/models/album.rb +9 -0
  129. data/examples/snippets/commit-timestamp/models/singer.rb +9 -0
  130. data/examples/snippets/config/environment.rb +21 -0
  131. data/examples/snippets/create-records/README.md +12 -0
  132. data/examples/snippets/create-records/Rakefile +13 -0
  133. data/examples/snippets/create-records/application.rb +42 -0
  134. data/examples/snippets/create-records/config/database.yml +8 -0
  135. data/examples/snippets/create-records/db/migrate/01_create_tables.rb +21 -0
  136. data/examples/snippets/create-records/db/schema.rb +26 -0
  137. data/examples/snippets/create-records/db/seeds.rb +5 -0
  138. data/examples/snippets/create-records/models/album.rb +9 -0
  139. data/examples/snippets/create-records/models/singer.rb +9 -0
  140. data/examples/snippets/date-data-type/README.md +19 -0
  141. data/examples/snippets/date-data-type/Rakefile +13 -0
  142. data/examples/snippets/date-data-type/application.rb +35 -0
  143. data/examples/snippets/date-data-type/config/database.yml +8 -0
  144. data/examples/snippets/date-data-type/db/migrate/01_create_tables.rb +20 -0
  145. data/examples/snippets/date-data-type/db/schema.rb +21 -0
  146. data/examples/snippets/date-data-type/db/seeds.rb +16 -0
  147. data/examples/snippets/date-data-type/models/singer.rb +8 -0
  148. data/examples/snippets/generated-column/README.md +41 -0
  149. data/examples/snippets/generated-column/Rakefile +13 -0
  150. data/examples/snippets/generated-column/application.rb +37 -0
  151. data/examples/snippets/generated-column/config/database.yml +8 -0
  152. data/examples/snippets/generated-column/db/migrate/01_create_tables.rb +23 -0
  153. data/examples/snippets/generated-column/db/schema.rb +21 -0
  154. data/examples/snippets/generated-column/db/seeds.rb +18 -0
  155. data/examples/snippets/generated-column/models/singer.rb +8 -0
  156. data/examples/snippets/interleaved-tables/README.md +152 -0
  157. data/examples/snippets/interleaved-tables/Rakefile +13 -0
  158. data/examples/snippets/interleaved-tables/application.rb +109 -0
  159. data/examples/snippets/interleaved-tables/config/database.yml +8 -0
  160. data/examples/snippets/interleaved-tables/db/migrate/01_create_tables.rb +44 -0
  161. data/examples/snippets/interleaved-tables/db/schema.rb +32 -0
  162. data/examples/snippets/interleaved-tables/db/seeds.rb +40 -0
  163. data/examples/snippets/interleaved-tables/models/album.rb +15 -0
  164. data/examples/snippets/interleaved-tables/models/singer.rb +20 -0
  165. data/examples/snippets/interleaved-tables/models/track.rb +25 -0
  166. data/examples/snippets/migrations/README.md +43 -0
  167. data/examples/snippets/migrations/Rakefile +13 -0
  168. data/examples/snippets/migrations/application.rb +26 -0
  169. data/examples/snippets/migrations/config/database.yml +8 -0
  170. data/examples/snippets/migrations/db/migrate/01_create_tables.rb +28 -0
  171. data/examples/snippets/migrations/db/schema.rb +33 -0
  172. data/examples/snippets/migrations/db/seeds.rb +5 -0
  173. data/examples/snippets/migrations/models/album.rb +10 -0
  174. data/examples/snippets/migrations/models/singer.rb +10 -0
  175. data/examples/snippets/migrations/models/track.rb +9 -0
  176. data/examples/snippets/mutations/README.md +34 -0
  177. data/examples/snippets/mutations/Rakefile +13 -0
  178. data/examples/snippets/mutations/application.rb +47 -0
  179. data/examples/snippets/mutations/config/database.yml +8 -0
  180. data/examples/snippets/mutations/db/migrate/01_create_tables.rb +22 -0
  181. data/examples/snippets/mutations/db/schema.rb +27 -0
  182. data/examples/snippets/mutations/db/seeds.rb +25 -0
  183. data/examples/snippets/mutations/models/album.rb +9 -0
  184. data/examples/snippets/mutations/models/singer.rb +9 -0
  185. data/examples/snippets/optimistic-locking/README.md +12 -0
  186. data/examples/snippets/optimistic-locking/Rakefile +13 -0
  187. data/examples/snippets/optimistic-locking/application.rb +48 -0
  188. data/examples/snippets/optimistic-locking/config/database.yml +8 -0
  189. data/examples/snippets/optimistic-locking/db/migrate/01_create_tables.rb +26 -0
  190. data/examples/snippets/optimistic-locking/db/schema.rb +29 -0
  191. data/examples/snippets/optimistic-locking/db/seeds.rb +25 -0
  192. data/examples/snippets/optimistic-locking/models/album.rb +9 -0
  193. data/examples/snippets/optimistic-locking/models/singer.rb +9 -0
  194. data/examples/snippets/quickstart/README.md +26 -0
  195. data/examples/snippets/quickstart/Rakefile +13 -0
  196. data/examples/snippets/quickstart/application.rb +51 -0
  197. data/examples/snippets/quickstart/config/database.yml +8 -0
  198. data/examples/snippets/quickstart/db/migrate/01_create_tables.rb +21 -0
  199. data/examples/snippets/quickstart/db/schema.rb +26 -0
  200. data/examples/snippets/quickstart/db/seeds.rb +24 -0
  201. data/examples/snippets/quickstart/models/album.rb +9 -0
  202. data/examples/snippets/quickstart/models/singer.rb +9 -0
  203. data/examples/snippets/read-only-transactions/README.md +13 -0
  204. data/examples/snippets/read-only-transactions/Rakefile +13 -0
  205. data/examples/snippets/read-only-transactions/application.rb +49 -0
  206. data/examples/snippets/read-only-transactions/config/database.yml +8 -0
  207. data/examples/snippets/read-only-transactions/db/migrate/01_create_tables.rb +21 -0
  208. data/examples/snippets/read-only-transactions/db/schema.rb +26 -0
  209. data/examples/snippets/read-only-transactions/db/seeds.rb +24 -0
  210. data/examples/snippets/read-only-transactions/models/album.rb +9 -0
  211. data/examples/snippets/read-only-transactions/models/singer.rb +9 -0
  212. data/examples/snippets/read-write-transactions/README.md +12 -0
  213. data/examples/snippets/read-write-transactions/Rakefile +13 -0
  214. data/examples/snippets/read-write-transactions/application.rb +39 -0
  215. data/examples/snippets/read-write-transactions/config/database.yml +8 -0
  216. data/examples/snippets/read-write-transactions/db/migrate/01_create_tables.rb +22 -0
  217. data/examples/snippets/read-write-transactions/db/schema.rb +27 -0
  218. data/examples/snippets/read-write-transactions/db/seeds.rb +25 -0
  219. data/examples/snippets/read-write-transactions/models/album.rb +9 -0
  220. data/examples/snippets/read-write-transactions/models/singer.rb +9 -0
  221. data/examples/snippets/timestamp-data-type/README.md +17 -0
  222. data/examples/snippets/timestamp-data-type/Rakefile +13 -0
  223. data/examples/snippets/timestamp-data-type/application.rb +42 -0
  224. data/examples/snippets/timestamp-data-type/config/database.yml +8 -0
  225. data/examples/snippets/timestamp-data-type/db/migrate/01_create_tables.rb +21 -0
  226. data/examples/snippets/timestamp-data-type/db/schema.rb +21 -0
  227. data/examples/snippets/timestamp-data-type/db/seeds.rb +6 -0
  228. data/examples/snippets/timestamp-data-type/models/meeting.rb +19 -0
  229. data/examples/solidus/README.md +172 -0
  230. data/lib/active_record/connection_adapters/spanner/database_statements.rb +224 -269
  231. data/lib/active_record/connection_adapters/spanner/quoting.rb +42 -50
  232. data/lib/active_record/connection_adapters/spanner/schema_cache.rb +43 -0
  233. data/lib/active_record/connection_adapters/spanner/schema_creation.rb +125 -9
  234. data/lib/active_record/connection_adapters/spanner/schema_definitions.rb +122 -0
  235. data/lib/active_record/connection_adapters/spanner/schema_dumper.rb +19 -0
  236. data/lib/active_record/connection_adapters/spanner/schema_statements.rb +553 -139
  237. data/lib/active_record/connection_adapters/spanner/type_metadata.rb +37 -0
  238. data/lib/active_record/connection_adapters/spanner_adapter.rb +182 -78
  239. data/lib/active_record/tasks/spanner_database_tasks.rb +74 -0
  240. data/lib/active_record/type/spanner/array.rb +32 -0
  241. data/lib/active_record/type/spanner/bytes.rb +26 -0
  242. data/lib/active_record/type/spanner/spanner_active_record_converter.rb +32 -0
  243. data/lib/active_record/type/spanner/time.rb +37 -0
  244. data/lib/activerecord-spanner-adapter.rb +23 -0
  245. data/lib/activerecord_spanner_adapter/base.rb +217 -0
  246. data/lib/activerecord_spanner_adapter/connection.rb +324 -0
  247. data/lib/activerecord_spanner_adapter/errors.rb +13 -0
  248. data/lib/activerecord_spanner_adapter/foreign_key.rb +29 -0
  249. data/lib/activerecord_spanner_adapter/index/column.rb +38 -0
  250. data/lib/activerecord_spanner_adapter/index.rb +80 -0
  251. data/lib/activerecord_spanner_adapter/information_schema.rb +261 -0
  252. data/lib/activerecord_spanner_adapter/primary_key.rb +31 -0
  253. data/lib/activerecord_spanner_adapter/table/column.rb +59 -0
  254. data/lib/activerecord_spanner_adapter/table.rb +61 -0
  255. data/lib/activerecord_spanner_adapter/transaction.rb +113 -0
  256. data/lib/activerecord_spanner_adapter/version.rb +9 -0
  257. data/lib/arel/visitors/spanner.rb +35 -0
  258. data/lib/spanner_client_ext.rb +82 -0
  259. data/renovate.json +5 -0
  260. metadata +387 -34
  261. data/.travis.yml +0 -5
  262. data/lib/active_record/connection_adapters/spanner/client.rb +0 -190
  263. data/lib/active_record/connection_adapters/spanner.rb +0 -10
  264. data/lib/activerecord-spanner-adapter/version.rb +0 -3
@@ -0,0 +1,259 @@
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 ReferencesForeignKeyInCreateTest < SpannerAdapter::TestCase
14
+ include SpannerAdapter::Migration::TestHelper
15
+
16
+ def setup
17
+ skip_test_table_create!
18
+ super
19
+ connection.ddl_batch do
20
+ @connection.create_table(:testing_parents, force: true)
21
+ end
22
+ end
23
+
24
+ def teardown
25
+ @connection.ddl_batch do
26
+ @connection.drop_table "testings", if_exists: true
27
+ @connection.drop_table "testing_parents", if_exists: true
28
+ end
29
+ end
30
+
31
+ def test_create_foreign_key_with_table_create
32
+ connection.ddl_batch do
33
+ connection.create_table :testings do |t|
34
+ t.references :testing_parent, foreign_key: true
35
+ end
36
+ end
37
+
38
+ fk = connection.foreign_keys("testings").first
39
+ assert_equal "testings", fk.from_table
40
+ assert_equal "testing_parents", fk.to_table
41
+ end
42
+
43
+ def test_create_foreign_key_created_by_default
44
+ connection.ddl_batch do
45
+ connection.create_table :testings do |t|
46
+ t.references :testing_parent
47
+ end
48
+ end
49
+
50
+ assert_equal [], @connection.foreign_keys("testings")
51
+ end
52
+
53
+ def test_options_can_be_passed
54
+ connection.ddl_batch do
55
+ connection.change_table :testing_parents do |t|
56
+ t.references :other, index: { unique: true }
57
+ end
58
+ connection.create_table :testings do |t|
59
+ t.references :testing_parent, foreign_key: { primary_key: :other_id }
60
+ end
61
+ end
62
+
63
+ fk = @connection.foreign_keys("testings").find { |k| k.to_table == "testing_parents" }
64
+ assert_equal "other_id", fk.primary_key
65
+ end
66
+
67
+ def test_to_table_options_can_be_passed
68
+ connection.ddl_batch do
69
+ @connection.create_table :testings do |t|
70
+ t.references :parent, foreign_key: { to_table: :testing_parents }
71
+ end
72
+ end
73
+ fks = @connection.foreign_keys("testings")
74
+ assert_equal([["testings", "testing_parents", "parent_id"]],
75
+ fks.map { |fk| [fk.from_table, fk.to_table, fk.column] })
76
+ end
77
+ end
78
+ end
79
+ end
80
+
81
+ module ActiveRecord
82
+ class Migration
83
+ class ReferencesForeignKeyTest < SpannerAdapter::TestCase
84
+ include SpannerAdapter::Migration::TestHelper
85
+ include ActiveSupport::Testing::Stream
86
+
87
+ def setup
88
+ skip_test_table_create!
89
+ super
90
+ connection = ActiveRecord::Base.connection
91
+ connection.ddl_batch do
92
+ connection.create_table(:testing_parents, force: true)
93
+ end
94
+ end
95
+
96
+ def teardown
97
+ connection.ddl_batch do
98
+ connection.drop_table "testings", if_exists: true
99
+ connection.drop_table "testing_parents", if_exists: true
100
+ end
101
+ end
102
+
103
+ def test_create_foreign_key_with_changing_table
104
+ connection.ddl_batch do
105
+ connection.create_table :testings
106
+ connection.change_table :testings do |t|
107
+ t.references :testing_parent, foreign_key: true
108
+ end
109
+ end
110
+
111
+ fk = connection.foreign_keys("testings").first
112
+ assert_equal "testings", fk.from_table
113
+ assert_equal "testing_parents", fk.to_table
114
+ end
115
+
116
+ def test_foreign_key_not_added_by_default_on_table_change
117
+ connection.create_table :testings
118
+ connection.change_table :testings do |t|
119
+ t.references :testing_parent
120
+ end
121
+
122
+ assert_equal [], connection.foreign_keys("testings")
123
+ end
124
+
125
+ def test_foreign_key_accept_option_on_table_change
126
+ connection.ddl_batch do
127
+ connection.change_table :testing_parents do |t|
128
+ t.references :other, index: { unique: true }
129
+ end
130
+ connection.create_table :testings
131
+ end
132
+ connection.change_table :testings do |t|
133
+ t.references :testing_parent, foreign_key: { primary_key: :other_id }
134
+ end
135
+
136
+ fk = connection.foreign_keys("testings").find { |k| k.to_table == "testing_parents" }
137
+ assert_equal "other_id", fk.primary_key
138
+ end
139
+
140
+ def test_foreign_key_column_can_be_removed
141
+ connection.ddl_batch do
142
+ connection.create_table :testings do |t|
143
+ t.references :testing_parent, index: true, foreign_key: true
144
+ end
145
+ end
146
+
147
+ connection.remove_reference :testings, :testing_parent, foreign_key: true
148
+ assert_equal 0, connection.foreign_keys('testings').size
149
+ end
150
+
151
+ def test_remove_column_removes_foreign_key
152
+ connection.ddl_batch do
153
+ connection.create_table :testings do |t|
154
+ t.references :testing_parent, index: true, foreign_key: true
155
+ end
156
+ end
157
+
158
+ connection.ddl_batch do
159
+ connection.remove_column :testings, :testing_parent_id
160
+ end
161
+ assert_equal 0, connection.foreign_keys('testings').size
162
+ end
163
+
164
+ def test_foreign_key_respect_pluralize_table_names
165
+ original_pluralize_table_names = ActiveRecord::Base.pluralize_table_names
166
+ ActiveRecord::Base.pluralize_table_names = false
167
+ connection.create_table :testing
168
+ connection.ddl_batch do
169
+ connection.change_table :testing_parents do |t|
170
+ t.references :testing, foreign_key: true
171
+ end
172
+ end
173
+
174
+ fk = connection.foreign_keys("testing_parents").first
175
+ assert_equal "testing_parents", fk.from_table
176
+ assert_equal "testing", fk.to_table
177
+
178
+ assert_difference "@connection.foreign_keys('testing_parents').size", -1 do
179
+ connection.remove_reference :testing_parents, :testing, foreign_key: true
180
+ end
181
+ ensure
182
+ ActiveRecord::Base.pluralize_table_names = original_pluralize_table_names
183
+ connection.ddl_batch do
184
+ connection.drop_table "testing", if_exists: true
185
+ end
186
+ end
187
+
188
+ class CreateDogsMigration < ActiveRecord::Migration::Current
189
+ def up
190
+ connection.ddl_batch do
191
+ create_table :dog_owners
192
+
193
+ create_table :dogs do |t|
194
+ t.references :dog_owner, foreign_key: true
195
+ end
196
+ end
197
+ end
198
+
199
+ def down
200
+ connection.ddl_batch do
201
+ drop_table :dogs, if_exists: true
202
+ drop_table :dog_owners, if_exists: true
203
+ end
204
+ end
205
+ end
206
+
207
+ def test_references_foreign_key_with_prefix
208
+ ActiveRecord::Base.table_name_prefix = "p_"
209
+ migration = CreateDogsMigration.new
210
+ silence_stream($stdout) { migration.migrate(:up) }
211
+ assert_equal 1, @connection.foreign_keys("p_dogs").size
212
+ ensure
213
+ silence_stream($stdout) { migration.migrate(:down) }
214
+ ActiveRecord::Base.table_name_prefix = nil
215
+ end
216
+
217
+ def test_references_foreign_key_with_suffix
218
+ ActiveRecord::Base.table_name_suffix = "_s"
219
+ migration = CreateDogsMigration.new
220
+ silence_stream($stdout) { migration.migrate(:up) }
221
+ assert_equal 1, @connection.foreign_keys("dogs_s").size
222
+ ensure
223
+ silence_stream($stdout) { migration.migrate(:down) }
224
+ ActiveRecord::Base.table_name_suffix = nil
225
+ end
226
+
227
+ def test_multiple_foreign_keys_can_added_to_same_table
228
+ connection.ddl_batch do
229
+ connection.create_table :testings do |t|
230
+ t.references :parent1, foreign_key: { to_table: :testing_parents }
231
+ t.references :parent2, foreign_key: { to_table: :testing_parents }
232
+ end
233
+ end
234
+
235
+ fks = connection.foreign_keys("testings").sort_by(&:column)
236
+
237
+ fk_definitions = fks.map { |fk| [fk.from_table, fk.to_table, fk.column] }
238
+ assert_equal([["testings", "testing_parents", "parent1_id"],
239
+ ["testings", "testing_parents", "parent2_id"]], fk_definitions)
240
+ end
241
+
242
+ def test_multiple_foreign_keys_removed
243
+ connection.create_table :testings do |t|
244
+ t.references :parent1, foreign_key: { to_table: :testing_parents }
245
+ t.references :parent2, foreign_key: { to_table: :testing_parents }
246
+ end
247
+
248
+ connection.remove_reference :testings, :parent1, foreign_key: { to_table: :testing_parents }
249
+
250
+ assert_equal 1, connection.foreign_keys('testings').size
251
+
252
+ fks = connection.foreign_keys("testings").sort_by(&:column)
253
+
254
+ fk_definitions = fks.map { |fk| [fk.from_table, fk.to_table, fk.column] }
255
+ assert_equal([["testings", "testing_parents", "parent2_id"]], fk_definitions)
256
+ end
257
+ end
258
+ end
259
+ end
@@ -0,0 +1,135 @@
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 ReferencesIndexTest < SpannerAdapter::TestCase
14
+ include SpannerAdapter::Migration::TestHelper
15
+
16
+ attr_reader :table_name
17
+
18
+ def setup
19
+ skip_test_table_create!
20
+ super
21
+
22
+ @table_name = :testings
23
+ end
24
+
25
+ def teardown
26
+ connection.ddl_batch do
27
+ connection.drop_table :testings
28
+ end rescue nil
29
+ end
30
+
31
+ def test_creates_index
32
+ connection.ddl_batch do
33
+ connection.create_table table_name do |t|
34
+ t.references :foo, index: true
35
+ end
36
+ end
37
+
38
+ assert connection.index_exists?(table_name, :foo_id, name: :index_testings_on_foo_id)
39
+ end
40
+
41
+ def test_creates_index_by_default_even_if_index_option_is_not_passed
42
+ connection.ddl_batch do
43
+ connection.create_table table_name do |t|
44
+ t.references :foo
45
+ end
46
+ end
47
+
48
+ assert connection.index_exists?(table_name, :foo_id, name: :index_testings_on_foo_id)
49
+ end
50
+
51
+ def test_does_not_create_index_explicit
52
+ connection.ddl_batch do
53
+ connection.create_table table_name do |t|
54
+ t.references :foo, index: false
55
+ end
56
+ end
57
+
58
+ assert_not connection.index_exists?(table_name, :foo_id, name: :index_testings_on_foo_id)
59
+ end
60
+
61
+ def test_creates_index_with_options
62
+ connection.ddl_batch do
63
+ connection.create_table table_name do |t|
64
+ t.references :foo, index: { name: :index_testings_on_yo_momma }
65
+ t.references :bar, index: { unique: true }
66
+ end
67
+ end
68
+
69
+ assert connection.index_exists?(table_name, :foo_id, name: :index_testings_on_yo_momma)
70
+ assert connection.index_exists?(table_name, :bar_id, name: :index_testings_on_bar_id, unique: true)
71
+ end
72
+
73
+ def test_creates_polymorphic_index
74
+ connection.ddl_batch do
75
+ connection.create_table table_name do |t|
76
+ t.references :foo, polymorphic: true, index: true
77
+ end
78
+ end
79
+
80
+ if ActiveRecord::gem_version < Gem::Version.create('6.1.0')
81
+ assert connection.index_exists?(table_name, [:foo_type, :foo_id], name: :index_testings_on_foo_type_and_foo_id)
82
+ else
83
+ assert connection.index_exists?(table_name, [:foo_type, :foo_id], name: :index_testings_on_foo)
84
+ end
85
+ end
86
+
87
+ def test_creates_index_for_existing_table
88
+ connection.ddl_batch do
89
+ connection.create_table table_name
90
+ connection.change_table table_name do |t|
91
+ t.references :foo, index: true
92
+ end
93
+ end
94
+
95
+ assert connection.index_exists?(table_name, :foo_id, name: :index_testings_on_foo_id)
96
+ end
97
+
98
+ def test_creates_index_for_existing_table_even_if_index_option_is_not_passed
99
+ connection.ddl_batch do
100
+ connection.create_table table_name
101
+ connection.change_table table_name do |t|
102
+ t.references :foo
103
+ end
104
+ end
105
+
106
+ assert connection.index_exists?(table_name, :foo_id, name: :index_testings_on_foo_id)
107
+ end
108
+
109
+ def test_does_not_create_index_for_existing_table_explicit
110
+ connection.ddl_batch do
111
+ connection.create_table table_name
112
+ connection.change_table table_name do |t|
113
+ t.references :foo, index: false
114
+ end
115
+ end
116
+ assert_not connection.index_exists?(table_name, :foo_id, name: :index_testings_on_foo)
117
+ end
118
+
119
+ def test_creates_polymorphic_index_for_existing_table
120
+ connection.ddl_batch do
121
+ connection.create_table table_name
122
+ connection.change_table table_name do |t|
123
+ t.references :foo, polymorphic: true, index: true
124
+ end
125
+ end
126
+
127
+ if ActiveRecord::gem_version < Gem::Version.create('6.1.0')
128
+ assert connection.index_exists?(table_name, [:foo_type, :foo_id], name: :index_testings_on_foo_type_and_foo_id)
129
+ else
130
+ assert connection.index_exists?(table_name, [:foo_type, :foo_id], name: :index_testings_on_foo)
131
+ end
132
+ end
133
+ end
134
+ end
135
+ end
@@ -0,0 +1,166 @@
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 ReferencesStatementsTest < SpannerAdapter::TestCase
14
+ include SpannerAdapter::Migration::TestHelper
15
+
16
+ attr_reader :table_name
17
+
18
+ def setup
19
+ super
20
+ @table_name = :test_models
21
+
22
+ connection.ddl_batch do
23
+ add_column table_name, :supplier_id, :integer, index: true
24
+ end
25
+ end
26
+
27
+ def test_creates_reference_id_column
28
+ connection.ddl_batch do
29
+ add_reference table_name, :user
30
+ end
31
+ assert column_exists?(table_name, :user_id, :integer)
32
+ end
33
+
34
+ def test_does_not_create_reference_type_column
35
+ connection.ddl_batch do
36
+ add_reference table_name, :taggable
37
+ end
38
+ assert_not column_exists?(table_name, :taggable_type, :string)
39
+ end
40
+
41
+ def test_creates_reference_type_column
42
+ connection.ddl_batch do
43
+ add_reference table_name, :taggable, polymorphic: true
44
+ end
45
+ assert column_exists?(table_name, :taggable_id, :integer)
46
+ assert column_exists?(table_name, :taggable_type, :string)
47
+ end
48
+
49
+ def test_does_not_create_reference_id_index_if_index_is_false
50
+ connection.ddl_batch do
51
+ add_reference table_name, :user, index: false
52
+ end
53
+ assert_not index_exists?(table_name, :user_id)
54
+ end
55
+
56
+ def test_create_reference_id_index_even_if_index_option_is_not_passed
57
+ connection.ddl_batch do
58
+ add_reference table_name, :user
59
+ end
60
+ assert index_exists?(table_name, :user_id)
61
+ end
62
+
63
+ def test_creates_polymorphic_index
64
+ connection.ddl_batch do
65
+ add_reference table_name, :taggable, polymorphic: true, index: true
66
+ end
67
+ assert index_exists?(table_name, [:taggable_type, :taggable_id])
68
+ end
69
+
70
+ def test_creates_reference_type_column_with_not_null
71
+ connection.ddl_batch do
72
+ connection.create_table table_name, force: true do |t|
73
+ t.references :taggable, null: false, polymorphic: true
74
+ end
75
+ end
76
+ assert column_exists?(table_name, :taggable_id, :integer, null: false)
77
+ assert column_exists?(table_name, :taggable_type, :string, null: false)
78
+ end
79
+
80
+ def test_creates_named_index
81
+ connection.ddl_batch do
82
+ add_reference table_name, :tag, index: { name: "index_taggings_on_tag_id" }
83
+ end
84
+ assert index_exists?(table_name, :tag_id, name: "index_taggings_on_tag_id")
85
+ end
86
+
87
+ def test_creates_named_unique_index
88
+ connection.ddl_batch do
89
+ add_reference table_name, :tag, index: { name: "index_taggings_on_tag_id", unique: true }
90
+ end
91
+ assert index_exists?(table_name, :tag_id, name: "index_taggings_on_tag_id", unique: true)
92
+ end
93
+
94
+ def test_creates_reference_id_with_specified_type
95
+ connection.ddl_batch do
96
+ add_reference table_name, :user, type: :string
97
+ end
98
+ assert column_exists?(table_name, :user_id, :string)
99
+ end
100
+
101
+ def test_deletes_reference_id_column
102
+ connection.ddl_batch do
103
+ remove_reference table_name, :supplier
104
+ end
105
+ assert_not column_exists?(table_name, :supplier_id, :string)
106
+ end
107
+
108
+ def test_deletes_reference_id_index
109
+ connection.ddl_batch do
110
+ remove_reference table_name, :supplier
111
+ end
112
+ assert_not index_exists?(table_name, :supplier_id)
113
+ end
114
+
115
+ def test_does_not_delete_reference_type_column
116
+ with_polymorphic_column do
117
+ connection.ddl_batch do
118
+ remove_reference table_name, :supplier
119
+ end
120
+
121
+ assert_not column_exists?(table_name, :supplier_id, :string)
122
+ assert column_exists?(table_name, :supplier_type, :string)
123
+ end
124
+ end
125
+
126
+ def test_deletes_reference_type_column
127
+ with_polymorphic_column do
128
+ remove_reference table_name, :supplier, polymorphic: true
129
+ assert_not column_exists?(table_name, :supplier_type, :string)
130
+ end
131
+ end
132
+
133
+ def test_deletes_polymorphic_index
134
+ with_polymorphic_column do
135
+ remove_reference table_name, :supplier, polymorphic: true
136
+ assert_not index_exists?(table_name, [:supplier_id, :supplier_type])
137
+ end
138
+ end
139
+
140
+ def test_add_belongs_to_alias
141
+ connection.ddl_batch do
142
+ add_belongs_to table_name, :user
143
+ end
144
+ assert column_exists?(table_name, :user_id, :integer)
145
+ end
146
+
147
+ def test_remove_belongs_to_alias
148
+ connection.ddl_batch do
149
+ remove_belongs_to table_name, :supplier
150
+ end
151
+ assert_not column_exists?(table_name, :supplier_id, :integer)
152
+ end
153
+
154
+ private
155
+
156
+ def with_polymorphic_column
157
+ connection.ddl_batch do
158
+ add_column table_name, :supplier_type, :string
159
+ add_index table_name, [:supplier_id, :supplier_type]
160
+ end
161
+
162
+ yield
163
+ end
164
+ end
165
+ end
166
+ end