dynamic_migrations 3.6.7 → 3.6.9

Sign up to get free protection for your applications and to get access to all the features.
Files changed (37) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -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/enum.rb +4 -0
  12. data/lib/dynamic_migrations/postgres/server/database/schema/table/column.rb +15 -2
  13. data/lib/dynamic_migrations/postgres/server/database/schema/table/trigger.rb +8 -8
  14. data/lib/dynamic_migrations/postgres/server/database/structure_loader.rb +8 -20
  15. data/lib/dynamic_migrations/postgres/server/database/triggers_and_functions_loader.rb +6 -2
  16. data/lib/dynamic_migrations/version.rb +1 -1
  17. data/sig/dynamic_migrations/active_record/migrators/trigger.rbs +7 -7
  18. data/sig/dynamic_migrations/postgres/generator/column.rbs +1 -1
  19. data/sig/dynamic_migrations/postgres/generator/enum.rbs +1 -1
  20. data/sig/dynamic_migrations/postgres/generator/extension.rbs +1 -1
  21. data/sig/dynamic_migrations/postgres/generator/foreign_key_constraint.rbs +1 -1
  22. data/sig/dynamic_migrations/postgres/generator/fragment.rbs +13 -2
  23. data/sig/dynamic_migrations/postgres/generator/function.rbs +1 -1
  24. data/sig/dynamic_migrations/postgres/generator/index.rbs +1 -1
  25. data/sig/dynamic_migrations/postgres/generator/migration.rbs +6 -2
  26. data/sig/dynamic_migrations/postgres/generator/primary_key.rbs +1 -1
  27. data/sig/dynamic_migrations/postgres/generator/schema.rbs +1 -1
  28. data/sig/dynamic_migrations/postgres/generator/table.rbs +3 -2
  29. data/sig/dynamic_migrations/postgres/generator/trigger.rbs +1 -1
  30. data/sig/dynamic_migrations/postgres/generator/unique_constraint.rbs +1 -1
  31. data/sig/dynamic_migrations/postgres/generator/validation.rbs +1 -1
  32. data/sig/dynamic_migrations/postgres/generator.rbs +1 -1
  33. data/sig/dynamic_migrations/postgres/server/database/schema/enum.rbs +1 -0
  34. data/sig/dynamic_migrations/postgres/server/database/schema/table/column.rbs +6 -1
  35. data/sig/dynamic_migrations/postgres/server/database/schema/table/trigger.rbs +2 -2
  36. data/sig/dynamic_migrations/postgres/server/database/schema/table/triggers.rbs +1 -1
  37. 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: eda59bc82b8accf553a95dabc66fdb1d59ea68750cb4318b2ee970d62d5b679f
4
+ data.tar.gz: faaf288de33ee1a6d419be2148a4cc7ec5f76bcd05260d5419b82af7fd256f51
5
5
  SHA512:
6
- metadata.gz: 346ea3c2425e136487200f521b9669d1cd4ec3646f64113340b2bf487416b48226c68d4b32e5008dca9405f75dd7c50020edbe9caa33e4fcd2c676f61f09fbbf
7
- data.tar.gz: bfc5f568840046e813f0c04b47a54b50be0c4053ae2f8dd94cd5f59c86c42505aeb902d4a8eb85004b5aa0f37c922d25cac793d87a20f467d32bc2730f51f3fc
6
+ metadata.gz: 85bb27898ab75f4815f7d08b6c7cdd27174f7bbb850fb55d21dad082627077e175d26b87fa64aa3651d98a914e1719a81d0d72955b7b763ecb5fe2ee5e93c9a1
7
+ data.tar.gz: a2bb9765ad753949c7f8db6640ca41046f7d1e946d0ed05211cce922d1f0c8b63dc4111183d1ab556c8f4b01278f3f83b2a39fd45c49dd50f718e32e8e617bbb
data/CHANGELOG.md CHANGED
@@ -1,5 +1,21 @@
1
1
  # Changelog
2
2
 
3
+ ## [3.6.9](https://github.com/craigulliott/dynamic_migrations/compare/v3.6.8...v3.6.9) (2023-09-13)
4
+
5
+
6
+ ### Bug Fixes
7
+
8
+ * enum name as a data type should include the schema name ([7658d14](https://github.com/craigulliott/dynamic_migrations/commit/7658d1482b7e50bcce11268d8121ee59ae194fa3))
9
+
10
+ ## [3.6.8](https://github.com/craigulliott/dynamic_migrations/compare/v3.6.7...v3.6.8) (2023-09-13)
11
+
12
+
13
+ ### Bug Fixes
14
+
15
+ * dependency resolution is now aware of functions, enums and works across schemas. ([460de82](https://github.com/craigulliott/dynamic_migrations/commit/460de828be1826930bc1b185cf2a4c4e354d7dad))
16
+ * enum columns now accept an enum object ([460de82](https://github.com/craigulliott/dynamic_migrations/commit/460de828be1826930bc1b185cf2a4c4e354d7dad))
17
+ * trigger parameters is now an array of strings ([460de82](https://github.com/craigulliott/dynamic_migrations/commit/460de828be1826930bc1b185cf2a4c4e354d7dad))
18
+
3
19
  ## [3.6.7](https://github.com/craigulliott/dynamic_migrations/compare/v3.6.6...v3.6.7) (2023-09-13)
4
20
 
5
21
 
@@ -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)
@@ -52,6 +52,10 @@ module DynamicMigrations
52
52
  :values
53
53
  ]
54
54
  end
55
+
56
+ def full_name
57
+ :"#{schema.name}.#{name}"
58
+ end
55
59
  end
56
60
  end
57
61
  end
@@ -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.full_name || @data_type == "#{enum.full_name}[]"
54
+ raise UnexpectedEnumError, "enum `#{enum.full_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.9"
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]
@@ -12,6 +12,7 @@ module DynamicMigrations
12
12
  attr_reader values: Array[Symbol]
13
13
  attr_reader description: String?
14
14
  def initialize: (database_or_configuration source, Schema schema, Symbol name, Array[Symbol] values, ?description: String?) -> void
15
+ def full_name: -> Symbol
15
16
  def has_description?: -> bool
16
17
  def differences_descriptions: (Enum other_enum) -> Array[String]
17
18
 
@@ -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.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - Craig Ulliott