dynamic_migrations 3.6.7 → 3.6.8

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 (35) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +9 -0
  3. data/lib/dynamic_migrations/active_record/migrators/trigger.rb +10 -8
  4. data/lib/dynamic_migrations/postgres/generator/column.rb +4 -0
  5. data/lib/dynamic_migrations/postgres/generator/fragment.rb +64 -3
  6. data/lib/dynamic_migrations/postgres/generator/migration.rb +20 -4
  7. data/lib/dynamic_migrations/postgres/generator/table.rb +19 -3
  8. data/lib/dynamic_migrations/postgres/generator/trigger.rb +4 -2
  9. data/lib/dynamic_migrations/postgres/generator.rb +46 -16
  10. data/lib/dynamic_migrations/postgres/server/database/loaded_schemas_builder.rb +27 -10
  11. data/lib/dynamic_migrations/postgres/server/database/schema/table/column.rb +15 -2
  12. data/lib/dynamic_migrations/postgres/server/database/schema/table/trigger.rb +8 -8
  13. data/lib/dynamic_migrations/postgres/server/database/structure_loader.rb +8 -20
  14. data/lib/dynamic_migrations/postgres/server/database/triggers_and_functions_loader.rb +6 -2
  15. data/lib/dynamic_migrations/version.rb +1 -1
  16. data/sig/dynamic_migrations/active_record/migrators/trigger.rbs +7 -7
  17. data/sig/dynamic_migrations/postgres/generator/column.rbs +1 -1
  18. data/sig/dynamic_migrations/postgres/generator/enum.rbs +1 -1
  19. data/sig/dynamic_migrations/postgres/generator/extension.rbs +1 -1
  20. data/sig/dynamic_migrations/postgres/generator/foreign_key_constraint.rbs +1 -1
  21. data/sig/dynamic_migrations/postgres/generator/fragment.rbs +13 -2
  22. data/sig/dynamic_migrations/postgres/generator/function.rbs +1 -1
  23. data/sig/dynamic_migrations/postgres/generator/index.rbs +1 -1
  24. data/sig/dynamic_migrations/postgres/generator/migration.rbs +6 -2
  25. data/sig/dynamic_migrations/postgres/generator/primary_key.rbs +1 -1
  26. data/sig/dynamic_migrations/postgres/generator/schema.rbs +1 -1
  27. data/sig/dynamic_migrations/postgres/generator/table.rbs +3 -2
  28. data/sig/dynamic_migrations/postgres/generator/trigger.rbs +1 -1
  29. data/sig/dynamic_migrations/postgres/generator/unique_constraint.rbs +1 -1
  30. data/sig/dynamic_migrations/postgres/generator/validation.rbs +1 -1
  31. data/sig/dynamic_migrations/postgres/generator.rbs +1 -1
  32. data/sig/dynamic_migrations/postgres/server/database/schema/table/column.rbs +6 -1
  33. data/sig/dynamic_migrations/postgres/server/database/schema/table/trigger.rbs +2 -2
  34. data/sig/dynamic_migrations/postgres/server/database/schema/table/triggers.rbs +1 -1
  35. metadata +1 -1
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 595c87d8edaa9e8a2d3d8f3676e4383b1c5c3fd59223051d5541855e5117fa61
4
- data.tar.gz: df3dfbff71ec825947dd7d8a89fd8a163291fbdf5ef58ffa95b15b057ff028d9
3
+ metadata.gz: d876905704f02b0e0f4fa5ba3842e7b7b8083ab7ba957f7e30b2ea314f62578d
4
+ data.tar.gz: 06e02f49a1d162cff9062d4c785ae76f67e03547402411566152a2facc91812e
5
5
  SHA512:
6
- metadata.gz: 346ea3c2425e136487200f521b9669d1cd4ec3646f64113340b2bf487416b48226c68d4b32e5008dca9405f75dd7c50020edbe9caa33e4fcd2c676f61f09fbbf
7
- data.tar.gz: bfc5f568840046e813f0c04b47a54b50be0c4053ae2f8dd94cd5f59c86c42505aeb902d4a8eb85004b5aa0f37c922d25cac793d87a20f467d32bc2730f51f3fc
6
+ metadata.gz: 311b0e7c617dd0484212b84d4c929853f12c21fe9bd0ea78209d38a995c2ae20f4f2bc8a6674b6fb6ddba896130814bf6fbccfb6880828bcbecc3066c9986940
7
+ data.tar.gz: adafdf79065b117c281cf12aaf23abef54948bc6e93d78956157cc0b7d56f2e78bec05ba9e7c008138772477c9855107dafd41b39dc1d4f462c7a071ee00cb82
data/CHANGELOG.md CHANGED
@@ -1,5 +1,14 @@
1
1
  # Changelog
2
2
 
