pg_trunk 0.1.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 (196) hide show
  1. checksums.yaml +7 -0
  2. data/.github/workflows/ci.yml +87 -0
  3. data/.gitignore +9 -0
  4. data/.rspec +4 -0
  5. data/.rubocop.yml +92 -0
  6. data/.yardopts +4 -0
  7. data/CHANGELOG.md +31 -0
  8. data/CONTRIBUTING.md +17 -0
  9. data/Gemfile +22 -0
  10. data/LICENSE.txt +21 -0
  11. data/README.md +141 -0
  12. data/Rakefile +16 -0
  13. data/bin/console +8 -0
  14. data/bin/rake +19 -0
  15. data/bin/rspec +19 -0
  16. data/bin/setup +8 -0
  17. data/bin/yard +19 -0
  18. data/lib/pg_trunk/core/adapters/postgres.rb +80 -0
  19. data/lib/pg_trunk/core/dependencies_resolver.rb +101 -0
  20. data/lib/pg_trunk/core/generators.rb +140 -0
  21. data/lib/pg_trunk/core/operation/attributes.rb +78 -0
  22. data/lib/pg_trunk/core/operation/callbacks.rb +40 -0
  23. data/lib/pg_trunk/core/operation/generators.rb +51 -0
  24. data/lib/pg_trunk/core/operation/inversion.rb +70 -0
  25. data/lib/pg_trunk/core/operation/registration.rb +55 -0
  26. data/lib/pg_trunk/core/operation/ruby_builder.rb +112 -0
  27. data/lib/pg_trunk/core/operation/ruby_helpers.rb +99 -0
  28. data/lib/pg_trunk/core/operation/sql_helpers.rb +44 -0
  29. data/lib/pg_trunk/core/operation/validations.rb +21 -0
  30. data/lib/pg_trunk/core/operation.rb +78 -0
  31. data/lib/pg_trunk/core/qualified_name.rb +165 -0
  32. data/lib/pg_trunk/core/railtie/command_recorder.rb +30 -0
  33. data/lib/pg_trunk/core/railtie/custom_types.rb +37 -0
  34. data/lib/pg_trunk/core/railtie/migration.rb +50 -0
  35. data/lib/pg_trunk/core/railtie/migrator.rb +22 -0
  36. data/lib/pg_trunk/core/railtie/schema_dumper.rb +75 -0
  37. data/lib/pg_trunk/core/railtie/schema_migration.rb +22 -0
  38. data/lib/pg_trunk/core/railtie/statements.rb +21 -0
  39. data/lib/pg_trunk/core/railtie.rb +35 -0
  40. data/lib/pg_trunk/core/registry.rb +159 -0
  41. data/lib/pg_trunk/core/serializers/array_of_hashes_serializer.rb +28 -0
  42. data/lib/pg_trunk/core/serializers/array_of_strings_serializer.rb +29 -0
  43. data/lib/pg_trunk/core/serializers/array_of_symbols_serializer.rb +28 -0
  44. data/lib/pg_trunk/core/serializers/array_serializer.rb +22 -0
  45. data/lib/pg_trunk/core/serializers/lowercase_string_serializer.rb +21 -0
  46. data/lib/pg_trunk/core/serializers/multiline_text_serializer.rb +21 -0
  47. data/lib/pg_trunk/core/serializers/qualified_name_serializer.rb +27 -0
  48. data/lib/pg_trunk/core/serializers/symbol_serializer.rb +22 -0
  49. data/lib/pg_trunk/core/serializers.rb +16 -0
  50. data/lib/pg_trunk/core/validators/all_items_valid_validator.rb +15 -0
  51. data/lib/pg_trunk/core/validators/difference_validator.rb +19 -0
  52. data/lib/pg_trunk/core/validators.rb +10 -0
  53. data/lib/pg_trunk/core.rb +21 -0
  54. data/lib/pg_trunk/generators.rb +7 -0
  55. data/lib/pg_trunk/operations/check_constraints/add_check_constraint.rb +109 -0
  56. data/lib/pg_trunk/operations/check_constraints/base.rb +69 -0
  57. data/lib/pg_trunk/operations/check_constraints/drop_check_constraint.rb +60 -0
  58. data/lib/pg_trunk/operations/check_constraints/rename_check_constraint.rb +54 -0
  59. data/lib/pg_trunk/operations/check_constraints/validate_check_constraint.rb +39 -0
  60. data/lib/pg_trunk/operations/check_constraints.rb +14 -0
  61. data/lib/pg_trunk/operations/composite_types/base.rb +61 -0
  62. data/lib/pg_trunk/operations/composite_types/change_composite_type.rb +136 -0
  63. data/lib/pg_trunk/operations/composite_types/column.rb +118 -0
  64. data/lib/pg_trunk/operations/composite_types/create_composite_type.rb +99 -0
  65. data/lib/pg_trunk/operations/composite_types/drop_composite_type.rb +67 -0
  66. data/lib/pg_trunk/operations/composite_types/rename_composite_type.rb +44 -0
  67. data/lib/pg_trunk/operations/composite_types.rb +15 -0
  68. data/lib/pg_trunk/operations/domains/base.rb +46 -0
  69. data/lib/pg_trunk/operations/domains/change_domain.rb +140 -0
  70. data/lib/pg_trunk/operations/domains/constraint.rb +93 -0
  71. data/lib/pg_trunk/operations/domains/create_domain.rb +124 -0
  72. data/lib/pg_trunk/operations/domains/drop_domain.rb +65 -0
  73. data/lib/pg_trunk/operations/domains/rename_domain.rb +44 -0
  74. data/lib/pg_trunk/operations/domains.rb +15 -0
  75. data/lib/pg_trunk/operations/enums/base.rb +47 -0
  76. data/lib/pg_trunk/operations/enums/change.rb +55 -0
  77. data/lib/pg_trunk/operations/enums/change_enum.rb +119 -0
  78. data/lib/pg_trunk/operations/enums/create_enum.rb +83 -0
  79. data/lib/pg_trunk/operations/enums/drop_enum.rb +63 -0
  80. data/lib/pg_trunk/operations/enums/rename_enum.rb +44 -0
  81. data/lib/pg_trunk/operations/enums.rb +15 -0
  82. data/lib/pg_trunk/operations/foreign_keys/add_foreign_key.rb +174 -0
  83. data/lib/pg_trunk/operations/foreign_keys/base.rb +155 -0
  84. data/lib/pg_trunk/operations/foreign_keys/drop_foreign_key.rb +76 -0
  85. data/lib/pg_trunk/operations/foreign_keys/rename_foreign_key.rb +63 -0
  86. data/lib/pg_trunk/operations/foreign_keys.rb +16 -0
  87. data/lib/pg_trunk/operations/functions/base.rb +54 -0
  88. data/lib/pg_trunk/operations/functions/change_function.rb +108 -0
  89. data/lib/pg_trunk/operations/functions/create_function.rb +198 -0
  90. data/lib/pg_trunk/operations/functions/drop_function.rb +88 -0
  91. data/lib/pg_trunk/operations/functions/rename_function.rb +57 -0
  92. data/lib/pg_trunk/operations/functions.rb +14 -0
  93. data/lib/pg_trunk/operations/indexes/add_index.rb +68 -0
  94. data/lib/pg_trunk/operations/indexes.rb +10 -0
  95. data/lib/pg_trunk/operations/materialized_views/base.rb +79 -0
  96. data/lib/pg_trunk/operations/materialized_views/change_materialized_view.rb +139 -0
  97. data/lib/pg_trunk/operations/materialized_views/column.rb +94 -0
  98. data/lib/pg_trunk/operations/materialized_views/create_materialized_view.rb +170 -0
  99. data/lib/pg_trunk/operations/materialized_views/drop_materialized_view.rb +70 -0
  100. data/lib/pg_trunk/operations/materialized_views/refresh_materialized_view.rb +48 -0
  101. data/lib/pg_trunk/operations/materialized_views/rename_materialized_view.rb +61 -0
  102. data/lib/pg_trunk/operations/materialized_views.rb +17 -0
  103. data/lib/pg_trunk/operations/procedures/base.rb +42 -0
  104. data/lib/pg_trunk/operations/procedures/change_procedure.rb +107 -0
  105. data/lib/pg_trunk/operations/procedures/create_procedure.rb +146 -0
  106. data/lib/pg_trunk/operations/procedures/drop_procedure.rb +66 -0
  107. data/lib/pg_trunk/operations/procedures/rename_procedure.rb +57 -0
  108. data/lib/pg_trunk/operations/procedures.rb +14 -0
  109. data/lib/pg_trunk/operations/statistics/base.rb +94 -0
  110. data/lib/pg_trunk/operations/statistics/create_statistics.rb +181 -0
  111. data/lib/pg_trunk/operations/statistics/drop_statistics.rb +75 -0
  112. data/lib/pg_trunk/operations/statistics/rename_statistics.rb +48 -0
  113. data/lib/pg_trunk/operations/statistics.rb +13 -0
  114. data/lib/pg_trunk/operations/tables/create_table.rb +75 -0
  115. data/lib/pg_trunk/operations/tables.rb +10 -0
  116. data/lib/pg_trunk/operations/triggers/base.rb +119 -0
  117. data/lib/pg_trunk/operations/triggers/change_trigger.rb +82 -0
  118. data/lib/pg_trunk/operations/triggers/create_trigger.rb +208 -0
  119. data/lib/pg_trunk/operations/triggers/drop_trigger.rb +66 -0
  120. data/lib/pg_trunk/operations/triggers/rename_trigger.rb +71 -0
  121. data/lib/pg_trunk/operations/triggers.rb +14 -0
  122. data/lib/pg_trunk/operations/views/base.rb +38 -0
  123. data/lib/pg_trunk/operations/views/change_view.rb +90 -0
  124. data/lib/pg_trunk/operations/views/create_view.rb +115 -0
  125. data/lib/pg_trunk/operations/views/drop_view.rb +69 -0
  126. data/lib/pg_trunk/operations/views/rename_view.rb +58 -0
  127. data/lib/pg_trunk/operations/views.rb +14 -0
  128. data/lib/pg_trunk/operations.rb +23 -0
  129. data/lib/pg_trunk/version.rb +6 -0
  130. data/lib/pg_trunk.rb +27 -0
  131. data/pg_trunk.gemspec +34 -0
  132. data/spec/dummy/.gitignore +16 -0
  133. data/spec/dummy/Rakefile +15 -0
  134. data/spec/dummy/bin/bundle +6 -0
  135. data/spec/dummy/bin/rails +6 -0
  136. data/spec/dummy/bin/rake +6 -0
  137. data/spec/dummy/config/application.rb +18 -0
  138. data/spec/dummy/config/boot.rb +7 -0
  139. data/spec/dummy/config/database.yml +14 -0
  140. data/spec/dummy/config/environment.rb +7 -0
  141. data/spec/dummy/config.ru +6 -0
  142. data/spec/dummy/db/materialized_views/admin_users_v01.sql +1 -0
  143. data/spec/dummy/db/migrate/.keep +0 -0
  144. data/spec/dummy/db/schema.rb +18 -0
  145. data/spec/dummy/db/views/admin_users_v01.sql +1 -0
  146. data/spec/dummy/db/views/admin_users_v02.sql +1 -0
  147. data/spec/operations/check_constraints/add_check_constraint_spec.rb +85 -0
  148. data/spec/operations/check_constraints/drop_check_constraint_spec.rb +111 -0
  149. data/spec/operations/check_constraints/rename_check_constraint_spec.rb +90 -0
  150. data/spec/operations/composite_types/change_composite_type_spec.rb +257 -0
  151. data/spec/operations/composite_types/create_composite_type_spec.rb +55 -0
  152. data/spec/operations/composite_types/drop_composite_type_spec.rb +109 -0
  153. data/spec/operations/composite_types/rename_composite_type_spec.rb +74 -0
  154. data/spec/operations/dependency_resolver_spec.rb +177 -0
  155. data/spec/operations/domains/change_domain_spec.rb +287 -0
  156. data/spec/operations/domains/create_domain_spec.rb +69 -0
  157. data/spec/operations/domains/drop_domain_spec.rb +119 -0
  158. data/spec/operations/domains/rename_domain_spec.rb +70 -0
  159. data/spec/operations/enums/change_enum_spec.rb +157 -0
  160. data/spec/operations/enums/create_enum_spec.rb +40 -0
  161. data/spec/operations/enums/drop_enum_spec.rb +120 -0
  162. data/spec/operations/enums/rename_enum_spec.rb +72 -0
  163. data/spec/operations/foreign_keys/add_foreign_key_spec.rb +208 -0
  164. data/spec/operations/foreign_keys/drop_foreign_key_spec.rb +167 -0
  165. data/spec/operations/foreign_keys/rename_foreign_key_spec.rb +101 -0
  166. data/spec/operations/functions/change_function_spec.rb +166 -0
  167. data/spec/operations/functions/create_function_spec.rb +192 -0
  168. data/spec/operations/functions/drop_function_spec.rb +182 -0
  169. data/spec/operations/functions/rename_function_spec.rb +101 -0
  170. data/spec/operations/indexes/add_index_spec.rb +94 -0
  171. data/spec/operations/materialized_views/change_materialized_view_spec.rb +190 -0
  172. data/spec/operations/materialized_views/create_materialized_view_spec.rb +144 -0
  173. data/spec/operations/materialized_views/drop_materialized_view_spec.rb +145 -0
  174. data/spec/operations/materialized_views/refresh_materialized_view_spec.rb +79 -0
  175. data/spec/operations/materialized_views/rename_materialized_view_spec.rb +88 -0
  176. data/spec/operations/procedures/change_procedure_spec.rb +175 -0
  177. data/spec/operations/procedures/create_procedure_spec.rb +151 -0
  178. data/spec/operations/procedures/drop_procedure_spec.rb +159 -0
  179. data/spec/operations/procedures/rename_procedure_spec.rb +107 -0
  180. data/spec/operations/statistics/create_statistics_spec.rb +230 -0
  181. data/spec/operations/statistics/drop_statistics_spec.rb +106 -0
  182. data/spec/operations/statistics/rename_statistics_spec.rb +129 -0
  183. data/spec/operations/tables/create_table_spec.rb +53 -0
  184. data/spec/operations/tables/rename_table_spec.rb +37 -0
  185. data/spec/operations/triggers/change_trigger_spec.rb +195 -0
  186. data/spec/operations/triggers/create_trigger_spec.rb +104 -0
  187. data/spec/operations/triggers/drop_trigger_spec.rb +124 -0
  188. data/spec/operations/triggers/rename_trigger_spec.rb +160 -0
  189. data/spec/operations/views/change_view_spec.rb +144 -0
  190. data/spec/operations/views/create_view_spec.rb +134 -0
  191. data/spec/operations/views/drop_view_spec.rb +146 -0
  192. data/spec/operations/views/rename_view_spec.rb +85 -0
  193. data/spec/pg_trunk/dependencies_resolver_spec.rb +43 -0
  194. data/spec/spec_helper.rb +28 -0
  195. data/spec/support/migrations_helper.rb +376 -0
  196. metadata +348 -0
