activerecord-spanner-adapter 0.3.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
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