3
+ ## [3.6.8](https://github.com/craigulliott/dynamic_migrations/compare/v3.6.7...v3.6.8) (2023-09-13)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * dependency resolution is now aware of functions, enums and works across schemas. ([460de82](https://github.com/craigulliott/dynamic_migrations/commit/460de828be1826930bc1b185cf2a4c4e354d7dad))
9
+ * enum columns now accept an enum object ([460de82](https://github.com/craigulliott/dynamic_migrations/commit/460de828be1826930bc1b185cf2a4c4e354d7dad))
10
+ * trigger parameters is now an array of strings ([460de82](https://github.com/craigulliott/dynamic_migrations/commit/460de828be1826930bc1b185cf2a4c4e354d7dad))
11
+
3
12
  ## [3.6.7](https://github.com/craigulliott/dynamic_migrations/compare/v3.6.6...v3.6.7) (2023-09-13)
4
13
 
5
14
 
@@ -16,7 +16,7 @@ module DynamicMigrations
16
16
  end
17
17
 
18
18
  # create a postgres trigger
19
- def add_trigger table_name, name:, action_timing:, event_manipulation:, action_orientation:, function_schema_name:, function_name:, parameters: nil, action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, comment: nil
19
+ def add_trigger table_name, name:, action_timing:, event_manipulation:, action_orientation:, function_schema_name:, function_name:, parameters: [], action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, comment: nil
20
20
  unless [:insert, :delete, :update].include? event_manipulation
21
21
  raise UnexpectedEventManipulationError, event_manipulation
22
22
  end
@@ -47,13 +47,15 @@ module DynamicMigrations
47
47
  end
48
48
  temp_tables_sql = temp_tables.any? ? "REFERENCING #{temp_tables.join(" ")}" : ""
49
49
 
50
+ parameters_str = parameters.map { |p| quote(p) }.join(", ")
51
+
50
52
  # schema_name was not provided to this method, it comes from the migration class
51
53
  execute <<~SQL
52
54
  CREATE TRIGGER #{name}
53
55
  #{timing_sql} ON #{schema_name}.#{table_name} #{temp_tables_sql}
54
56
  FOR EACH #{action_orientation}
55
57
  #{condition_sql}
56
- EXECUTE FUNCTION #{function_schema_name}.#{function_name}(#{parameters});
58
+ EXECUTE FUNCTION #{function_schema_name}.#{function_name}(#{parameters_str});
57
59
  SQL
58
60
 
59
61
  if comment.is_a? String
@@ -62,27 +64,27 @@ module DynamicMigrations
62
64
  end
63
65
 
64
66
  # wrappers for add_trigger which provide more friendly syntax
65
- def before_insert table_name, name:, function_schema_name:, function_name:, parameters: nil, action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, comment: nil
67
+ def before_insert table_name, name:, function_schema_name:, function_name:, parameters: [], action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, comment: nil
66
68
  add_trigger table_name, name: name, action_timing: :before, event_manipulation: :insert, action_orientation: :row, function_schema_name: function_schema_name, function_name: function_name, parameters: parameters, action_condition: action_condition, action_reference_old_table: action_reference_old_table, action_reference_new_table: action_reference_new_table, comment: comment
67
69
  end
68
70
 
69
- def before_update table_name, name:, function_schema_name:, function_name:, parameters: nil, action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, comment: nil
71
+ def before_update table_name, name:, function_schema_name:, function_name:, parameters: [], action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, comment: nil
70
72
  add_trigger table_name, name: name, action_timing: :before, event_manipulation: :update, action_orientation: :row, function_schema_name: function_schema_name, function_name: function_name, parameters: parameters, action_condition: action_condition, action_reference_old_table: action_reference_old_table, action_reference_new_table: action_reference_new_table, comment: comment
71
73
  end
72
74
 
73
- def before_delete table_name, name:, function_schema_name:, function_name:, parameters: nil, action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, comment: nil
75
+ def before_delete table_name, name:, function_schema_name:, function_name:, parameters: [], action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, comment: nil
74
76
  add_trigger table_name, name: name, action_timing: :before, event_manipulation: :delete, action_orientation: :row, function_schema_name: function_schema_name, function_name: function_name, parameters: parameters, action_condition: action_condition, action_reference_old_table: action_reference_old_table, action_reference_new_table: action_reference_new_table, comment: comment
75
77
  end
76
78
 
77
- def after_insert table_name, name:, function_schema_name:, function_name:, parameters: nil, action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, comment: nil
79
+ def after_insert table_name, name:, function_schema_name:, function_name:, parameters: [], action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, comment: nil
78
80
  add_trigger table_name, name: name, action_timing: :after, event_manipulation: :insert, action_orientation: :row, function_schema_name: function_schema_name, function_name: function_name, parameters: parameters, action_condition: action_condition, action_reference_old_table: action_reference_old_table, action_reference_new_table: action_reference_new_table, comment: comment
79
81
  end
80
82
 
81
- def after_update table_name, name:, function_schema_name:, function_name:, parameters: nil, action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, comment: nil
83
+ def after_update table_name, name:, function_schema_name:, function_name:, parameters: [], action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, comment: nil
82
84
  add_trigger table_name, name: name, action_timing: :after, event_manipulation: :update, action_orientation: :row, function_schema_name: function_schema_name, function_name: function_name, parameters: parameters, action_condition: action_condition, action_reference_old_table: action_reference_old_table, action_reference_new_table: action_reference_new_table, comment: comment
83
85
  end
84
86
 
85
- def after_delete table_name, name:, function_schema_name:, function_name:, parameters: nil, action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, comment: nil
87
+ def after_delete table_name, name:, function_schema_name:, function_name:, parameters: [], action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, comment: nil
86
88
  add_trigger table_name, name: name, action_timing: :after, event_manipulation: :delete, action_orientation: :row, function_schema_name: function_schema_name, function_name: function_name, parameters: parameters, action_condition: action_condition, action_reference_old_table: action_reference_old_table, action_reference_new_table: action_reference_new_table, comment: comment
87
89
  end
88
90
 
@@ -48,6 +48,8 @@ module DynamicMigrations
48
48
  add_fragment schema: column.table.schema,
49
49
  table: column.table,
50
50
  migration_method: :add_column,
51
+ # this will be nil if the column is not an enum
52
+ dependent_enum: column.enum,
51
53
  object: column,
52
54
  code_comment: code_comment,
53
55
  migration: <<~RUBY
@@ -77,6 +79,8 @@ module DynamicMigrations
77
79
  add_fragment schema: column.table.schema,
78
80
  table: column.table,
79
81
  migration_method: :change_column,
82
+ # this will be nil if the column is not an enum
83
+ dependent_enum: column.enum,
80
84
  object: column,
81
85
  code_comment: code_comment,
82
86
  migration: <<~RUBY
@@ -8,6 +8,8 @@ module DynamicMigrations
8
8
  attr_reader :object_name
9
9
  attr_reader :dependency_schema_name
10
10
  attr_reader :dependency_table_name
11
+ attr_reader :dependency_function_name
12
+ attr_reader :dependency_enum_name
11
13
 
12
14
  def initialize schema_name, table_name, migration_method, object_name, code_comment, content
13
15
  @schema_name = schema_name
@@ -38,7 +40,7 @@ module DynamicMigrations
38
40
 
39
41
  # If a table dependency has been set, then returns a hash with the schema_name
40
42
  # and table_name, otherwise returns nil.
41
- def dependency
43
+ def table_dependency
42
44
  if dependency_schema_name && dependency_table_name
43
45
  {
44
46
  schema_name: dependency_schema_name,
@@ -47,18 +49,77 @@ module DynamicMigrations
47
49
  end
48
50
  end
49
51
 
52
+ # If a function dependency has been set, then returns a hash with the schema_name
53
+ # and function_name, otherwise returns nil.
54
+ def function_dependency
55
+ if dependency_schema_name && dependency_function_name
56
+ {
57
+ schema_name: dependency_schema_name,
58
+ function_name: dependency_function_name
59
+ }
60
+ end
61
+ end
62
+
63
+ # If an enum dependency has been set, then returns a hash with the schema_name
64
+ # and enum_name, otherwise returns nil.
65
+ def enum_dependency
66
+ if dependency_schema_name && dependency_enum_name
67
+ {
68
+ schema_name: dependency_schema_name,
69
+ enum_name: dependency_enum_name
70
+ }
71
+ end
72
+ end
73
+
50
74
  # returns true if the fragment has a table dependency, and the dependency matches
51
75
  # the provided schema_name and table_name, otherwise returns false.
52
- def is_dependent_on? schema_name, table_name
76
+ def is_dependent_on_table? schema_name, table_name
53
77
  dependency_schema_name && schema_name == dependency_schema_name && table_name == dependency_table_name || false
54
78
  end
55
79
 
56
- # Set the table table dependency for this fragment. Takes a schema name and
80
+ # Set a table dependency for this fragment. Takes a schema name and
57
81
  # table name
58
82
  def set_dependent_table schema_name, table_name
83
+ if @dependency_schema_name
84
+ raise "Cannot set a table dependency for a fragment that already has a #{dependency_type} dependency"
85
+ end
59
86
  @dependency_schema_name = schema_name
60
87
  @dependency_table_name = table_name
61
88
  end
89
+
90
+ # Set a function dependency for this fragment. Takes a schema name and
91
+ # function name
92
+ def set_dependent_function schema_name, function_name
93
+ if @dependency_schema_name
94
+ raise "Cannot set a table dependency for a fragment that already has a #{dependency_type} dependency"
95
+ end
96
+ @dependency_schema_name = schema_name
97
+ @dependency_function_name = function_name
98
+ end
99
+
100
+ # Set an enum dependency for this fragment. Takes a schema name and
101
+ # enum name
102
+ def set_dependent_enum schema_name, enum_name
103
+ if @dependency_schema_name
104
+ raise "Cannot set a table dependency for a fragment that already has a #{dependency_type} dependency"
105
+ end
106
+ @dependency_schema_name = schema_name
107
+ @dependency_enum_name = enum_name
108
+ end
109
+
110
+ private
111
+
112
+ # returns a symbol representing the type of dependency this fragment has,
113
+ # or nil if there is no dependency
114
+ def dependency_type
115
+ if dependency_function_name
116
+ :function
117
+ elsif dependency_enum_name
118
+ :enum
119
+ elsif dependency_table_name
120
+ :table
121
+ end
122
+ end
62
123
  end
63
124
  end
64
125
  end
@@ -96,18 +96,34 @@ module DynamicMigrations
96
96
  # Return an array of table dependencies for this migration, this array comes from
97
97
  # combining any table dependencies from each fragment.
98
98
  # Will raise an error if no fragments have been provided.
99
- def dependencies
99
+ def table_dependencies
100
100
  raise NoFragmentsError if fragments.empty?
101
- @fragments.map(&:dependency).compact
101
+ @fragments.map(&:table_dependency).compact
102
+ end
103
+
104
+ # Return an array of function dependencies for this migration, this array comes from
105
+ # combining any function dependencies from each fragment.
106
+ # Will raise an error if no fragments have been provided.
107
+ def function_dependencies
108
+ raise NoFragmentsError if fragments.empty?
109
+ @fragments.map(&:function_dependency).compact
110
+ end
111
+
112
+ # Return an array of enum dependencies for this migration, this array comes from
113
+ # combining any enum dependencies from each fragment.
114
+ # Will raise an error if no fragments have been provided.
115
+ def enum_dependencies
116
+ raise NoFragmentsError if fragments.empty?
117
+ @fragments.map(&:enum_dependency).compact
102
118
  end
103
119
 
104
120
  # removes and returns any fragments which have a dependency on the table with the
105
121
  # provided schema_name and table_name, this is used for extracting fragments which
106
122
  # cause circular dependencies so they can be placed into their own migrations
107
123
  def extract_fragments_with_dependency schema_name, table_name
108
- results = @fragments.filter { |f| f.is_dependent_on? schema_name, table_name }
124
+ results = @fragments.filter { |f| f.is_dependent_on_table? schema_name, table_name }
109
125
  # remove any of these from the internal array of fragments
110
- @fragments.filter! { |f| !f.is_dependent_on?(schema_name, table_name) }
126
+ @fragments.filter! { |f| !f.is_dependent_on_table?(schema_name, table_name) }
111
127
  # return the results
112
128
  results
113
129
  end
@@ -13,19 +13,35 @@ module DynamicMigrations
13
13
  raise NoTableCommentError, "Refusing to generate create_table migration, no description was provided for `#{table.schema.name}`.`#{table.name}`"
14
14
  end
15
15
 
16
- add_fragment schema: table.schema,
16
+ # We only add the columns that are not enums from within the add_table block, this
17
+ # is because columns that are enums require those enums to be created first and we
18
+ # want to create those as seperate fragments which have the correct dependency metadata
19
+ columns_without_enums = table.columns.reject(&:enum)
20
+ columns_with_enums = table.columns.select(&:enum)
21
+
22
+ fragments = []
23
+ fragments << add_fragment(schema: table.schema,
17
24
  table: table,
18
25
  migration_method: :create_table,
19
26
  object: table,
20
27
  code_comment: code_comment,
21
28
  migration: <<~RUBY
22
29
  table_comment = <<~COMMENT
23
- #{indent table.description}
30
+ #{indent table.description || ""}
24
31
  COMMENT
25
32
  create_table :#{table.name}, #{table_options table} do |t|
26
- #{indent table_columns(table.columns)}
33
+ #{indent table_columns(columns_without_enums)}
27
34
  end
28
35
  RUBY
36
+ )
37
+
38
+ # seperately add the columns that are enums (so dependency managment works correctly)
39
+ fragments += columns_with_enums.map do |column|
40
+ add_column column
41
+ end
42
+
43
+ # return all the fragments (we do this with all generators so e can more easily test the methods)
44
+ fragments
29
45
  end
30
46
 
31
47
  def drop_table table, code_comment = nil
@@ -61,8 +61,8 @@ module DynamicMigrations
61
61
  options[:action_condition] = "\"#{trigger.action_condition}\""
62
62
  end
63
63
 
64
- unless trigger.parameters.nil?
65
- options[:parameters] = "\"#{trigger.parameters}\""
64
+ unless trigger.parameters.empty?
65
+ options[:parameters] = "[\"#{trigger.parameters.join('", "')}\"]"
66
66
  end
67
67
 
68
68
  unless trigger.action_reference_old_table.nil?
@@ -88,6 +88,8 @@ module DynamicMigrations
88
88
  migration_method: :add_trigger,
89
89
  object: trigger,
90
90
  code_comment: code_comment,
91
+ dependent_function: trigger.function,
92
+ # also need dependent_enum
91
93
  migration: <<~RUBY
92
94
  #{method_name} :#{trigger.table.name}, #{options_syntax}
93
95
  RUBY
@@ -41,9 +41,10 @@ module DynamicMigrations
41
41
  # a hash to hold the generated migrations orgnized by their schema and table
42
42
  # this makes it easier and faster to work with them within this method
43
43
  database_migrations = {}
44
- # the database_specific_migration is for migrations which dont belong
45
- # within a specific schema
46
- database_specific_migration = DatabaseMigration.new
44
+ # the database_specific_migrations are for migrations which dont belong
45
+ # within a specific schema, they are important enough that we have a
46
+ # dedicated migration for each one
47
+ database_specific_migrations = []
47
48
 
48
49
  # Process each fragment, and organize them into migrations. We create a shared
49
50
  # Migration for each table, and a single shared migration for any schema migrations
@@ -75,7 +76,9 @@ module DynamicMigrations
75
76
  # migrations with no schema or table, are added to a database
76
77
  # migration (these are really just creating/dropping schemas and extensions)
77
78
  elsif schema_name.nil? && table_name.nil?
78
- database_specific_migration.add_fragment fragment
79
+ database_specific_migration = DatabaseMigration.new
80
+ database_specific_migration.add_fragment(fragment)
81
+ database_specific_migrations << database_specific_migration
79
82
 
80
83
  else
81
84
  raise UnprocessableFragmentError
@@ -94,7 +97,7 @@ module DynamicMigrations
94
97
  # never have dependencies
95
98
  schema_migrations[:table_migrations].values.each do |table_migration|
96
99
  # recursively test each table migration for circular dependencies
97
- table_migration.dependencies.each do |dependency|
100
+ table_migration.table_dependencies.each do |dependency|
98
101
  if circular_dependency? table_migration.schema_name, table_migration.table_name, dependency, all_table_migrations
99
102
  # remove the fragment which is causing the circular dependency
100
103
  removed_fragments = table_migration.extract_fragments_with_dependency dependency[:schema_name], dependency[:table_name]
@@ -132,10 +135,10 @@ module DynamicMigrations
132
135
  # if there is a schema migration, then it should always come first
133
136
  # so make the table migration depend on it
134
137
  deps << schema_migrations[:schema_migration] if schema_migrations[:schema_migration]
135
- # if the table migration has any dependencies, then add them
136
- table_migration.dependencies.each do |dependency|
138
+ # if the table migration has any dependencies on other tables, then add them
139
+ table_migration.table_dependencies.each do |dependency|
137
140
  # find the migration which matches the dependency
138
- dependent_migration = schema_migrations[:table_migrations][dependency[:table_name]]
141
+ dependent_migration = database_migrations[dependency[:schema_name]] && database_migrations[dependency[:schema_name]][:table_migrations][dependency[:table_name]]
139
142
  # if the table migration is not found, then it's safe to assume the table was created
140
143
  # by an earlier set of migrations
141
144
  unless dependent_migration.nil?
@@ -143,6 +146,14 @@ module DynamicMigrations
143
146
  deps << dependent_migration
144
147
  end
145
148
  end
149
+ # if the table migration has any dependencies on functions or enums, then add them
150
+ (table_migration.function_dependencies + table_migration.enum_dependencies).each do |dependency|
151
+ # functions are always added to a schema specific migration, if it does not exist then
152
+ # we can assume the function was added in a previous set of migrations
153
+ if (dependencies_schema_migration = database_migrations[dependency[:schema_name]] && database_migrations[dependency[:schema_name]][:schema_migration])
154
+ deps << dependencies_schema_migration
155
+ end
156
+ end
146
157
  end
147
158
  # add each additional migration, and its dependencies
148
159
  schema_migrations[:additional_migrations].each do |additional_migration|
@@ -157,16 +168,24 @@ module DynamicMigrations
157
168
  unless table_migration.nil?
158
169
  deps << table_migration
159
170
  end
160
- # if the additional_migration has any dependencies, then add them too
161
- additional_migration.dependencies.each do |dependency|
171
+ # if the additional_migration has any dependencies on other tables, then add them too
172
+ additional_migration.table_dependencies.each do |dependency|
162
173
  # find the table migration which matches the dependency
163
- dependent_migration = schema_migrations[:table_migrations][dependency[:table_name]]
174
+ dependent_migration = database_migrations[dependency[:schema_name]] && database_migrations[dependency[:schema_name]][:table_migrations][dependency[:table_name]]
164
175
  # if the table migration is not found, then it's safe to assume the table was created
165
176
  # by an earlier set of migrations
166
177
  unless dependent_migration.nil?
167
178
  deps << dependent_migration
168
179
  end
169
180
  end
181
+ # if the table migration has any dependencies on functions or enums, then add them
182
+ (table_migration.function_dependencies + table_migration.enum_dependencies).each do |dependency|
183
+ # functions are always added to a schema specific migration, if it does not exist then
184
+ # we can assume the function was added in a previous set of migrations
185
+ if (dependencies_schema_migration = database_migrations[dependency[:schema_name]] && database_migrations[dependency[:schema_name]][:schema_migration])
186
+ deps << dependencies_schema_migration
187
+ end
188
+ end
170
189
  end
171
190
  end
172
191
 
@@ -174,9 +193,9 @@ module DynamicMigrations
174
193
  # the order is determined by their dependencies
175
194
  final_migrations = dependency_sorter.tsort
176
195
 
177
- # if any database only migrations exist, then add them to the from of the array here
178
- if database_specific_migration.fragments.any?
179
- final_migrations.unshift database_specific_migration
196
+ # if any database only migrations exist, then add them to the front of the array here
197
+ if database_specific_migrations.any?
198
+ final_migrations = database_specific_migrations + final_migrations
180
199
  end
181
200
 
182
201
  # return the final migrations in the expected format
@@ -200,7 +219,7 @@ module DynamicMigrations
200
219
  dependent_migrations = all_table_migrations.filter { |m| m.schema_name == dependency[:schema_name] && m.table_name == dependency[:table_name] }
201
220
  # recursively call this method for all the dependencies for these migrations
202
221
  dependent_migrations.each do |dependent_migration|
203
- dependent_migration.dependencies.each do |next_dependency|
222
+ dependent_migration.table_dependencies.each do |next_dependency|
204
223
  # if we find a dependency which matches the original schema and table name then we have a circular dependency
205
224
  if circular_dependency?(schema_name, table_name, next_dependency, all_table_migrations)
206
225
  return true
@@ -221,15 +240,26 @@ module DynamicMigrations
221
240
  @dep[node].each(&block)
222
241
  end
223
242
 
224
- def add_fragment migration_method:, object:, migration:, schema: nil, table: nil, code_comment: nil, dependent_table: nil
243
+ # This method is called from within the various modules which are included to this class.
244
+ # It locally stores all the fragments which will later be organized into different migrations.
245
+ def add_fragment migration_method:, object:, migration:, schema: nil, table: nil, code_comment: nil, dependent_table: nil, dependent_function: nil, dependent_enum: nil
225
246
  # Remove any empty lines and whitespace from the beginning or the end of the migration and then
226
247
  # strip any empty lines witin the migration (remove the whitespace from them, not delete them).
227
248
  final_migration = strip_empty_lines(migration).strip
228
249
  fragment = Fragment.new(schema&.name, table&.name, migration_method, object.name, code_comment, final_migration)
250
+
229
251
  if dependent_table
230
252
  fragment.set_dependent_table dependent_table.schema.name, dependent_table.name
231
253
  end
232
254
 
255
+ if dependent_function
256
+ fragment.set_dependent_function dependent_function.schema.name, dependent_function.name
257
+ end
258
+
259
+ if dependent_enum
260
+ fragment.set_dependent_enum dependent_enum.schema.name, dependent_enum.name
261
+ end
262
+
233
263
  # add this fragment to the list
234
264
  @fragments << fragment
235
265
 
@@ -15,8 +15,24 @@ module DynamicMigrations
15
15
  # tables and columns
16
16
  def recursively_load_database_structure
17
17
  validations = fetch_validations
18
- fetch_structure.each do |schema_name, schema_definition|
19
- schema = add_loaded_schema schema_name
18
+
19
+ structure = fetch_structure
20
+
21
+ # add any schemas
22
+ structure.each do |schema_name, schema_definition|
23
+ add_loaded_schema schema_name
24
+ end
25
+
26
+ # add any enums (required for adding columns below)
27
+ fetch_enums.each do |schema_name, schema_definition|
28
+ schema_definition.each do |enum_name, enum_definition|
29
+ loaded_schema(schema_name).add_enum enum_name, enum_definition[:values], description: enum_definition[:description]
30
+ end
31
+ end
32
+
33
+ structure.each do |schema_name, schema_definition|
34
+ # the schema was already added above
35
+ schema = loaded_schema schema_name
20
36
  schema_validations = validations[schema_name]
21
37
 
22
38
  schema_definition[:tables].each do |table_name, table_definition|
@@ -25,11 +41,19 @@ module DynamicMigrations
25
41
 
26
42
  # add each table column
27
43
  table_definition[:columns].each do |column_name, column_definition|
44
+ if column_definition[:is_enum]
45
+ enum_schema, enum_name = column_definition[:data_type].to_s.split(".")
46
+ enum = table.schema.database.loaded_schema(enum_schema.to_sym).enum(enum_name.to_sym)
47
+ else
48
+ enum = nil
49
+ end
50
+
28
51
  table.add_column column_name, column_definition[:data_type],
29
52
  null: column_definition[:null],
30
53
  default: column_definition[:default],
31
54
  description: column_definition[:description],
32
- interval_type: column_definition[:interval_type]
55
+ interval_type: column_definition[:interval_type],
56
+ enum: enum
33
57
  end
34
58
 
35
59
  # add any validations
@@ -44,13 +68,6 @@ module DynamicMigrations
44
68
  add_loaded_extension extension_name
45
69
  end
46
70
 
47
- # add any enums
48
- fetch_enums.each do |schema_name, schema_definition|
49
- schema_definition.each do |enum_name, enum_definition|
50
- loaded_schema(schema_name).add_enum enum_name, enum_definition[:values], description: enum_definition[:description]
51
- end
52
- end
53
-
54
71
  # now that the structure has been loaded, we can add keys (foreign
55
72
  # keys need to be added last, because they can depend on tables from
56
73
  # different schemas)
@@ -11,6 +11,9 @@ module DynamicMigrations
11
11
  class ExpectedTableError < StandardError
12
12
  end
13
13
 
14
+ class UnexpectedEnumError < StandardError
15
+ end
16
+
14
17
  attr_reader :table
15
18
  attr_reader :name
16
19
  attr_reader :data_type
@@ -18,9 +21,10 @@ module DynamicMigrations
18
21
  attr_reader :null
19
22
  attr_reader :default
20
23
  attr_reader :interval_type
24
+ attr_reader :enum
21
25
 
22
26
  # initialize a new object to represent a column in a postgres table
23
- def initialize source, table, name, data_type, null: true, default: nil, description: nil, interval_type: nil
27
+ def initialize source, table, name, data_type, null: true, default: nil, description: nil, interval_type: nil, enum: nil
24
28
  super source
25
29
  raise ExpectedTableError, table unless table.is_a? Table
26
30
  @table = table
@@ -28,7 +32,6 @@ module DynamicMigrations
28
32
  raise ExpectedSymbolError, name unless name.is_a? Symbol
29
33
  @name = name
30
34
 
31
- @data_type = data_type
32
35
  raise ExpectedSymbolError, data_type unless data_type.is_a? Symbol
33
36
  @data_type = data_type
34
37
 
@@ -42,6 +45,16 @@ module DynamicMigrations
42
45
  end
43
46
 
44
47
  @interval_type = interval_type
48
+
49
+ if enum
50
+ unless enum.is_a? Enum
51
+ raise UnexpectedEnumError, "#{enum} is not a valid enum"
52
+ end
53
+ unless @data_type == enum.name || @data_type == "#{enum.name}[]"
54
+ raise UnexpectedEnumError, "enum `#{enum.name}` does not match this column's data type `#{@data_type}`"
55
+ end
56
+ @enum = enum
57
+ end
45
58
  end
46
59
 
47
60
  # return true if this column has a description, otherwise false
@@ -92,11 +92,10 @@ module DynamicMigrations
92
92
  end
93
93
  @action_condition = action_condition&.strip
94
94
 
95
- is_comma_sperated_list_of_strings = (parameters.is_a?(String) && parameters[/\A'[\w\d_ -]+'(, ?'[\w\d_ -]+')*\z/])
96
- unless parameters.nil? || is_comma_sperated_list_of_strings
97
- raise UnexpectedParametersError, "unexpected parameters `#{parameters}`, currently only a comma seeparated list of strings is supported"
95
+ unless parameters.is_a?(Array) && parameters.all? { |p| p.is_a? String }
96
+ raise UnexpectedParametersError, "unexpected parameters `#{parameters}`, currently only an array of strings is supported"
98
97
  end
99
- @parameters = parameters&.strip
98
+ @parameters = parameters
100
99
 
101
100
  unless [:row, :statement].include? action_orientation
102
101
  raise UnexpectedActionOrientationError, action_orientation
@@ -167,11 +166,12 @@ module DynamicMigrations
167
166
  @action_condition = new_action_condition&.strip
168
167
  end
169
168
 
170
- def parameters= new_parameters
171
- unless new_parameters.nil? || new_parameters.is_a?(String)
172
- raise ExpectedStringError, new_parameters
169
+ def add_parameter new_parameter
170
+ unless new_parameter.is_a? String
171
+ raise UnexpectedParametersError, "unexpected parameter `#{new_parameter}`, can only add strings to the list of parameters"
173
172
  end
174
- @parameters = new_parameters&.strip
173
+
174
+ @parameters << new_parameter
175
175
  end
176
176
 
177
177
  # return true if this has a description, otherwise false
@@ -33,6 +33,13 @@ module DynamicMigrations
33
33
  AND attnum = columns.ordinal_position
34
34
  )
35
35
  END AS data_type,
36
+ -- is this an emum
37
+ EXISTS (
38
+ SELECT 1
39
+ FROM pg_type typ
40
+ INNER JOIN pg_enum enu ON typ.oid = enu.enumtypid
41
+ WHERE typ.typname = columns.udt_name
42
+ ) AS is_enum,
36
43
  -- If data_type identifies an interval type, this column contains
37
44
  -- the specification which fields the intervals include for this
38
45
  -- column, e.g., YEAR TO MONTH, DAY TO SECOND, etc. If no field
@@ -93,6 +100,7 @@ module DynamicMigrations
93
100
 
94
101
  column[:data_type] = row["data_type"].to_sym
95
102
  column[:null] = row["is_nullable"] == "YES"
103
+ column[:is_enum] = row["is_enum"] == "TRUE"
96
104
  column[:default] = row["column_default"]
97
105
  column[:description] = row["column_description"]
98
106
  column[:interval_type] = row["interval_type"].nil? ? nil : row["interval_type"].to_sym
@@ -102,26 +110,6 @@ module DynamicMigrations
102
110
  schemas
103
111
  end
104
112
 
105
- # recursively process the database and build all the schemas,
106
- # tables and columns
107
- def recursively_load_database_structure
108
- fetch_structure.each do |schema_name, schema_definition|
109
- schema = add_loaded_schema schema_name
110
-
111
- schema_definition[:tables].each do |table_name, table_definition|
112
- table = schema.add_table table_name, table_definition[:description]
113
-
114
- table_definition[:columns].each do |column_name, column_definition|
115
- table.add_column column_name, column_definition[:data_type],
116
- null: column_definition[:null],
117
- default: column_definition[:default],
118
- description: column_definition[:description],
119
- interval_type: column_definition[:interval_type]
120
- end
121
- end
122
- end
123
- end
124
-
125
113
  # returns a list of the schema names in this database
126
114
  def fetch_schema_names
127
115
  rows = connection.exec(<<~SQL)
@@ -38,7 +38,7 @@ module DynamicMigrations
38
38
  SUBSTRING(
39
39
  pg_get_triggerdef(t.oid)
40
40
  FROM
41
- '\\(([\d\w_''-]+)\\)$'
41
+ '\\(([^(]+)\\)$'
42
42
  ) AS parameters,
43
43
  p_n.nspname AS function_schema,
44
44
  p.proname AS function_name,
@@ -96,6 +96,10 @@ module DynamicMigrations
96
96
  raise EventTriggerProcedureSchemaMismatchError, "Expected trigger, procedure and event_object to be in the same schema for trigger '#{trigger_name}'"
97
97
  end
98
98
 
99
+ # turn the parameters into an array of strings
100
+ # the format looks a little like this: "'hi', 'there', 'hmmm'"
101
+ parameters = row["parameters"]&.delete("'")&.split(",")&.map(&:strip) || []
102
+
99
103
  table[trigger_name] = {
100
104
  trigger_schema: row["trigger_schema"].to_sym,
101
105
  event_manipulation: row["event_manipulation"].to_sym,
@@ -104,7 +108,7 @@ module DynamicMigrations
104
108
  function_schema: row["function_schema"].to_sym,
105
109
  function_name: row["function_name"].to_sym,
106
110
  function_definition: row["function_definition"],
107
- parameters: row["parameters"],
111
+ parameters: parameters,
108
112
  action_orientation: row["action_orientation"].to_sym,
109
113
  action_timing: row["action_timing"].to_sym,
110
114
  # `action_reference_old_table` and `action_reference_new_table` can be null
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DynamicMigrations
4
- VERSION = "3.6.7"
4
+ VERSION = "3.6.8"
5
5
  end
@@ -3,17 +3,17 @@ module DynamicMigrations
3
3
  module ActiveRecord
4
4
  module Migrators
5
5
  module Trigger
6
- def add_trigger: (Symbol table_name, name: Symbol, action_timing: Symbol, event_manipulation: Symbol, action_orientation: Symbol, function_schema_name: Symbol, function_name: Symbol, ?parameters: String?, ?action_condition: String?, ?action_reference_old_table: Symbol?, ?action_reference_new_table: Symbol?, ?comment: String?) -> void
6
+ def add_trigger: (Symbol table_name, name: Symbol, action_timing: Symbol, event_manipulation: Symbol, action_orientation: Symbol, function_schema_name: Symbol, function_name: Symbol, ?parameters: Array[String], ?action_condition: String?, ?action_reference_old_table: Symbol?, ?action_reference_new_table: Symbol?, ?comment: String?) -> void
7
7
  def remove_trigger: (Symbol table_name, Symbol trigger_name) -> void
8
8
  def set_trigger_comment: (Symbol table_name, Symbol trigger_name, String comment) -> void
9
9
  def remove_trigger_comment: (Symbol table_name, Symbol trigger_name) -> void
10
10
 
11
- def before_insert: (Symbol table_name, name: Symbol, function_schema_name: Symbol, function_name: Symbol, ?parameters: String?, ?action_condition: String?, ?action_reference_old_table: Symbol?, ?action_reference_new_table: Symbol?, ?comment: String?) -> void
12
- def before_update: (Symbol table_name, name: Symbol, function_schema_name: Symbol, function_name: Symbol, ?parameters: String?, ?action_condition: String?, ?action_reference_old_table: Symbol?, ?action_reference_new_table: Symbol?, ?comment: String?) -> void
13
- def before_delete: (Symbol table_name, name: Symbol, function_schema_name: Symbol, function_name: Symbol, ?parameters: String?, ?action_condition: String?, ?action_reference_old_table: Symbol?, ?action_reference_new_table: Symbol?, ?comment: String?) -> void
14
- def after_insert: (Symbol table_name, name: Symbol, function_schema_name: Symbol, function_name: Symbol, ?parameters: String?, ?action_condition: String?, ?action_reference_old_table: Symbol?, ?action_reference_new_table: Symbol?, ?comment: String?) -> void
15
- def after_update: (Symbol table_name, name: Symbol, function_schema_name: Symbol, function_name: Symbol, ?parameters: String?, ?action_condition: String?, ?action_reference_old_table: Symbol?, ?action_reference_new_table: Symbol?, ?comment: String?) -> void
16
- def after_delete: (Symbol table_name, name: Symbol, function_schema_name: Symbol, function_name: Symbol, ?parameters: String?, ?action_condition: String?, ?action_reference_old_table: Symbol?, ?action_reference_new_table: Symbol?, ?comment: String?) -> void
11
+ def before_insert: (Symbol table_name, name: Symbol, function_schema_name: Symbol, function_name: Symbol, ?parameters: Array[String], ?action_condition: String?, ?action_reference_old_table: Symbol?, ?action_reference_new_table: Symbol?, ?comment: String?) -> void
12
+ def before_update: (Symbol table_name, name: Symbol, function_schema_name: Symbol, function_name: Symbol, ?parameters: Array[String], ?action_condition: String?, ?action_reference_old_table: Symbol?, ?action_reference_new_table: Symbol?, ?comment: String?) -> void
13
+ def before_delete: (Symbol table_name, name: Symbol, function_schema_name: Symbol, function_name: Symbol, ?parameters: Array[String], ?action_condition: String?, ?action_reference_old_table: Symbol?, ?action_reference_new_table: Symbol?, ?comment: String?) -> void
14
+ def after_insert: (Symbol table_name, name: Symbol, function_schema_name: Symbol, function_name: Symbol, ?parameters: Array[String], ?action_condition: String?, ?action_reference_old_table: Symbol?, ?action_reference_new_table: Symbol?, ?comment: String?) -> void
15
+ def after_update: (Symbol table_name, name: Symbol, function_schema_name: Symbol, function_name: Symbol, ?parameters: Array[String], ?action_condition: String?, ?action_reference_old_table: Symbol?, ?action_reference_new_table: Symbol?, ?comment: String?) -> void
16
+ def after_delete: (Symbol table_name, name: Symbol, function_schema_name: Symbol, function_name: Symbol, ?parameters: Array[String], ?action_condition: String?, ?action_reference_old_table: Symbol?, ?action_reference_new_table: Symbol?, ?comment: String?) -> void
17
17
 
18
18
  # stubbing these out, as they are available on the module which includes this module
19
19
  def execute: (String sql) -> void
@@ -12,7 +12,7 @@ module DynamicMigrations
12
12
  def remove_column_comment: (Postgres::Server::Database::Schema::Table::Column column, ?String? code_comment) -> Fragment
13
13
 
14
14
  # these come from the generator object (which this module is included into)
15
- def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?) -> untyped
15
+ def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?, ?dependent_function: Server::Database::Schema::Function?, ?dependent_enum: Server::Database::Schema::Enum?) -> Fragment
16
16
 
17
17
  def indent: (String migration, ?Integer levels) -> String
18
18
 
@@ -11,7 +11,7 @@ module DynamicMigrations
11
11
  def set_enum_comment: (Server::Database::Schema::Enum enum, ?String? code_comment) -> Fragment
12
12
  def remove_enum_comment: (Server::Database::Schema::Enum enum, ?String? code_comment) -> Fragment
13
13
  # these come from the generator object (which this module is included into)
14
- def add_fragment: (schema: Server::Database::Schema, migration_method: Symbol, object: Server::Database::Schema::Enum enum, migration: String, ?table: nil | Server::Database::Schema::Table, ?code_comment: String?, ?dependent_table: nil | Server::Database::Schema::Table) -> Fragment
14
+ def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?, ?dependent_function: Server::Database::Schema::Function?, ?dependent_enum: Server::Database::Schema::Enum?) -> Fragment
15
15
  def indent: (String migration, ?Integer levels) -> String
16
16
 
17
17
  class UnremovableEnumValuesError < StandardError
@@ -9,7 +9,7 @@ module DynamicMigrations
9
9
  def disable_extension: (Symbol extension_name, ?String? code_comment) -> Fragment
10
10
 
11
11
  # these come from the generator object (which this module is included into)
12
- def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?) -> untyped
12
+ def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?, ?dependent_function: Server::Database::Schema::Function?, ?dependent_enum: Server::Database::Schema::Enum?) -> Fragment
13
13
  end