@@ -0,0 +1,195 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe ActiveRecord::Migration, "#change_trigger" do
4
+ before_all do
5
+ run_migration <<~RUBY
6
+ create_table "users", force: :cascade do |t|
7
+ t.string "name"
8
+ t.boolean "admin"
9
+ end
10
+
11
+ create_function "do_nothing() trigger" do |f|
12
+ f.language "plpgsql"
13
+ f.body "BEGIN END;"
14
+ end
15
+
16
+ create_function "set_foo() trigger" do |f|
17
+ f.language "plpgsql"
18
+ f.body "BEGIN SET custom.foo = 42; END;"
19
+ end
20
+ RUBY
21
+ end
22
+ before { run_migration(old_snippet) }
23
+
24
+ let(:old_snippet) do
25
+ <<~RUBY
26
+ create_trigger "users", "do_nothing" do |t|
27
+ t.function "do_nothing()"
28
+ t.for_each :row
29
+ t.type :after
30
+ t.events %i[update]
31
+ t.comment "Old comment"
32
+ end
33
+ RUBY
34
+ end
35
+
36
+ context "in PostgreSQL v14+", since_version: 14 do
37
+ context "with explicitly reversible changes" do
38
+ let(:migration) do
39
+ <<~RUBY
40
+ change_trigger "users", "do_nothing" do |t|
41
+ t.function "set_foo()", from: "do_nothing()"
42
+ t.type :before, from: :after
43
+ t.events %i[insert update], from: %i[update]
44
+ t.comment "New comment", from: "Old comment"
45
+ end
46
+ RUBY
47
+ end
48
+ let(:new_snippet) do
49
+ <<~RUBY
50
+ create_trigger "users", "do_nothing" do |t|
51
+ t.function "set_foo()"
52
+ t.for_each :row
53
+ t.type :before
54
+ t.events %i[insert update]
55
+ t.comment "New comment"
56
+ end
57
+ RUBY
58
+ end
59
+
60
+ its(:execution) { is_expected.to insert(new_snippet).into_schema }
61
+ its(:execution) { is_expected.to remove(old_snippet).from_schema }
62
+ its(:inversion) { is_expected.not_to change_schema }
63
+ end
64
+
65
+ context "with implicitly reversible changes" do
66
+ let(:migration) do
67
+ <<~RUBY
68
+ change_trigger "users", "do_nothing" do |t|
69
+ t.for_each :statement
70
+ end
71
+ RUBY
72
+ end
73
+ let(:new_snippet) do
74
+ <<~RUBY
75
+ create_trigger "users", "do_nothing" do |t|
76
+ t.function "do_nothing()"
77
+ t.type :after
78
+ t.events %i[update]
79
+ t.comment "Old comment"
80
+ end
81
+ RUBY
82
+ end
83
+
84
+ its(:execution) { is_expected.to insert(new_snippet).into_schema }
85
+ its(:execution) { is_expected.to remove(old_snippet).from_schema }
86
+ its(:inversion) { is_expected.not_to change_schema }
87
+ end
88
+
89
+ context "with irreversible changes" do
90
+ let(:migration) do
91
+ <<~RUBY
92
+ change_trigger "users", "do_nothing" do |t|
93
+ t.function "set_foo()"
94
+ t.type :before
95
+ t.events %i[insert update]
96
+ t.comment "New comment"
97
+ end
98
+ RUBY
99
+ end
100
+ let(:new_snippet) do
101
+ <<~RUBY
102
+ create_trigger "users", "do_nothing" do |t|
103
+ t.function "set_foo()"
104
+ t.for_each :row
105
+ t.type :before
106
+ t.events %i[insert update]
107
+ t.comment "New comment"
108
+ end
109
+ RUBY
110
+ end
111
+
112
+ its(:execution) { is_expected.to insert(new_snippet).into_schema }
113
+ its(:execution) { is_expected.to remove(old_snippet).from_schema }
114
+ it { is_expected.to be_irreversible.because_of(/body|comment/i) }
115
+ end
116
+
117
+ context "when the procedure is absent" do
118
+ let(:migration) do
119
+ <<~RUBY
120
+ change_trigger "users", "unknown" do |t|
121
+ t.comment "New comment", from: "Old comment"
122
+ end
123
+ RUBY
124
+ end
125
+
126
+ context "without the `if_exists` option" do
127
+ its(:execution) { is_expected.to raise_error(StandardError) }
128
+ end
129
+
130
+ context "with the `if_exists: true` option" do
131
+ let(:migration) do
132
+ <<~RUBY
133
+ change_trigger "users", "unknown", if_exists: true do |t|
134
+ t.comment "New comment", from: "Old comment"
135
+ end
136
+ RUBY
137
+ end
138
+
139
+ its(:execution) { is_expected.not_to change_schema }
140
+ it { is_expected.to be_irreversible.because_of(/if_exists: true/i) }
141
+ end
142
+ end
143
+
144
+ context "with unknown table" do
145
+ let(:migration) do
146
+ <<~RUBY
147
+ change_trigger "user", "do_nothing" do |t|
148
+ t.comment "New comment", from: "Old comment"
149
+ end
150
+ RUBY
151
+ end
152
+
153
+ its(:execution) { is_expected.to raise_error(StandardError) }
154
+ end
155
+ end
156
+
157
+ context "in PostgreSQL before v14", before_version: 14 do
158
+ context "with explicitly reversible changes" do
159
+ let(:migration) do
160
+ <<~RUBY
161
+ change_trigger "users", "do_nothing" do |t|
162
+ t.function "set_foo()", from: "do_nothing()"
163
+ t.type :before, from: :after
164
+ t.events %i[insert update], from: %i[update]
165
+ t.comment "New comment", from: "Old comment"
166
+ end
167
+ RUBY
168
+ end
169
+
170
+ its(:execution) { is_expected.to raise_error(/supported by PostgreSQL server v14+/i) }
171
+ end
172
+ end
173
+
174
+ context "with no changes" do
175
+ let(:migration) do
176
+ <<~RUBY
177
+ change_trigger "users", "do_nothing"
178
+ RUBY
179
+ end
180
+
181
+ it { is_expected.to fail_validation.because(/changes can't be blank/i) }
182
+ end
183
+
184
+ context "without name" do
185
+ let(:migration) do
186
+ <<~RUBY
187
+ change_trigger "users", if_exists: true do |t|
188
+ t.comment "New comment", from: "Old comment"
189
+ end
190
+ RUBY
191
+ end
192
+
193
+ it { is_expected.to fail_validation.because(/name can't be blank/i) }
194
+ end
195
+ end
@@ -0,0 +1,104 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe ActiveRecord::Migration, "#create_trigger" do
4
+ before_all do
5
+ run_migration <<~RUBY
6
+ create_table "users", force: :cascade do |t|
7
+ t.string "name"
8
+ t.boolean "admin"
9
+ end
10
+
11
+ create_function "do_nothing() trigger" do |f|
12
+ f.language "plpgsql"
13
+ f.body "BEGIN END;"
14
+ end
15
+ RUBY
16
+ end
17
+
18
+ context "with an explicit name" do
19
+ let(:migration) do
20
+ <<~RUBY
21
+ create_trigger "users", "do_nothing" do |t|
22
+ t.function "do_nothing()"
23
+ t.for_each :row
24
+ t.type :after
25
+ t.events %i[update]
26
+ t.comment "Block granting rights of an admin"
27
+ end
28
+ RUBY
29
+ end
30
+
31
+ its(:execution) { is_expected.to insert(migration).into_schema }
32
+ its(:inversion) { is_expected.not_to change_schema }
33
+ end
34
+
35
+ context "with a constraint" do
36
+ let(:migration) do
37
+ <<~RUBY
38
+ create_trigger "users", "do_nothing" do |t|
39
+ t.function "do_nothing()"
40
+ t.constraint true
41
+ t.events %i[update]
42
+ t.comment "Block granting rights of an admin"
43
+ end
44
+ RUBY
45
+ end
46
+ let(:snippet) do
47
+ <<~RUBY
48
+ create_trigger "users", "do_nothing" do |t|
49
+ t.function "do_nothing()"
50
+ t.constraint true
51
+ t.for_each :row
52
+ t.type :after
53
+ t.events %i[update]
54
+ t.comment "Block granting rights of an admin"
55
+ end
56
+ RUBY
57
+ end
58
+
59
+ its(:execution) { is_expected.to insert(snippet).into_schema }
60
+ its(:inversion) { is_expected.not_to change_schema }
61
+ end
62
+
63
+ context "without a name" do
64
+ let(:migration) do
65
+ <<~RUBY
66
+ create_trigger "users" do |t|
67
+ t.function "do_nothing()"
68
+ t.for_each :row
69
+ t.type :before
70
+ t.events %i[insert]
71
+ t.comment "Block creation of an admin"
72
+ end
73
+ RUBY
74
+ end
75
+
76
+ its(:execution) { is_expected.to insert(migration).into_schema }
77
+ its(:inversion) { is_expected.not_to change_schema }
78
+ end
79
+
80
+ context "without a function" do
81
+ let(:migration) do
82
+ <<~RUBY
83
+ create_trigger "users" do |t|
84
+ t.type :instead_of
85
+ t.events %i[insert]
86
+ end
87
+ RUBY
88
+ end
89
+
90
+ it { is_expected.to fail_validation.because_of(/function/i) }
91
+ end
92
+
93
+ context "without events definition" do
94
+ let(:migration) do
95
+ <<~RUBY
96
+ create_trigger "users" do |t|
97
+ t.function "do_nothing()"
98
+ end
99
+ RUBY
100
+ end
101
+
102
+ it { is_expected.to fail_validation.because_of(/events/i) }
103
+ end
104
+ end
@@ -0,0 +1,124 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe ActiveRecord::Migration, "#drop_trigger" do
4
+ before_all do
5
+ run_migration <<~RUBY
6
+ create_table "users", force: :cascade do |t|
7
+ t.string "name"
8
+ t.boolean "admin"
9
+ end
10
+
11
+ create_function "do_nothing() trigger" do |f|
12
+ f.language "plpgsql"
13
+ f.body "BEGIN END;"
14
+ end
15
+ RUBY
16
+ end
17
+ before { run_migration(snippet) }
18
+
19
+ context "when a trigger had an explicit name" do
20
+ let(:snippet) do
21
+ <<~RUBY
22
+ create_trigger "users", "do_nothing" do |t|
23
+ t.function "do_nothing()"
24
+ t.for_each :row
25
+ t.type :after
26
+ t.events %i[update]
27
+ t.comment "My new trigger"
28
+ end
29
+ RUBY
30
+ end
31
+
32
+ context "with the full definition of the trigger" do
33
+ let(:migration) do
34
+ <<~RUBY
35
+ drop_trigger "users", "do_nothing" do |t|
36
+ t.function "do_nothing()"
37
+ t.for_each :row
38
+ t.type :after
39
+ t.events %i[update]
40
+ t.comment "My new trigger"
41
+ end
42
+ RUBY
43
+ end
44
+
45
+ its(:execution) { is_expected.to remove(snippet).from_schema }
46
+ its(:inversion) { is_expected.not_to change_schema }
47
+ end
48
+
49
+ context "with the explicit name only" do
50
+ let(:migration) do
51
+ <<~RUBY
52
+ drop_trigger "users", "do_nothing"
53
+ RUBY
54
+ end
55
+
56
+ its(:execution) { is_expected.to remove(snippet).from_schema }
57
+ it { is_expected.to be_irreversible.because_of(/function/i) }
58
+ end
59
+
60
+ context "when the trigger not existed" do
61
+ context "without the `if_exists` option" do
62
+ let(:migration) do
63
+ <<~RUBY
64
+ drop_trigger "users", "weird"
65
+ RUBY
66
+ end
67
+
68
+ its(:execution) { is_expected.to raise_error(StandardError) }
69
+ end
70
+
71
+ context "with the `if_exists` option" do
72
+ let(:migration) do
73
+ <<~RUBY
74
+ drop_trigger "users", "weird", if_exists: true
75
+ RUBY
76
+ end
77
+
78
+ its(:execution) { is_expected.not_to raise_error }
79
+ it { is_expected.to be_irreversible.because_of(/if_exists: true/i) }
80
+ end
81
+ end
82
+ end
83
+
84
+ context "when a trigger was anonymous (with a generated name)" do
85
+ let(:snippet) do
86
+ <<~RUBY
87
+ create_trigger "users" do |t|
88
+ t.function "do_nothing()"
89
+ t.for_each :row
90
+ t.type :after
91
+ t.events %i[update]
92
+ t.comment "My new trigger"
93
+ end
94
+ RUBY
95
+ end
96
+
97
+ context "with the full definition of the trigger" do
98
+ let(:migration) do
99
+ <<~RUBY
100
+ drop_trigger "users" do |t|
101
+ t.function "do_nothing()"
102
+ t.for_each :row
103
+ t.type :after
104
+ t.events %i[update]
105
+ t.comment "My new trigger"
106
+ end
107
+ RUBY
108
+ end
109
+
110
+ its(:execution) { is_expected.to remove(snippet).from_schema }
111
+ its(:inversion) { is_expected.not_to change_schema }
112
+ end
113
+
114
+ context "without a full definition" do
115
+ let(:migration) do
116
+ <<~RUBY
117
+ drop_trigger "users"
118
+ RUBY
119
+ end
120
+
121
+ it { is_expected.to fail_validation.because(/name can't be blank/i) }
122
+ end
123
+ end
124
+ end
@@ -0,0 +1,160 @@
1
+ # frozen_string_literal: true
2
+
3
+ describe ActiveRecord::Migration, "#rename_trigger" do
4
+ before_all do
5
+ run_migration <<~RUBY
6
+ create_table :foo
7
+ create_function "avoid() trigger", language: :plpgsql, body: "BEGIN END;"
8
+ RUBY
9
+ end
10
+ before { run_migration(old_snippet) }
11
+
12
+ context "when a trigger had an explicit name" do
13
+ let(:old_snippet) do
14
+ <<~RUBY
15
+ create_trigger "foo", "do_nothing" do |t|
16
+ t.function "avoid()"
17
+ t.type :after
18
+ t.events %i[insert]
19
+ end
20
+ RUBY
21
+ end
22
+
23
+ context "with both old and new names" do
24
+ let(:migration) do
25
+ <<~RUBY
26
+ rename_trigger :foo, :do_nothing, to: :do_something
27
+ RUBY
28
+ end
29
+ let(:new_snippet) do
30
+ <<~RUBY
31
+ create_trigger "foo", "do_something" do |t|
32
+ t.function "avoid()"
33
+ t.type :after
34
+ t.events %i[insert]
35
+ end
36
+ RUBY
37
+ end
38
+
39
+ its(:execution) { is_expected.to remove(old_snippet).from_schema }
40
+ its(:execution) { is_expected.to insert(new_snippet).into_schema }
41
+ its(:inversion) { is_expected.not_to change_schema }
42
+ end
43
+
44
+ context "when a new name can be generated from params" do
45
+ let(:migration) do
46
+ <<~RUBY
47
+ rename_trigger "foo", "do_nothing" do |t|
48
+ t.function "avoid()"
49
+ t.type :after
50
+ t.events %i[insert]
51
+ end
52
+ RUBY
53
+ end
54
+ let(:new_snippet) do
55
+ <<~RUBY
56
+ create_trigger "foo" do |t|
57
+ t.function "avoid()"
58
+ t.type :after
59
+ t.events %i[insert]
60
+ end
61
+ RUBY
62
+ end
63
+
64
+ its(:execution) { is_expected.to remove(old_snippet).from_schema }
65
+ its(:execution) { is_expected.to insert(new_snippet).into_schema }
66
+ its(:inversion) { is_expected.not_to change_schema }
67
+ end
68
+
69
+ context "when a new name can't be generated" do
70
+ let(:migration) do
71
+ <<~RUBY
72
+ rename_trigger "foo", "do_nothing"
73
+ RUBY
74
+ end
75
+
76
+ it { is_expected.to fail_validation.because(/new name can't be blank/i) }
77
+ end
78
+
79
+ context "with the same name" do
80
+ let(:migration) do
81
+ <<~RUBY
82
+ rename_trigger :foo, :do_nothing, to: :do_nothing
83
+ RUBY
84
+ end
85
+
86
+ it { is_expected.to fail_validation.because(/new name must be different/i) }
87
+ end
88
+
89
+ context "without an old name" do
90
+ let(:migration) do
91
+ <<~RUBY
92
+ rename_trigger :foo, to: :do_something
93
+ RUBY
94
+ end
95
+
96
+ it { is_expected.to fail_validation.because(/name can't be blank/i) }
97
+ end
98
+ end
99
+
100
+ context "when a trigger had a generated name" do
101
+ let(:old_snippet) do
102
+ <<~RUBY
103
+ create_trigger "foo" do |t|
104
+ t.function "avoid()"
105
+ t.type :after
106
+ t.events %i[insert]
107
+ end
108
+ RUBY
109
+ end
110
+
111
+ context "when the old name can be generated from params" do
112
+ let(:migration) do
113
+ <<~RUBY
114
+ rename_trigger "foo", to: "do_something" do |t|
115
+ t.function "avoid()"
116
+ t.type :after
117
+ t.events %i[insert]
118
+ end
119
+ RUBY
120
+ end
121
+ let(:new_snippet) do
122
+ <<~RUBY
123
+ create_trigger "foo", "do_something" do |t|
124
+ t.function "avoid()"
125
+ t.type :after
126
+ t.events %i[insert]
127
+ end
128
+ RUBY
129
+ end
130
+
131
+ its(:execution) { is_expected.to remove(old_snippet).from_schema }
132
+ its(:execution) { is_expected.to insert(new_snippet).into_schema }
133
+ its(:inversion) { is_expected.not_to change_schema }
134
+ end
135
+
136
+ context "when the old name can't be generated" do
137
+ let(:migration) do
138
+ <<~RUBY
139
+ rename_trigger "foo", to: "do_something"
140
+ RUBY
141
+ end
142
+
143
+ it { is_expected.to fail_validation.because(/name can't be blank/i) }
144
+ end
145
+
146
+ context "without a new name" do
147
+ let(:migration) do
148
+ <<~RUBY
149
+ rename_trigger "foo" do |t|
150
+ t.function "avoid()"
151
+ t.type :after
152
+ t.events %i[insert]
153
+ end
154
+ RUBY
155
+ end
156
+
157
+ it { is_expected.to fail_validation.because(/new name must be different/i) }
158
+ end
159
+ end
160
+ end