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,406 @@
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 CommandRecorderTest < SpannerAdapter::TestCase
14
+ include SpannerAdapter::Migration::TestHelper
15
+
16
+ VERSION_6_1_0 = Gem::Version.create "6.1.0"
17
+ VERSION_6_0_3 = Gem::Version.create "6.0.3"
18
+
19
+ def setup
20
+ skip_test_table_create!
21
+ super
22
+ @recorder = CommandRecorder.new(connection)
23
+ end
24
+
25
+ def test_respond_to_delegates
26
+ recorder = CommandRecorder.new(Class.new {
27
+ def america; end
28
+ }.new)
29
+ assert_respond_to recorder, :america
30
+ end
31
+
32
+ def test_send_calls_super
33
+ assert_raises(NoMethodError) do
34
+ @recorder.send(:non_existing_method, :horses)
35
+ end
36
+ end
37
+
38
+ def test_send_delegates_to_record
39
+ recorder = CommandRecorder.new(Class.new {
40
+ def create_table(name); end
41
+ }.new)
42
+ assert_respond_to recorder, :create_table
43
+ recorder.send(:create_table, :horses)
44
+ assert_equal [[:create_table, [:horses], nil]], recorder.commands
45
+ end
46
+
47
+ def test_unknown_commands_delegate
48
+ recorder = Class.new do
49
+ def foo(kw:)
50
+ kw
51
+ end
52
+ end
53
+ recorder = CommandRecorder.new(recorder.new)
54
+ assert_equal "bar", recorder.foo(kw: "bar")
55
+ end
56
+
57
+ def test_inverse_of_raise_exception_on_unknown_commands
58
+ assert_raises(ActiveRecord::IrreversibleMigration) do
59
+ @recorder.inverse_of :execute, ["some sql"]
60
+ end
61
+ end
62
+
63
+ def test_irreversible_commands_raise_exception
64
+ assert_raises(ActiveRecord::IrreversibleMigration) do
65
+ @recorder.revert { @recorder.execute "some sql" }
66
+ end
67
+ end
68
+
69
+ def test_record
70
+ @recorder.record :create_table, [:system_settings]
71
+ assert_equal 1, @recorder.commands.length
72
+ end
73
+
74
+ def test_inverted_commands_are_reversed
75
+ @recorder.revert do
76
+ @recorder.record :create_table, [:hello]
77
+ @recorder.record :create_table, [:world]
78
+ end
79
+ tables = @recorder.commands.map { |_cmd, args, _block| args }
80
+ assert_equal [[:world], [:hello]], tables
81
+ end
82
+
83
+ def test_revert_order
84
+ block = Proc.new { |t| t.string :name }
85
+ @recorder.instance_eval do
86
+ create_table("apples", &block)
87
+ revert do
88
+ create_table("bananas", &block)
89
+ revert do
90
+ create_table("clementines", &block)
91
+ create_table("dates")
92
+ end
93
+ create_table("elderberries")
94
+ end
95
+ revert do
96
+ create_table("figs", &block)
97
+ create_table("grapes")
98
+ end
99
+ end
100
+ assert_equal [[:create_table, ["apples"], block], [:drop_table, ["elderberries"], nil],
101
+ [:create_table, ["clementines"], block], [:create_table, ["dates"], nil],
102
+ [:drop_table, ["bananas"], block], [:drop_table, ["grapes"], nil],
103
+ [:drop_table, ["figs"], block]], @recorder.commands
104
+ end
105
+
106
+ def test_invert_change_table
107
+ @recorder.revert do
108
+ @recorder.change_table :fruits do |t|
109
+ t.string :name
110
+ t.rename :kind, :cultivar
111
+ end
112
+ end
113
+
114
+ if RUBY_VERSION >= "2.8"
115
+ assert_equal [
116
+ [:rename_column, [:fruits, :cultivar, :kind]],
117
+ [:remove_column, [:fruits, :name, :string], nil],
118
+ ], @recorder.commands
119
+ else
120
+ assert_equal [
121
+ [:rename_column, [:fruits, :cultivar, :kind]],
122
+ [:remove_column, [:fruits, :name, :string, {}], nil],
123
+ ], @recorder.commands
124
+ end
125
+
126
+ assert_raises(ActiveRecord::IrreversibleMigration) do
127
+ @recorder.revert do
128
+ @recorder.change_table :fruits do |t|
129
+ t.remove :kind
130
+ end
131
+ end
132
+ end
133
+ end
134
+
135
+ def test_invert_create_table
136
+ @recorder.revert do
137
+ @recorder.record :create_table, [:system_settings]
138
+ end
139
+ drop_table = @recorder.commands.first
140
+ assert_equal [:drop_table, [:system_settings], nil], drop_table
141
+ end
142
+
143
+ def test_invert_create_table_with_options_and_block
144
+ block = Proc.new { }
145
+ drop_table = @recorder.inverse_of :create_table, [:people_reminders, id: false], &block
146
+ assert_equal [:drop_table, [:people_reminders, id: false], block], drop_table
147
+ end
148
+
149
+ def test_invert_drop_table
150
+ block = Proc.new { }
151
+ create_table = @recorder.inverse_of :drop_table, [:people_reminders, id: false], &block
152
+ assert_equal [:create_table, [:people_reminders, id: false], block], create_table
153
+ end
154
+
155
+ def test_invert_drop_table_without_a_block_nor_option
156
+ assert_raises(ActiveRecord::IrreversibleMigration) do
157
+ @recorder.inverse_of :drop_table, [:people_reminders]
158
+ end
159
+ end
160
+
161
+ def test_invert_create_join_table
162
+ drop_join_table = @recorder.inverse_of :create_join_table, [:musics, :artists]
163
+ assert_equal [:drop_join_table, [:musics, :artists], nil], drop_join_table
164
+ end
165
+
166
+ def test_invert_create_join_table_with_table_name
167
+ drop_join_table = @recorder.inverse_of :create_join_table, [:musics, :artists, table_name: :catalog]
168
+ assert_equal [:drop_join_table, [:musics, :artists, table_name: :catalog], nil], drop_join_table
169
+ end
170
+
171
+ def test_invert_drop_join_table
172
+ block = Proc.new { }
173
+ create_join_table = @recorder.inverse_of :drop_join_table, [:musics, :artists, table_name: :catalog], &block
174
+ assert_equal [:create_join_table, [:musics, :artists, table_name: :catalog], block], create_join_table
175
+ end
176
+
177
+ def test_invert_rename_table
178
+ rename = @recorder.inverse_of :rename_table, [:old, :new]
179
+ assert_equal [:rename_table, [:new, :old]], rename
180
+ end
181
+
182
+ def test_invert_add_column
183
+ remove = @recorder.inverse_of :add_column, [:table, :column, :type, {}]
184
+ assert_equal [:remove_column, [:table, :column, :type, {}], nil], remove
185
+ end
186
+
187
+ def test_invert_change_column
188
+ assert_raises(ActiveRecord::IrreversibleMigration) do
189
+ @recorder.inverse_of :change_column, [:table, :column, :type, {}]
190
+ end
191
+ end
192
+
193
+ def test_invert_remove_column
194
+ add = @recorder.inverse_of :remove_column, [:table, :column, :type, {}]
195
+ assert_equal [:add_column, [:table, :column, :type, {}], nil], add
196
+ end
197
+
198
+ def test_invert_remove_column_without_type
199
+ assert_raises(ActiveRecord::IrreversibleMigration) do
200
+ @recorder.inverse_of :remove_column, [:table, :column]
201
+ end
202
+ end
203
+
204
+ def test_invert_add_index
205
+ remove = @recorder.inverse_of :add_index, [:table, [:one, :two]]
206
+ if ActiveRecord::gem_version < Gem::Version.create('6.1.0')
207
+ assert_equal [:remove_index, [:table, { column: [:one, :two] }]], remove
208
+ else
209
+ assert_equal [:remove_index, [:table, [:one, :two]], nil], remove
210
+ end
211
+ end
212
+
213
+ def test_invert_add_index_with_name
214
+ remove = @recorder.inverse_of :add_index, [:table, [:one, :two], name: "new_index"]
215
+ if ActiveRecord::gem_version < Gem::Version.create('6.1.0')
216
+ assert_equal [:remove_index, [:table, { name: "new_index" }]], remove
217
+ else
218
+ assert_equal [:remove_index, [:table, [:one, :two], {:name=>"new_index"}], nil], remove
219
+ end
220
+ end
221
+
222
+ def test_invert_remove_index
223
+ add = @recorder.inverse_of :remove_index, [:table, :one]
224
+ assert_equal [:add_index, [:table, :one]], add
225
+ end
226
+
227
+ def test_invert_remove_index_with_options
228
+ add = @recorder.inverse_of :remove_index, [:table, { column: :one }]
229
+ if ActiveRecord::gem_version < Gem::Version.create('6.1.0')
230
+ assert_equal [:add_index, [:table, :one, {} ]], add
231
+ else
232
+ assert_equal [:add_index, [:table, :one ]], add
233
+ end
234
+ end
235
+
236
+ def test_invert_remove_index_with_positional_column
237
+ add = @recorder.inverse_of :remove_index, [:table, { column: [:one, :two], options: true }]
238
+ assert_equal [:add_index, [:table, [:one, :two], options: true]], add
239
+ end
240
+
241
+ def test_invert_remove_index_with_column
242
+ add = @recorder.inverse_of :remove_index, [:table, { column: [:one, :two], options: true }]
243
+ assert_equal [:add_index, [:table, [:one, :two], options: true]], add
244
+ end
245
+
246
+ def test_invert_remove_index_with_name
247
+ add = @recorder.inverse_of :remove_index, [:table, { column: [:one, :two], name: "new_index" }]
248
+ assert_equal [:add_index, [:table, [:one, :two], name: "new_index"]], add
249
+ end
250
+
251
+ def test_invert_remove_index_with_no_special_options
252
+ add = @recorder.inverse_of :remove_index, [:table, { column: [:one, :two] }]
253
+ if ActiveRecord::gem_version < Gem::Version.create('6.1.0')
254
+ assert_equal [:add_index, [:table, [:one, :two], {}]], add
255
+ else
256
+ assert_equal [:add_index, [:table, [:one, :two]]], add
257
+ end
258
+ end
259
+
260
+ def test_invert_remove_index_with_no_column
261
+ assert_raises(ActiveRecord::IrreversibleMigration) do
262
+ @recorder.inverse_of :remove_index, [:table, name: "new_index"]
263
+ end
264
+ end
265
+
266
+ def test_invert_rename_index
267
+ rename = @recorder.inverse_of :rename_index, [:table, :old, :new]
268
+ assert_equal [:rename_index, [:table, :new, :old]], rename
269
+ end
270
+
271
+ def test_invert_add_timestamps
272
+ remove = @recorder.inverse_of :add_timestamps, [:table]
273
+ assert_equal [:remove_timestamps, [:table], nil], remove
274
+ end
275
+
276
+ def test_invert_remove_timestamps
277
+ add = @recorder.inverse_of :remove_timestamps, [:table, { null: true }]
278
+ assert_equal [:add_timestamps, [:table, { null: true }], nil], add
279
+ end
280
+
281
+ def test_invert_add_reference
282
+ remove = @recorder.inverse_of :add_reference, [:table, :taggable, { polymorphic: true }]
283
+ assert_equal [:remove_reference, [:table, :taggable, { polymorphic: true }], nil], remove
284
+ end
285
+
286
+ def test_invert_add_belongs_to_alias
287
+ remove = @recorder.inverse_of :add_belongs_to, [:table, :user]
288
+ assert_equal [:remove_reference, [:table, :user], nil], remove
289
+ end
290
+
291
+ def test_invert_remove_reference
292
+ add = @recorder.inverse_of :remove_reference, [:table, :taggable, { polymorphic: true }]
293
+ assert_equal [:add_reference, [:table, :taggable, { polymorphic: true }], nil], add
294
+ end
295
+
296
+ def test_invert_remove_reference_with_index_and_foreign_key
297
+ add = @recorder.inverse_of :remove_reference, [:table, :taggable, { index: true, foreign_key: true }]
298
+ assert_equal [:add_reference, [:table, :taggable, { index: true, foreign_key: true }], nil], add
299
+ end
300
+
301
+ def test_invert_remove_belongs_to_alias
302
+ add = @recorder.inverse_of :remove_belongs_to, [:table, :user]
303
+ assert_equal [:add_reference, [:table, :user], nil], add
304
+ end
305
+
306
+ def test_invert_enable_extension
307
+ disable = @recorder.inverse_of :enable_extension, ["uuid-ossp"]
308
+ assert_equal [:disable_extension, ["uuid-ossp"], nil], disable
309
+ end
310
+
311
+ def test_invert_disable_extension
312
+ enable = @recorder.inverse_of :disable_extension, ["uuid-ossp"]
313
+ assert_equal [:enable_extension, ["uuid-ossp"], nil], enable
314
+ end
315
+
316
+ def test_invert_add_foreign_key
317
+ enable = @recorder.inverse_of :add_foreign_key, [:dogs, :people]
318
+ if ActiveRecord.gem_version < VERSION_6_0_3
319
+ assert_equal [:remove_foreign_key, [:dogs, :people]], enable
320
+ else
321
+ assert_equal [:remove_foreign_key, [:dogs, :people], nil], enable
322
+ end
323
+ end
324
+
325
+ def test_invert_remove_foreign_key
326
+ enable = @recorder.inverse_of :remove_foreign_key, [:dogs, :people]
327
+ assert_equal [:add_foreign_key, [:dogs, :people]], enable
328
+ end
329
+
330
+ def test_invert_add_foreign_key_with_column
331
+ enable = @recorder.inverse_of :add_foreign_key, [:dogs, :people, column: "owner_id"]
332
+ if ActiveRecord.gem_version < VERSION_6_0_3
333
+ assert_equal [:remove_foreign_key, [:dogs, column: "owner_id"]], enable
334
+ else
335
+ assert_equal [:remove_foreign_key, [:dogs, :people, column: "owner_id"], nil], enable
336
+ end
337
+ end
338
+
339
+ def test_invert_remove_foreign_key_with_column
340
+ enable = @recorder.inverse_of :remove_foreign_key, [:dogs, :people, column: "owner_id"]
341
+ assert_equal [:add_foreign_key, [:dogs, :people, column: "owner_id"]], enable
342
+ end
343
+
344
+ def test_invert_add_foreign_key_with_column_and_name
345
+ enable = @recorder.inverse_of :add_foreign_key, [:dogs, :people, column: "owner_id", name: "fk"]
346
+ if ActiveRecord.gem_version < VERSION_6_0_3
347
+ assert_equal [:remove_foreign_key, [:dogs, { name: "fk" }]], enable
348
+ else
349
+ assert_equal [:remove_foreign_key, [:dogs, :people, { column: "owner_id", name: "fk" }], nil], enable
350
+ end
351
+ end
352
+
353
+ def test_invert_remove_foreign_key_with_column_and_name
354
+ enable = @recorder.inverse_of :remove_foreign_key, [:dogs, :people, column: "owner_id", name: "fk"]
355
+ assert_equal [:add_foreign_key, [:dogs, :people, column: "owner_id", name: "fk"]], enable
356
+ end
357
+
358
+ def test_invert_remove_foreign_key_with_primary_key
359
+ enable = @recorder.inverse_of :remove_foreign_key, [:dogs, :people, primary_key: "person_id"]
360
+ assert_equal [:add_foreign_key, [:dogs, :people, primary_key: "person_id"]], enable
361
+ end
362
+
363
+ def test_invert_remove_foreign_key_with_primary_key_and_to_table_in_options
364
+ enable = @recorder.inverse_of :remove_foreign_key, [:dogs, to_table: :people, primary_key: "uuid"]
365
+ assert_equal [:add_foreign_key, [:dogs, :people, primary_key: "uuid"]], enable
366
+ end
367
+
368
+ def test_invert_remove_foreign_key_with_on_delete_on_update
369
+ enable = @recorder.inverse_of :remove_foreign_key, [:dogs, :people, on_delete: :nullify, on_update: :cascade]
370
+ assert_equal [:add_foreign_key, [:dogs, :people, on_delete: :nullify, on_update: :cascade]], enable
371
+ end
372
+
373
+ def test_invert_remove_foreign_key_with_to_table_in_options
374
+ enable = @recorder.inverse_of :remove_foreign_key, [:dogs, to_table: :people]
375
+ assert_equal [:add_foreign_key, [:dogs, :people]], enable
376
+
377
+ enable = @recorder.inverse_of :remove_foreign_key, [:dogs, to_table: :people, column: :owner_id]
378
+ assert_equal [:add_foreign_key, [:dogs, :people, column: :owner_id]], enable
379
+ end
380
+
381
+ def test_invert_remove_foreign_key_is_irreversible_without_to_table
382
+ assert_raises ActiveRecord::IrreversibleMigration do
383
+ @recorder.inverse_of :remove_foreign_key, [:dogs, column: "owner_id"]
384
+ end
385
+
386
+ assert_raises ActiveRecord::IrreversibleMigration do
387
+ @recorder.inverse_of :remove_foreign_key, [:dogs, name: "fk"]
388
+ end
389
+
390
+ assert_raises ActiveRecord::IrreversibleMigration do
391
+ @recorder.inverse_of :remove_foreign_key, [:dogs]
392
+ end
393
+ end
394
+
395
+ def test_invert_transaction_with_irreversible_inside_is_irreversible
396
+ assert_raises(ActiveRecord::IrreversibleMigration) do
397
+ @recorder.revert do
398
+ @recorder.transaction do
399
+ @recorder.execute "some sql"
400
+ end
401
+ end
402
+ end
403
+ end
404
+ end
405
+ end
406
+ end
@@ -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