14
14
  end
15
15
  end
@@ -12,7 +12,7 @@ module DynamicMigrations
12
12
  def remove_foreign_key_constraint_comment: (Postgres::Server::Database::Schema::Table::ForeignKeyConstraint foreign_key_constraint, ?String? code_comment) -> Fragment
13
13
 
14
14
  # these come from the generator object (which this module is included into)
15
- def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?) -> untyped
15
+ def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?, ?dependent_function: Server::Database::Schema::Function?, ?dependent_enum: Server::Database::Schema::Enum?) -> Fragment
16
16
 
17
17
  def indent: (String migration, ?Integer levels) -> String
18
18
  end
@@ -19,13 +19,24 @@ module DynamicMigrations
19
19
  # dependecy on a table is optional
20
20
  attr_reader dependency_schema_name: Symbol?
21
21
  attr_reader dependency_table_name: Symbol?
22
+ attr_reader dependency_function_name: Symbol?
23
+ attr_reader dependency_enum_name: Symbol?
22
24
 
23
25
  def initialize: (Symbol? schema_name, Symbol? table_name, Symbol migration_method, Symbol object_name, String? code_comment, String content) -> void
24
26
  def to_s: -> String
25
27
  def has_code_comment?: -> bool
26
- def dependency: -> ({schema_name: Symbol, table_name: Symbol} | nil)
27
- def is_dependent_on?: (Symbol schema_name, Symbol table_name) -> bool
28
+
29
+ def table_dependency: -> ({schema_name: Symbol, table_name: Symbol} | nil)
30
+ def function_dependency: -> ({schema_name: Symbol, function_name: Symbol} | nil)
31
+ def enum_dependency: -> ({schema_name: Symbol, enum_name: Symbol} | nil)
32
+
33
+ def is_dependent_on_table?: (Symbol schema_name, Symbol table_name) -> bool
34
+
28
35
  def set_dependent_table: (Symbol schema_name, Symbol table_name) -> void
36
+ def set_dependent_function: (Symbol schema_name, Symbol function_name) -> void
37
+ def set_dependent_enum: (Symbol schema_name, Symbol enum_name) -> void
38
+
39
+ def dependency_type: -> (nil | :function | :table | :enum)
29
40
  end
30
41
  end
31
42
  end
@@ -12,7 +12,7 @@ module DynamicMigrations
12
12
  def remove_function_comment: (Postgres::Server::Database::Schema::Function function, ?String? code_comment) -> Fragment
13
13
 
14
14
  # these come from the generator object (which this module is included into)
15
- def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?) -> untyped
15
+ def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?, ?dependent_function: Server::Database::Schema::Function?, ?dependent_enum: Server::Database::Schema::Enum?) -> Fragment
16
16
 
17
17
  def indent: (String migration, ?Integer levels) -> String
18
18
  end
@@ -12,7 +12,7 @@ module DynamicMigrations
12
12
  def remove_index_comment: (Postgres::Server::Database::Schema::Table::Index index, ?String? code_comment) -> Fragment
13
13
 
14
14
  # these come from the generator object (which this module is included into)
15
- def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?) -> untyped
15
+ def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?, ?dependent_function: Server::Database::Schema::Function?, ?dependent_enum: Server::Database::Schema::Enum?) -> Fragment
16
16
 
17
17
  def indent: (String migration, ?Integer levels) -> String
18
18
  end
@@ -18,8 +18,12 @@ module DynamicMigrations
18
18
  attr_reader fragments: Array[Fragment]
19
19
  def initialize: (?Symbol? schema_name, ?Symbol? table_name) -> void
20
20
  def add_fragment: (Fragment fragment) -> void
21
- def dependencies: -> Array[{schema_name: Symbol, table_name: Symbol}]
22
- def extract_fragments_with_dependency: (Symbol schema_name, Symbol table_name) -> Array[Fragment]
21
+ def table_dependencies: -> Array[{schema_name: Symbol, table_name: Symbol}]
22
+ def enum_dependencies: -> Array[{schema_name: Symbol, enum_name: Symbol}]
23
+ def function_dependencies: -> Array[{schema_name: Symbol, function_name: Symbol}]
24
+
25
+ def extract_fragments_with_table_dependency: (Symbol schema_name, Symbol table_name) -> Array[Fragment]
26
+
23
27
  def content: -> String
24
28
  def name: -> (:changes | :schema_functions | Symbol)
25
29
 
@@ -10,7 +10,7 @@ module DynamicMigrations
10
10
  def recreate_primary_key: (Postgres::Server::Database::Schema::Table::PrimaryKey original_primary_key, Postgres::Server::Database::Schema::Table::PrimaryKey updated_primary_key) -> Array[Fragment]
11
11
 
12
12
  # these come from the generator object (which this module is included into)
13
- def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?) -> untyped
13
+ def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?, ?dependent_function: Server::Database::Schema::Function?, ?dependent_enum: Server::Database::Schema::Enum?) -> Fragment
14
14
 
15
15
  def indent: (String migration, ?Integer levels) -> String
16
16
 
@@ -9,7 +9,7 @@ module DynamicMigrations
9
9
  def drop_schema: (Postgres::Server::Database::Schema schema, ?String? code_comment) -> Fragment
10
10
 
11
11
  # these come from the generator object (which this module is included into)
12
- def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?) -> untyped
12
+ def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?, ?dependent_function: Server::Database::Schema::Function?, ?dependent_enum: Server::Database::Schema::Enum?) -> Fragment
13
13
 
14
14
  end
15
15
  end
@@ -5,13 +5,14 @@ module DynamicMigrations
5
5
  module Postgres
6
6
  class Generator
7
7
  module Table
8
- def create_table: (Postgres::Server::Database::Schema::Table table, ?String? code_comment) -> Fragment
8
+ def create_table: (Postgres::Server::Database::Schema::Table table, ?String? code_comment) -> Array[Fragment]
9
9
  def drop_table: (Postgres::Server::Database::Schema::Table table, ?String? code_comment) -> Fragment
10
10
  def set_table_comment: (Postgres::Server::Database::Schema::Table table, ?String? code_comment) -> Fragment
11
11
  def remove_table_comment: (Postgres::Server::Database::Schema::Table table, ?String? code_comment) -> Fragment
12
12
 
13
13
  # these come from the generator object (which this module is included into)
14
- def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?) -> untyped
14
+ def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?, ?dependent_function: Server::Database::Schema::Function?, ?dependent_enum: Server::Database::Schema::Enum?) -> Fragment
15
+ def add_column: (Postgres::Server::Database::Schema::Table::Column column, ?String? code_comment) -> Fragment
15
16
 
16
17
  def indent: (String migration, ?Integer levels) -> String
17
18
 
@@ -16,7 +16,7 @@ module DynamicMigrations
16
16
  def remove_trigger_comment: (Postgres::Server::Database::Schema::Table::Trigger trigger, ?String? code_comment) -> Fragment
17
17
 
18
18
  # these come from the generator object (which this module is included into)
19
- def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?) -> untyped
19
+ def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?, ?dependent_function: Server::Database::Schema::Function?, ?dependent_enum: Server::Database::Schema::Enum?) -> Fragment
20
20
 
21
21
  def indent: (String migration, ?Integer levels) -> String
22
22
 
@@ -12,7 +12,7 @@ module DynamicMigrations
12
12
  def remove_unique_constraint_comment: (Postgres::Server::Database::Schema::Table::UniqueConstraint unique_constraint, ?String? code_comment) -> Fragment
13
13
 
14
14
  # these come from the generator object (which this module is included into)
15
- def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?) -> untyped
15
+ def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?, ?dependent_function: Server::Database::Schema::Function?, ?dependent_enum: Server::Database::Schema::Enum?) -> Fragment
16
16
 
17
17
  def indent: (String migration, ?Integer levels) -> String
18
18
  end
@@ -18,7 +18,7 @@ module DynamicMigrations
18
18
  def remove_validation_comment: (Postgres::Server::Database::Schema::Table::Validation validation, ?String? code_comment) -> Fragment
19
19
 
20
20
  # these come from the generator object (which this module is included into)
21
- def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?) -> untyped
21
+ def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?, ?dependent_function: Server::Database::Schema::Function?, ?dependent_enum: Server::Database::Schema::Enum?) -> Fragment
22
22
 
23
23
  def indent: (String migration, ?Integer levels) -> String
24
24
 
@@ -29,7 +29,7 @@ module DynamicMigrations
29
29
  private
30
30
  def circular_dependency?: (Symbol schema_name, Symbol table_name, {schema_name: Symbol, table_name: Symbol} dependency, Array[TableMigration] all_table_migrations) -> bool
31
31
  def supported_migration_method?: (Symbol migration_method) -> bool
32
- def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: nil | Server::Database::Schema::Table) -> Fragment
32
+ def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?, ?dependent_function: Server::Database::Schema::Function?, ?dependent_enum: Server::Database::Schema::Enum?) -> Fragment
33
33
  def indent: (String migration, ?Integer levels) -> String
34
34
  def strip_empty_lines: (String migration) -> String
35
35
  def tsort_each_node: -> Enumerator[untyped, untyped]
@@ -13,12 +13,17 @@ module DynamicMigrations
13
13
  attr_reader data_type: Symbol
14
14
  attr_reader array: bool
15
15
  attr_reader interval_type: Symbol?
16
- def initialize: (database_or_configuration source, Table table, Symbol name, Symbol data_type, ?null: bool, ?default: untyped, ?description: String?, ?interval_type: Symbol?) -> void
16
+ attr_reader enum: Enum?
17
+
18
+ def initialize: (database_or_configuration source, Table table, Symbol name, Symbol data_type, ?null: bool, ?default: untyped, ?description: String?, ?interval_type: Symbol?, ?enum: Enum?) -> void
17
19
  def has_description?: -> bool
18
20
  def array?: -> bool
19
21
 
20
22
  class ExpectedTableError < StandardError
21
23
  end
24
+
25
+ class UnexpectedEnumError < StandardError
26
+ end
22
27
  end
23
28
  end
24
29
  end
@@ -14,7 +14,7 @@ module DynamicMigrations
14
14
  attr_reader event_manipulation: Symbol
15
15
  attr_reader action_timing: Symbol
16
16
  attr_reader action_condition: String?
17
- attr_reader parameters: String?
17
+ attr_reader parameters: Array[String]
18
18
  attr_reader action_orientation: Symbol
19
19
  attr_reader function: Function
20
20
  attr_reader action_reference_old_table: Symbol?
@@ -22,7 +22,7 @@ module DynamicMigrations
22
22
  attr_reader description: String?
23
23
  attr_reader template: Symbol?
24
24
 
25
- def initialize: (database_or_configuration source, Table table, Symbol name, action_timing: Symbol, event_manipulation: Symbol, parameters: String?, action_orientation: Symbol, function: Function, ?action_order: Integer?, ?action_condition: String?, ?action_reference_old_table: Symbol?, ?action_reference_new_table: Symbol?, ?description: String?, ?template: Symbol?) -> void
25
+ def initialize: (database_or_configuration source, Table table, Symbol name, action_timing: Symbol, event_manipulation: Symbol, parameters: Array[String], action_orientation: Symbol, function: Function, ?action_order: Integer?, ?action_condition: String?, ?action_reference_old_table: Symbol?, ?action_reference_new_table: Symbol?, ?description: String?, ?template: Symbol?) -> void
26
26
  def action_order: -> Integer
27
27
  def has_description?: -> false
28
28
  def differences_descriptions: (Trigger other_trigger) -> Array[String]
@@ -14,7 +14,7 @@ module DynamicMigrations
14
14
  def has_trigger?: (untyped name) -> bool
15
15
  def triggers: -> Array[Trigger]
16
16
  def triggers_hash: -> Hash[Symbol, Trigger]
17
- def add_trigger: (Symbol name, action_timing: Symbol, event_manipulation: Symbol, parameters: String, action_orientation: Symbol, function: Function, ?action_order: Integer?, ?action_condition: String?, ?action_reference_old_table: Symbol?, ?action_reference_new_table: Symbol?, ?description: String?, ?template: Symbol?) -> Trigger
17
+ def add_trigger: (Symbol name, action_timing: Symbol, event_manipulation: Symbol, parameters: Array[String], action_orientation: Symbol, function: Function, ?action_order: Integer?, ?action_condition: String?, ?action_reference_old_table: Symbol?, ?action_reference_new_table: Symbol?, ?description: String?, ?template: Symbol?) -> Trigger
18
18
 
19
19
  # these come from the table object (which this module is included into)
20
20
  def source: -> database_or_configuration
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dynamic_migrations
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.6.7
4
+ version: 3.6.8
5
5
  platform: ruby
6
6
  authors:
7
7
  - Craig Ulliott