dynamic_migrations 3.3.1 → 3.4.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (30) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +7 -0
  3. data/lib/dynamic_migrations/active_record/migrators/enum.rb +44 -0
  4. data/lib/dynamic_migrations/active_record/migrators.rb +1 -0
  5. data/lib/dynamic_migrations/postgres/generator/database_migration.rb +14 -0
  6. data/lib/dynamic_migrations/postgres/generator/enum.rb +75 -0
  7. data/lib/dynamic_migrations/postgres/generator/extension.rb +27 -0
  8. data/lib/dynamic_migrations/postgres/generator/migration.rb +50 -19
  9. data/lib/dynamic_migrations/postgres/generator/schema_migration.rb +8 -0
  10. data/lib/dynamic_migrations/postgres/generator/table_migration.rb +1 -16
  11. data/lib/dynamic_migrations/postgres/generator.rb +25 -5
  12. data/lib/dynamic_migrations/postgres/server/database/configured_extensions.rb +40 -0
  13. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/extensions.rb +30 -0
  14. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/enums.rb +73 -0
  15. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas.rb +3 -0
  16. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations.rb +10 -2
  17. data/lib/dynamic_migrations/postgres/server/database/differences.rb +55 -3
  18. data/lib/dynamic_migrations/postgres/server/database/enums_loader.rb +40 -0
  19. data/lib/dynamic_migrations/postgres/server/database/extensions_loader.rb +26 -0
  20. data/lib/dynamic_migrations/postgres/server/database/loaded_extensions.rb +40 -0
  21. data/lib/dynamic_migrations/postgres/server/database/loaded_schemas_builder.rb +13 -1
  22. data/lib/dynamic_migrations/postgres/server/database/schema/enum.rb +60 -0
  23. data/lib/dynamic_migrations/postgres/server/database/schema/enums.rb +63 -0
  24. data/lib/dynamic_migrations/postgres/server/database/schema/function.rb +1 -1
  25. data/lib/dynamic_migrations/postgres/server/database/schema.rb +2 -0
  26. data/lib/dynamic_migrations/postgres/server/database/structure_loader.rb +1 -1
  27. data/lib/dynamic_migrations/postgres/server/database.rb +6 -0
  28. data/lib/dynamic_migrations/version.rb +1 -1
  29. data/lib/dynamic_migrations.rb +12 -0
  30. metadata +14 -2
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3917e377fb83c0bf7d8d836521935e6fecb298d1fea691bef33b212577f78801
4
- data.tar.gz: 54c2c5ebc5c685029806cc2ecc99aea2871bf3a480fe245041594fe616362de8
3
+ metadata.gz: 4175e35ddf2a941304c9efec0400c7ed6d933bf982d3744eb45f2891d6806ec6
4
+ data.tar.gz: c78c493bf1660d8b2eb36fe355a07869b8ef2fdbc4a05527da51e27b56dcfa2e
5
5
  SHA512:
6
- metadata.gz: 18028c2423770216cb7b2121e626d361b4c9bd8943b17b28903221e0a05e63cb2b9ade9d59b23b4168a995d8e2d35b3ca9476a6f94f6b13980ef2931c7aa8885
7
- data.tar.gz: d2591dc1c9cf267efc8cf038dcef0a80ecd19eb0981dde81ae5fc68c853125ba805d7a2716123794843452fdc1eafe9dc7a9a1c34a09f71739e3aebd1b4579ff
6
+ metadata.gz: f4e13bc988a286385fa6e39b4cbf5d001674cec8482ee9cb4680d34fe9b3a82fc869dccbef8c31527f3f23a4230796cc07b4559bd90c35373b3865877328878c
7
+ data.tar.gz: 73a51e5ae774cd41863e67c2f5cf7f541beaeddbf6b027d81637a6926542d267fb0ca34e790b86b206786668cf2fc3466242a6347871ed552f739aa2a7a8baf8
data/CHANGELOG.md CHANGED
@@ -1,5 +1,12 @@
1
1
  # Changelog
2
2
 
3
+ ## [3.4.0](https://github.com/craigulliott/dynamic_migrations/compare/v3.3.1...v3.4.0) (2023-08-23)
4
+
5
+
6
+ ### Features
7
+
8
+ * adding support for enums and extensions ([6e00d5f](https://github.com/craigulliott/dynamic_migrations/commit/6e00d5fc726e2a1bbeb282477c8bca92b94462cf))
9
+
3
10
  ## [3.3.1](https://github.com/craigulliott/dynamic_migrations/compare/v3.3.0...v3.3.1) (2023-08-18)
4
11
 
5
12
 
@@ -0,0 +1,44 @@
1
+ module DynamicMigrations
2
+ module ActiveRecord
3
+ module Migrators
4
+ module Enum
5
+ # create a postgres enum
6
+ def create_enum enum_name, values
7
+ # schema_name was not provided to this method, it comes from the migration class
8
+ execute <<~SQL
9
+ CREATE TYPE #{schema_name}.#{enum_name} as ENUM ('#{values.join("','")}');
10
+ SQL
11
+ end
12
+
13
+ # add vaues to a given enum
14
+ def add_enum_values enum_name, values
15
+ sqls = values.map do |value|
16
+ "ALTER TYPE #{schema_name}.#{enum_name} ADD ATTRIBUTE '#{value}';"
17
+ end
18
+ execute sqls.join("\n")
19
+ end
20
+
21
+ # remove a enum from the schema
22
+ def drop_enum enum_name
23
+ execute <<~SQL
24
+ DROP TYPE #{schema_name}.#{enum_name};
25
+ SQL
26
+ end
27
+
28
+ # add a comment to a enum
29
+ def set_enum_comment enum_name, comment
30
+ execute <<~SQL
31
+ COMMENT ON TYPE #{schema_name}.#{enum_name} IS '#{quote comment}';
32
+ SQL
33
+ end
34
+
35
+ # remove the comment from a enum
36
+ def remove_enum_comment enum_name
37
+ execute <<~SQL
38
+ COMMENT ON TYPE #{schema_name}.#{enum_name} IS null;
39
+ SQL
40
+ end
41
+ end
42
+ end
43
+ end
44
+ end
@@ -30,6 +30,7 @@ module DynamicMigrations
30
30
  include Function
31
31
  include UniqueConstraint
32
32
  include Trigger
33
+ include Enum
33
34
 
34
35
  # The schema name should be set before the migrations for
35
36
  # each schema's migrations are run. This is done by:
@@ -0,0 +1,14 @@
1
+ module DynamicMigrations
2
+ module Postgres
3
+ class Generator
4
+ class DatabaseMigration < Migration
5
+ # these sections are in order for which they will appear in a migration,
6
+ # note that removals come before additions, and that the order here optomizes
7
+ # for dependencies (i.e. columns have to be created before indexes are added and
8
+ # triggers are removed before functions are dropped)
9
+ add_structure_template [:create_extension], "Create Extension"
10
+ add_structure_template [:drop_extension], "Drop Extension"
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,75 @@
1
+ module DynamicMigrations
2
+ module Postgres
3
+ class Generator
4
+ module Enum
5
+ class UnremovableEnumValuesError < StandardError
6
+ end
7
+
8
+ def create_enum enum, code_comment = nil
9
+ add_fragment schema: enum.schema,
10
+ migration_method: :create_enum,
11
+ object: enum,
12
+ code_comment: code_comment,
13
+ migration: <<~RUBY
14
+ create_enum :#{enum.name}, [
15
+ :#{enum.values.join(",\n :")}
16
+ ]
17
+ RUBY
18
+ end
19
+
20
+ def update_enum original_enum, updated_enum, code_comment = nil
21
+ added_values = updated_enum.values - original_enum.values
22
+ removed_values = original_enum.values - updated_enum.values
23
+
24
+ if removed_values.any?
25
+ raise UnremovableEnumValuesError, "You can not remove enum values from postgres. Tring to remove '#{removed_values.join("', ")}'"
26
+ end
27
+
28
+ add_fragment schema: updated_enum.schema,
29
+ migration_method: :add_enum_values,
30
+ object: updated_enum,
31
+ code_comment: code_comment,
32
+ migration: <<~RUBY
33
+ add_enum_values :#{updated_enum.name}, [
34
+ :#{added_values.join(",\n :")}
35
+ ]
36
+ RUBY
37
+ end
38
+
39
+ def drop_enum enum, code_comment = nil
40
+ add_fragment schema: enum.schema,
41
+ migration_method: :drop_enum,
42
+ object: enum,
43
+ code_comment: code_comment,
44
+ migration: <<~RUBY
45
+ drop_enum :#{enum.name}
46
+ RUBY
47
+ end
48
+
49
+ # add a comment to a enum
50
+ def set_enum_comment enum, code_comment = nil
51
+ add_fragment schema: enum.schema,
52
+ migration_method: :set_enum_comment,
53
+ object: enum,
54
+ code_comment: code_comment,
55
+ migration: <<~RUBY
56
+ set_enum_comment :#{enum.name}, <<~COMMENT
57
+ #{indent enum.description || ""}
58
+ COMMENT
59
+ RUBY
60
+ end
61
+
62
+ # remove the comment from a enum
63
+ def remove_enum_comment enum, code_comment = nil
64
+ add_fragment schema: enum.schema,
65
+ migration_method: :remove_enum_comment,
66
+ object: enum,
67
+ code_comment: code_comment,
68
+ migration: <<~RUBY
69
+ remove_enum_comment :#{enum.name}
70
+ RUBY
71
+ end
72
+ end
73
+ end
74
+ end
75
+ end
@@ -0,0 +1,27 @@
1
+ module DynamicMigrations
2
+ module Postgres
3
+ class Generator
4
+ module Extension
5
+ def create_extension extension_name, code_comment = nil
6
+ # no table or schema name for this fragment (it is executed at the database level)
7
+ add_fragment migration_method: :create_extension,
8
+ object: extension_name,
9
+ code_comment: code_comment,
10
+ migration: <<~RUBY
11
+ create_extension :#{extension_name}
12
+ RUBY
13
+ end
14
+
15
+ def drop_extension extension_name, code_comment = nil
16
+ # no table or schema name for this fragment (it is executed at the database level)
17
+ add_fragment migration_method: :drop_extension,
18
+ object: extension_name,
19
+ code_comment: code_comment,
20
+ migration: <<~RUBY
21
+ drop_extension :#{extension_name}
22
+ RUBY
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
@@ -2,9 +2,6 @@ module DynamicMigrations
2
2
  module Postgres
3
3
  class Generator
4
4
  class Migration
5
- class UnexpectedSchemaError < StandardError
6
- end
7
-
8
5
  class SectionNotFoundError < StandardError
9
6
  end
10
7
 
@@ -17,6 +14,29 @@ module DynamicMigrations
17
14
  class NoFragmentsError < StandardError
18
15
  end
19
16
 
17
+ class MissingRequiredTableName < StandardError
18
+ end
19
+
20
+ class MissingRequiredSchemaName < StandardError
21
+ end
22
+
23
+ class UnexpectedTableError < StandardError
24
+ end
25
+
26
+ class UnexpectedSchemaError < StandardError
27
+ end
28
+
29
+ attr_reader :table_name
30
+ attr_reader :schema_name
31
+ attr_reader :fragments
32
+
33
+ # schema_name and table_name can be nil
34
+ def initialize schema_name = nil, table_name = nil
35
+ @schema_name = schema_name
36
+ @table_name = table_name
37
+ @fragments = []
38
+ end
39
+
20
40
  # Defines a new section in the migration file, this is used to group
21
41
  # migration fragments of the provided method names together under the
22
42
  # provided header
@@ -47,25 +67,27 @@ module DynamicMigrations
47
67
  @structure_templates = []
48
68
  end
49
69
 
50
- attr_reader :schema_name
51
- attr_reader :fragments
52
-
53
- def initialize schema_name
54
- @schema_name = schema_name
55
- @fragments = []
56
- end
57
-
58
70
  # Add a migration fragment to this migration, if the migration is not
59
71
  # configured (via a structure template) to handle the method_name of the
60
72
  # fragment, then am error is raised. An error will also be raised if the
61
73
  # migration belongs to a different schema than the provided fragment.
62
74
  def add_fragment fragment
63
- raise UnexpectedSchemaError unless @schema_name == fragment.schema_name
64
-
65
75
  unless supported_migration_method? fragment.migration_method
66
76
  raise UnexpectedMigrationMethodNameError, "Expected method to be a valid migrator method, got `#{fragment.migration_method}`"
67
77
  end
68
78
 
79
+ # confirm the fragment is for this schema (even if both
80
+ # these values are nil/there is no schema)
81
+ unless @schema_name == fragment.schema_name
82
+ raise UnexpectedSchemaError, "Fragment is for schema `#{fragment.schema_name || "nil"}` but migration is for schema `#{@schema_name || "nil"}`"
83
+ end
84
+
85
+ # confirm this fragment is for this table, this works for database and schame
86
+ # migrations to, as all values should be nil
87
+ unless @table_name == fragment.table_name
88
+ raise UnexpectedTableError, "Fragment is for table `#{fragment.table_name || "nil"}` but migration is for table `#{@table_name || "nil"}`"
89
+ end
90
+
69
91
  @fragments << fragment
70
92
 
71
93
  fragment
@@ -122,25 +144,34 @@ module DynamicMigrations
122
144
  raise NoFragmentsError if fragments.empty?
123
145
 
124
146
  if fragments_for_method? :create_schema
125
- "create_#{first_fragment_using_migration_method(:create_schema).schema_name}_schema".to_sym
147
+ :"create_#{first_fragment_using_migration_method(:create_schema).schema_name}_schema"
126
148
 
127
149
  elsif fragments_for_method? :drop_schema
128
- "drop_#{first_fragment_using_migration_method(:drop_schema).schema_name}_schema".to_sym
150
+ :"drop_#{first_fragment_using_migration_method(:drop_schema).schema_name}_schema"
129
151
 
130
152
  elsif fragments_for_method? :create_table
131
- "create_#{first_fragment_using_migration_method(:create_table).table_name}".to_sym
153
+ :"create_#{first_fragment_using_migration_method(:create_table).table_name}"
132
154
 
133
155
  elsif fragments_for_method? :drop_table
134
- "drop_#{first_fragment_using_migration_method(:drop_table).table_name}".to_sym
156
+ :"drop_#{first_fragment_using_migration_method(:drop_table).table_name}"
135
157
 
136
158
  elsif all_fragments_for_method? [:create_function]
137
- "create_function_#{@fragments.find { |s| s.migration_method == :create_function }&.object_name}".to_sym
159
+ :"create_function_#{@fragments.find { |s| s.migration_method == :create_function }&.object_name}"
138
160
 
139
161
  elsif all_fragments_for_method? [:create_function, :update_function, :drop_function, :set_function_comment, :remove_function_comment]
140
162
  :schema_functions
141
163
 
164
+ elsif all_fragments_for_method? [:create_enum, :add_enum_values, :drop_enum, :set_enum_comment, :remove_enum_comment]
165
+ :enums
166
+
167
+ elsif all_fragments_for_method? [:create_extension]
168
+ (@fragments.count > 1) ? :":create_extensions" : :"create_#{fragments.first&.object_name}_extension"
169
+
170
+ elsif all_fragments_for_method? [:drop_extension]
171
+ (@fragments.count > 1) ? :":drop_extensions" : :"drop_#{fragments.first&.object_name}_extension"
172
+
142
173
  elsif @fragments.first&.table_name
143
- "changes_for_#{@fragments.first&.table_name}".to_sym
174
+ :"changes_for_#{@fragments.first&.table_name}"
144
175
 
145
176
  else
146
177
  :changes
@@ -7,10 +7,18 @@ module DynamicMigrations
7
7
  # for dependencies (i.e. columns have to be created before indexes are added and
8
8
  # triggers are removed before functions are dropped)
9
9
  add_structure_template [:remove_function_comment, :drop_function], "Remove Functions"
10
+ add_structure_template [:remove_enum_comment, :drop_enum], "Drop Enums"
10
11
  add_structure_template [:drop_schema], "Drop this schema"
12
+ add_structure_template [:create_enum, :add_enum_values, :set_enum_comment], "Enums"
11
13
  add_structure_template [:create_schema], "Create this schema"
12
14
  add_structure_template [:create_function], "Functions"
13
15
  add_structure_template [:update_function, :set_function_comment], "Update Functions"
16
+ add_structure_template [:create_extension, :drop_extension], "Extensions"
17
+
18
+ def initialize schema_name
19
+ raise MissingRequiredSchemaName unless schema_name
20
+ super
21
+ end
14
22
  end
15
23
  end
16
24
  end
@@ -2,12 +2,6 @@ module DynamicMigrations
2
2
  module Postgres
3
3
  class Generator
4
4
  class TableMigration < Migration
5
- class UnexpectedTableError < StandardError
6
- end
7
-
8
- class MissingRequiredTableName < StandardError
9
- end
10
-
11
5
  # these sections are in order for which they will appear in a migration,
12
6
  # note that removals come before additions, and that the order here optomizes
13
7
  # for dependencies (i.e. columns have to be created before indexes are added and
@@ -31,18 +25,9 @@ module DynamicMigrations
31
25
  add_structure_template [:add_trigger, :set_trigger_comment], "Triggers"
32
26
  add_structure_template [:update_function, :set_function_comment], "Update Functions"
33
27
 
34
- attr_accessor :table_name
35
-
36
28
  def initialize schema_name, table_name
29
+ raise MissingRequiredSchemaName unless schema_name
37
30
  raise MissingRequiredTableName unless table_name
38
- super schema_name
39
- @table_name = table_name
40
- end
41
-
42
- def add_fragment fragment
43
- unless @table_name == fragment.table_name
44
- raise UnexpectedTableError, "Frgment is for table `#{fragment.table_name}` but migration is for table `#{@table_name}`"
45
- end
46
31
  super
47
32
  end
48
33
  end
@@ -16,6 +16,9 @@ module DynamicMigrations
16
16
  class TableMigrationNotFound < StandardError
17
17
  end
18
18
 
19
+ class UnprocessableFragmentError < StandardError
20
+ end
21
+
19
22
  include Schema
20
23
  include Table
21
24
  include Column
@@ -26,6 +29,8 @@ module DynamicMigrations
26
29
  include Validation
27
30
  include Function
28
31
  include Trigger
32
+ include Enum
33
+ include Extension
29
34
 
30
35
  def initialize
31
36
  @fragments = []
@@ -36,6 +41,9 @@ module DynamicMigrations
36
41
  # a hash to hold the generated migrations orgnized by their schema and table
37
42
  # this makes it easier and faster to work with them within this method
38
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
39
47
 
40
48
  # Process each fragment, and organize them into migrations. We create a shared
41
49
  # Migration for each table, and a single shared migration for any schema migrations
@@ -54,15 +62,22 @@ module DynamicMigrations
54
62
  table_name = fragment.table_name
55
63
  # If we have a table name, then add the migration fragment to a
56
64
  # TableMigration which holds all of the migrations for this table
57
- if table_name
65
+ if table_name && schema_name
58
66
  table_migration = schema_migrations[:table_migrations][table_name] ||= TableMigration.new(schema_name, table_name)
59
67
  table_migration.add_fragment fragment
60
68
 
61
- # migration fragments which do not belong to a specific table are added
69
+ # migration fragments which do have a schema, but do not belong to a specific table are added
62
70
  # to a dedicated SchemaMigration object
63
- else
71
+ elsif schema_name && table_name.nil?
64
72
  schema_migration = schema_migrations[:schema_migration] ||= SchemaMigration.new(schema_name)
65
73
  schema_migration.add_fragment fragment
74
+
75
+ # migrations with no schema or table, are added to a database
76
+ # migration (these re really just creating/dropping extensions)
77
+ elsif schema_name.nil? && table_name.nil?
78
+ database_specific_migration.add_fragment fragment
79
+ else
80
+ raise UnprocessableFragmentError
66
81
  end
67
82
  end
68
83
 
@@ -158,6 +173,11 @@ module DynamicMigrations
158
173
  # the order is determined by their dependencies
159
174
  final_migrations = dependency_sorter.tsort
160
175
 
176
+ # if any database only migrations exist, then add them to the from of the array here
177
+ if database_specific_migration.fragments.any?
178
+ final_migrations.unshift database_specific_migration
179
+ end
180
+
161
181
  # return the final migrations in the expected format
162
182
  final_migrations.map do |migration|
163
183
  {
@@ -200,11 +220,11 @@ module DynamicMigrations
200
220
  @dep[node].each(&block)
201
221
  end
202
222
 
203
- def add_fragment schema:, migration_method:, object:, migration:, table: nil, code_comment: nil, dependent_table: nil
223
+ def add_fragment migration_method:, object:, migration:, schema: nil, table: nil, code_comment: nil, dependent_table: nil
204
224
  # Remove any empty lines and whitespace from the beginning or the end of the migration and then
205
225
  # strip any empty lines witin the migration (remove the whitespace from them, not delete them).
206
226
  final_migration = strip_empty_lines(migration).strip
207
- fragment = Fragment.new(schema.name, table&.name, migration_method, object.name, code_comment, final_migration)
227
+ fragment = Fragment.new(schema&.name, table&.name, migration_method, object.name, code_comment, final_migration)
208
228
  if dependent_table
209
229
  fragment.set_dependent_table dependent_table.schema.name, dependent_table.name
210
230
  end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DynamicMigrations
4
+ module Postgres
5
+ class Server
6
+ class Database
7
+ module ConfiguredExtensions
8
+ class ConfiguredExtensionAlreadyExistsError < StandardError
9
+ end
10
+
11
+ # adds a new configured extension for this database
12
+ def add_configured_extension extension_name
13
+ raise ExpectedSymbolError, extension_name unless extension_name.is_a? Symbol
14
+ if has_configured_extension? extension_name
15
+ raise(ConfiguredExtensionAlreadyExistsError, "Configured extension #{extension_name} already exists")
16
+ end
17
+ # sort the hash so that the extensions are in alphabetical order by name
18
+ @configured_extensions[extension_name] = true
19
+ sorted_extensions = {}
20
+ @configured_extensions.keys.sort.each do |extension_name|
21
+ sorted_extensions[extension_name] = true
22
+ end
23
+ @configured_extensions = sorted_extensions
24
+ end
25
+
26
+ # returns true if this table has a configured extension with the provided name, otherwise false
27
+ def has_configured_extension? extension_name
28
+ raise ExpectedSymbolError, extension_name unless extension_name.is_a? Symbol
29
+ @configured_extensions.key? extension_name
30
+ end
31
+
32
+ # returns an array of this tables configured extensions
33
+ def configured_extensions
34
+ @configured_extensions.keys
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DynamicMigrations
4
+ module Postgres
5
+ class Server
6
+ class Database
7
+ class Differences
8
+ class ToMigrations
9
+ module Extensions
10
+ def process_extension extension_name, configuration_extension, database_extension
11
+ # if the extension exists in the configuration but not in the database
12
+ # then we have to create it
13
+ if configuration_extension[:exists] == true && database_extension[:exists] == false
14
+ # a migration to create the extension
15
+ @generator.create_extension extension_name
16
+
17
+ # if the extension exists in the database but not in the configuration
18
+ # then we need to delete it
19
+ elsif configuration_extension[:exists] == false && database_extension[:exists] == true
20
+ # a migration to drop the extension
21
+ @generator.drop_extension extension_name
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,73 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DynamicMigrations
4
+ module Postgres
5
+ class Server
6
+ class Database
7
+ class Differences
8
+ class ToMigrations
9
+ module Schemas
10
+ module Enums
11
+ def process_enums schema_name, configuration_enums, database_enums
12
+ # process all the enums
13
+ enum_names = (configuration_enums.keys + database_enums.keys).uniq
14
+ enum_names.each do |enum_name|
15
+ process_enum schema_name, enum_name, configuration_enums[enum_name] || {}, database_enums[enum_name] || {}
16
+ end
17
+ end
18
+
19
+ def process_enum schema_name, enum_name, configuration_enum, database_enum
20
+ # If the enum exists in the configuration but not in the database
21
+ # then we have to create it.
22
+ if configuration_enum[:exists] == true && database_enum[:exists] == false
23
+ # a migration to create the enum
24
+ enum = @database.configured_schema(schema_name).enum(enum_name)
25
+ @generator.create_enum enum
26
+ # optionally add the description
27
+ if enum.has_description?
28
+ @generator.set_enum_comment enum
29
+ end
30
+
31
+ # If the schema exists in the database but not in the configuration
32
+ # then we need to delete it.
33
+ elsif configuration_enum[:exists] == false && database_enum[:exists] == true
34
+ # a migration to create the enum
35
+ enum = @database.loaded_schema(schema_name).enum(enum_name)
36
+ @generator.drop_enum enum
37
+
38
+ # If the enum exists in both the configuration and database representations
39
+ # but the values is different then we need to update the values.
40
+ elsif configuration_enum[:values][:matches] == false
41
+ original_enum = @database.loaded_schema(schema_name).enum(enum_name)
42
+ updated_enum = @database.configured_schema(schema_name).enum(enum_name)
43
+ @generator.update_enum original_enum, updated_enum
44
+ # does the description also need to be updated
45
+ if configuration_enum[:description][:matches] == false
46
+ # if the description was removed
47
+ if configuration_enum[:description].nil?
48
+ @generator.remove_enum_comment updated_enum
49
+ else
50
+ @generator.set_enum_comment updated_enum
51
+ end
52
+ end
53
+
54
+ # If the enum exists in both the configuration and database representations
55
+ # but the description is different then we need to update the description.
56
+ elsif configuration_enum[:description][:matches] == false
57
+ enum = @database.configured_schema(schema_name).enum(enum_name)
58
+ # if the description was removed
59
+ if configuration_enum[:description].nil?
60
+ @generator.remove_enum_comment enum
61
+ else
62
+ @generator.set_enum_comment enum
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
73
+ end
@@ -18,6 +18,7 @@ module DynamicMigrations
18
18
  # we process the tables and functions after we create the schema
19
19
  # otherwise the schemas objects will not be able to be created
20
20
  process_functions schema_name, configuration_schema[:functions], {}
21
+ process_enums schema_name, configuration_schema[:enums], {}
21
22
  process_tables schema_name, configuration_schema[:tables], {}
22
23
 
23
24
  # if the schema exists in the database but not in the configuration
@@ -26,6 +27,7 @@ module DynamicMigrations
26
27
  # we process the tables and functions before we drop the schema
27
28
  # as this will drop any dependencies on the schema
28
29
  process_functions schema_name, {}, database_schema[:functions]
30
+ process_enums schema_name, {}, database_schema[:enums]
29
31
  process_tables schema_name, {}, database_schema[:tables]
30
32
 
31
33
  # a migration to drop the schema
@@ -36,6 +38,7 @@ module DynamicMigrations
36
38
  # then we just need to process the tables and functions
37
39
  else
38
40
  process_functions schema_name, configuration_schema[:functions], database_schema[:functions]
41
+ process_enums schema_name, configuration_schema[:enums], database_schema[:enums]
39
42
  process_tables schema_name, configuration_schema[:tables], database_schema[:tables]
40
43
  end
41
44
  end
@@ -12,8 +12,10 @@ module DynamicMigrations
12
12
  class UnexpectedDifferencesObjectError < StandardError
13
13
  end
14
14
 
15
+ include Extensions
15
16
  include Schemas
16
17
  include Schemas::Functions
18
+ include Schemas::Enums
17
19
  include Schemas::Tables
18
20
  include Schemas::Tables::Columns
19
21
  include Schemas::Tables::ForeignKeyConstraints
@@ -35,11 +37,17 @@ module DynamicMigrations
35
37
  end
36
38
 
37
39
  def migrations
40
+ # process all the extensions
41
+ extension_names = differences[:configuration][:extensions].keys
42
+ extension_names.each do |extension_name|
43
+ process_extension extension_name, differences[:configuration][:extensions][extension_name], differences[:database][:extensions][extension_name]
44
+ end
45
+
38
46
  # process all the schemas (we can fetch the schema names from either the
39
47
  # configuration or the database object)
40
- schema_names = differences[:configuration].keys
48
+ schema_names = differences[:configuration][:schemas].keys
41
49
  schema_names.each do |schema_name|
42
- process_schema schema_name, differences[:configuration][schema_name], differences[:database][schema_name]
50
+ process_schema schema_name, differences[:configuration][:schemas][schema_name], differences[:database][:schemas][schema_name]
43
51
  end
44
52
 
45
53
  # return the migrations organized by schema
@@ -32,11 +32,38 @@ module DynamicMigrations
32
32
  # versions of the current database
33
33
  def to_h
34
34
  {
35
- configuration: self.class.compare_schemas(@database.configured_schemas_hash, @database.loaded_schemas_hash),
36
- database: self.class.compare_schemas(@database.loaded_schemas_hash, @database.configured_schemas_hash)
35
+ configuration: {
36
+ schemas: self.class.compare_schemas(@database.configured_schemas_hash, @database.loaded_schemas_hash),
37
+ extensions: self.class.compare_extensions(@database.configured_extensions, @database.loaded_extensions)
38
+ },
39
+ database: {
40
+ schemas: self.class.compare_schemas(@database.loaded_schemas_hash, @database.configured_schemas_hash),
41
+ extensions: self.class.compare_extensions(@database.loaded_extensions, @database.configured_extensions)
42
+ }
37
43
  }
38
44
  end
39
45
 
46
+ def self.compare_extensions extensions, comparison_extensions
47
+ result = {}
48
+ # the extensions
49
+ extensions.each do |extension_name|
50
+ # compare this extension to the equivilent in the comparison list
51
+ # note that the comparison may be nil
52
+ result[extension_name] = {
53
+ exists: true
54
+ }
55
+ end
56
+ # look for any in the comparison list which were not in the base list
57
+ comparison_extensions.each do |extension_name|
58
+ unless result.key? extension_name
59
+ result[extension_name] = {
60
+ exists: false
61
+ }
62
+ end
63
+ end
64
+ result
65
+ end
66
+
40
67
  def self.compare_schemas schemas, comparison_schemas
41
68
  result = {}
42
69
  # the base schemas
@@ -63,10 +90,12 @@ module DynamicMigrations
63
90
 
64
91
  comparison_tables = comparison_schema.nil? ? {} : comparison_schema.tables_hash
65
92
  comparison_functions = comparison_schema.nil? ? {} : comparison_schema.functions_hash
93
+ comparison_enums = comparison_schema.nil? ? {} : comparison_schema.enums_hash
66
94
  {
67
95
  exists: true,
68
96
  tables: compare_tables(schema.tables_hash, comparison_tables),
69
- functions: compare_functions(schema.functions_hash, comparison_functions)
97
+ functions: compare_functions(schema.functions_hash, comparison_functions),
98
+ enums: compare_enums(schema.enums_hash, comparison_enums)
70
99
  }
71
100
  end
72
101
 
@@ -158,6 +187,29 @@ module DynamicMigrations
158
187
  result
159
188
  end
160
189
 
190
+ # compare two hash representations of a set of enums and return
191
+ # an object which represents the provided `enums` and any differences
192
+ # between it and the `comparison_enums`
193
+ def self.compare_enums enums, comparison_enums
194
+ result = {}
195
+ # the base enums
196
+ enums.each do |enum_name, enum|
197
+ result[enum_name] = compare_record enum, comparison_enums[enum_name], [
198
+ :values,
199
+ :description
200
+ ]
201
+ end
202
+ # look for any in the comparison list which were not in the base list
203
+ comparison_enums.each do |enum_name, enum|
204
+ unless result.key? enum_name
205
+ result[enum_name] = {
206
+ exists: false
207
+ }
208
+ end
209
+ end
210
+ result
211
+ end
212
+
161
213
  # compare two hash representations of a set of columns and return
162
214
  # an object which represents the provided `columns` and any differences
163
215
  # between it and the `comparison_columns`
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DynamicMigrations
4
+ module Postgres
5
+ class Server
6
+ class Database
7
+ module EnumsLoader
8
+ def fetch_enums
9
+ rows = connection.exec(<<~SQL)
10
+ SELECT
11
+ n.nspname AS schema_name,
12
+ t.typname AS enum_name,
13
+ e.enumlabel AS enum_value,
14
+ obj_description(e.enumtypid, 'pg_type') as enum_description
15
+ FROM pg_type t
16
+ JOIN pg_enum e ON t.oid = e.enumtypid
17
+ JOIN pg_catalog.pg_namespace n ON n.oid = t.typnamespace
18
+ ORDER BY enumsortorder
19
+ SQL
20
+
21
+ schemas = {}
22
+ rows.each do |row|
23
+ schema_name = row["schema_name"].to_sym
24
+ enum_name = row["enum_name"].to_sym
25
+ enum_value = row["enum_value"].to_sym
26
+
27
+ schema = schemas[schema_name] ||= {}
28
+ enum = schema[enum_name] ||= {
29
+ values: [],
30
+ description: row["enum_description"]
31
+ }
32
+ enum[:values] << enum_value
33
+ end
34
+ schemas
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,26 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DynamicMigrations
4
+ module Postgres
5
+ class Server
6
+ class Database
7
+ module ExtensionsLoader
8
+ # return an array of the extensions active in this database
9
+ def fetch_extensions
10
+ rows = connection.exec(<<~SQL)
11
+ SELECT
12
+ extname AS name
13
+ FROM pg_extension;
14
+ SQL
15
+
16
+ extensions = []
17
+ rows.each do |row|
18
+ extensions << row["name"].to_sym
19
+ end
20
+ extensions
21
+ end
22
+ end
23
+ end
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,40 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DynamicMigrations
4
+ module Postgres
5
+ class Server
6
+ class Database
7
+ module LoadedExtensions
8
+ class LoadedExtensionAlreadyExistsError < StandardError
9
+ end
10
+
11
+ # adds a new loaded extension for this database
12
+ def add_loaded_extension extension_name
13
+ raise ExpectedSymbolError, extension_name unless extension_name.is_a? Symbol
14
+ if has_loaded_extension? extension_name
15
+ raise(LoadedExtensionAlreadyExistsError, "Loaded extension #{extension_name} already exists")
16
+ end
17
+ # sort the hash so that the extensions are in alphabetical order by name
18
+ @loaded_extensions[extension_name] = true
19
+ sorted_extensions = {}
20
+ @loaded_extensions.keys.sort.each do |extension_name|
21
+ sorted_extensions[extension_name] = true
22
+ end
23
+ @loaded_extensions = sorted_extensions
24
+ end
25
+
26
+ # returns true if this table has a loaded extension with the provided name, otherwise false
27
+ def has_loaded_extension? extension_name
28
+ raise ExpectedSymbolError, extension_name unless extension_name.is_a? Symbol
29
+ @loaded_extensions.key? extension_name
30
+ end
31
+
32
+ # returns an array of this tables loaded extensions
33
+ def loaded_extensions
34
+ @loaded_extensions.keys
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -13,7 +13,7 @@ module DynamicMigrations
13
13
 
14
14
  # recursively process the database and build all the schemas,
15
15
  # tables and columns
16
- def recursively_build_schemas_from_database
16
+ def recursively_load_database_structure
17
17
  validations = fetch_validations
18
18
  fetch_structure.each do |schema_name, schema_definition|
19
19
  schema = add_loaded_schema schema_name
@@ -39,6 +39,18 @@ module DynamicMigrations
39
39
  end
40
40
  end
41
41
 
42
+ # add any active extensions to the database
43
+ fetch_extensions.each do |extension_name|
44
+ add_loaded_extension extension_name
45
+ end
46
+
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
+
42
54
  # now that the structure has been loaded, we can add keys (foreign
43
55
  # keys need to be added last, because they can depend on tables from
44
56
  # different schemas)
@@ -0,0 +1,60 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DynamicMigrations
4
+ module Postgres
5
+ class Server
6
+ class Database
7
+ class Schema
8
+ # This class represents a postgres enum.
9
+ class Enum < Source
10
+ class ExpectedSchemaError < StandardError
11
+ end
12
+
13
+ class ExpectedValuesError < StandardError
14
+ end
15
+
16
+ attr_reader :schema
17
+ attr_reader :name
18
+ attr_reader :values
19
+ attr_reader :description
20
+
21
+ # initialize a new object to represent a postgres enum
22
+ def initialize source, schema, name, values, description: nil
23
+ super source
24
+
25
+ @values = []
26
+
27
+ raise ExpectedSchemaError, schema unless schema.is_a? Schema
28
+ @schema = schema
29
+
30
+ raise ExpectedSymbolError, name unless name.is_a? Symbol
31
+ @name = name
32
+
33
+ unless values.is_a?(Array) && values.count > 0
34
+ raise ExpectedValuesError, "Values are required for enums"
35
+ end
36
+ @values = values
37
+
38
+ unless description.nil?
39
+ raise ExpectedStringError, description unless description.is_a? String
40
+ @description = description.strip
41
+ @description = nil if description == ""
42
+ end
43
+ end
44
+
45
+ # returns true if this enum has a description, otehrwise false
46
+ def has_description?
47
+ !@description.nil?
48
+ end
49
+
50
+ def differences_descriptions other_enum
51
+ method_differences_descriptions other_enum, [
52
+ :values
53
+ ]
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DynamicMigrations
4
+ module Postgres
5
+ class Server
6
+ class Database
7
+ class Schema < Source
8
+ module Enums
9
+ class EnumAlreadyExistsError < StandardError
10
+ end
11
+
12
+ class EnumDoesNotExistError < StandardError
13
+ end
14
+
15
+ # create and add a new enum
16
+ def add_enum enum_name, values, description: nil
17
+ raise ExpectedSymbolError, enum_name unless enum_name.is_a? Symbol
18
+ if has_enum? enum_name
19
+ raise(EnumAlreadyExistsError, "Enum #{enum_name} already exists")
20
+ end
21
+ included_target = self
22
+ if included_target.is_a? Schema
23
+ new_enum = @enums[enum_name] = Enum.new source, included_target, enum_name, values, description: description
24
+ else
25
+ raise ModuleIncludedIntoUnexpectedTargetError, included_target
26
+ end
27
+ # sort the hash so that the enums are in alphabetical order by name
28
+ sorted_enums = {}
29
+ @enums.keys.sort.each do |enum_name|
30
+ sorted_enums[enum_name] = @enums[enum_name]
31
+ end
32
+ @enums = sorted_enums
33
+ # return the new enum
34
+ new_enum
35
+ end
36
+
37
+ # return a enum by its name, raises an error if the enum does not exist
38
+ def enum enum_name
39
+ raise ExpectedSymbolError, enum_name unless enum_name.is_a? Symbol
40
+ raise EnumDoesNotExistError unless has_enum? enum_name
41
+ @enums[enum_name]
42
+ end
43
+
44
+ # returns true/false representing if a enum with the provided name exists
45
+ def has_enum? enum_name
46
+ raise ExpectedSymbolError, enum_name unless enum_name.is_a? Symbol
47
+ @enums.key? enum_name
48
+ end
49
+
50
+ # returns an array of all enums in the schema
51
+ def enums
52
+ @enums.values
53
+ end
54
+
55
+ def enums_hash
56
+ @enums
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -23,7 +23,7 @@ module DynamicMigrations
23
23
  def initialize source, schema, name, definition, description: nil
24
24
  super source
25
25
 
26
- @triggers ||= []
26
+ @triggers = []
27
27
 
28
28
  raise ExpectedSchemaError, schema unless schema.is_a? Schema
29
29
  @schema = schema
@@ -13,6 +13,7 @@ module DynamicMigrations
13
13
 
14
14
  include Tables
15
15
  include Functions
16
+ include Enums
16
17
 
17
18
  attr_reader :database
18
19
  attr_reader :name
@@ -26,6 +27,7 @@ module DynamicMigrations
26
27
  @name = name
27
28
  @tables = {}
28
29
  @functions = {}
30
+ @enums = {}
29
31
  end
30
32
  end
31
33
  end
@@ -104,7 +104,7 @@ module DynamicMigrations
104
104
 
105
105
  # recursively process the database and build all the schemas,
106
106
  # tables and columns
107
- def recursively_build_schemas_from_database
107
+ def recursively_load_database_structure
108
108
  fetch_structure.each do |schema_name, schema_definition|
109
109
  schema = add_loaded_schema schema_name
110
110
 
@@ -17,6 +17,10 @@ module DynamicMigrations
17
17
  include LoadedSchemas
18
18
  include ConfiguredSchemas
19
19
  include LoadedSchemasBuilder
20
+ include ConfiguredExtensions
21
+ include LoadedExtensions
22
+ include EnumsLoader
23
+ include ExtensionsLoader
20
24
 
21
25
  attr_reader :server
22
26
  attr_reader :name
@@ -29,6 +33,8 @@ module DynamicMigrations
29
33
  @name = name
30
34
  @configured_schemas = {}
31
35
  @loaded_schemas = {}
36
+ @configured_extensions = {}
37
+ @loaded_extensions = {}
32
38
  end
33
39
 
34
40
  # if `source` is :configuration then returns the configured schema with
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DynamicMigrations
4
- VERSION = "3.3.1"
4
+ VERSION = "3.4.0"
5
5
  end
@@ -15,11 +15,16 @@ require "dynamic_migrations/postgres/server/database/structure_loader"
15
15
  require "dynamic_migrations/postgres/server/database/validations_loader"
16
16
  require "dynamic_migrations/postgres/server/database/keys_and_unique_constraints_loader"
17
17
  require "dynamic_migrations/postgres/server/database/triggers_and_functions_loader"
18
+ require "dynamic_migrations/postgres/server/database/extensions_loader"
19
+ require "dynamic_migrations/postgres/server/database/enums_loader"
18
20
  require "dynamic_migrations/postgres/server/database/loaded_schemas_builder"
19
21
  require "dynamic_migrations/postgres/server/database/loaded_schemas"
20
22
  require "dynamic_migrations/postgres/server/database/configured_schemas"
23
+ require "dynamic_migrations/postgres/server/database/loaded_extensions"
24
+ require "dynamic_migrations/postgres/server/database/configured_extensions"
21
25
 
22
26
  require "dynamic_migrations/postgres/server/database/differences"
27
+ require "dynamic_migrations/postgres/server/database/differences/to_migrations/extensions"
23
28
  require "dynamic_migrations/postgres/server/database/differences/to_migrations/schemas"
24
29
  require "dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables"
25
30
  require "dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/columns"
@@ -30,6 +35,7 @@ require "dynamic_migrations/postgres/server/database/differences/to_migrations/s
30
35
  require "dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/unique_constraints"
31
36
  require "dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/validations"
32
37
  require "dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/functions"
38
+ require "dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/enums"
33
39
  require "dynamic_migrations/postgres/server/database/differences/to_migrations"
34
40
 
35
41
  require "dynamic_migrations/postgres/server/database"
@@ -37,8 +43,10 @@ require "dynamic_migrations/postgres/server/database/source"
37
43
 
38
44
  require "dynamic_migrations/postgres/server/database/schema/tables"
39
45
  require "dynamic_migrations/postgres/server/database/schema/functions"
46
+ require "dynamic_migrations/postgres/server/database/schema/enums"
40
47
  require "dynamic_migrations/postgres/server/database/schema"
41
48
  require "dynamic_migrations/postgres/server/database/schema/function"
49
+ require "dynamic_migrations/postgres/server/database/schema/enum"
42
50
  require "dynamic_migrations/postgres/server/database/schema/table/validations"
43
51
  require "dynamic_migrations/postgres/server/database/schema/table/indexes"
44
52
  require "dynamic_migrations/postgres/server/database/schema/table/foreign_key_constraints"
@@ -58,8 +66,10 @@ require "dynamic_migrations/postgres/server"
58
66
  require "dynamic_migrations/postgres/connections"
59
67
 
60
68
  require "dynamic_migrations/postgres/generator/schema"
69
+ require "dynamic_migrations/postgres/generator/extension"
61
70
  require "dynamic_migrations/postgres/generator/table"
62
71
  require "dynamic_migrations/postgres/generator/column"
72
+ require "dynamic_migrations/postgres/generator/enum"
63
73
  require "dynamic_migrations/postgres/generator/foreign_key_constraint"
64
74
  require "dynamic_migrations/postgres/generator/function"
65
75
  require "dynamic_migrations/postgres/generator/index"
@@ -70,6 +80,7 @@ require "dynamic_migrations/postgres/generator/validation"
70
80
  require "dynamic_migrations/postgres/generator"
71
81
  require "dynamic_migrations/postgres/generator/fragment"
72
82
  require "dynamic_migrations/postgres/generator/migration"
83
+ require "dynamic_migrations/postgres/generator/database_migration"
73
84
  require "dynamic_migrations/postgres/generator/schema_migration"
74
85
  require "dynamic_migrations/postgres/generator/table_migration"
75
86
  require "dynamic_migrations/postgres/generator/migration_dependency_sorter"
@@ -82,6 +93,7 @@ require "dynamic_migrations/active_record/migrators/function"
82
93
  require "dynamic_migrations/active_record/migrators/trigger"
83
94
  require "dynamic_migrations/active_record/migrators/table"
84
95
  require "dynamic_migrations/active_record/migrators/index"
96
+ require "dynamic_migrations/active_record/migrators/enum"
85
97
  require "dynamic_migrations/active_record/migrators/column"
86
98
  require "dynamic_migrations/active_record/migrators"
87
99
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: dynamic_migrations
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.3.1
4
+ version: 3.4.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Craig Ulliott
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2023-08-18 00:00:00.000000000 Z
11
+ date: 2023-08-23 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pg
@@ -67,6 +67,7 @@ files:
67
67
  - lib/dynamic_migrations.rb
68
68
  - lib/dynamic_migrations/active_record/migrators.rb
69
69
  - lib/dynamic_migrations/active_record/migrators/column.rb
70
+ - lib/dynamic_migrations/active_record/migrators/enum.rb
70
71
  - lib/dynamic_migrations/active_record/migrators/foreign_key_constraint.rb
71
72
  - lib/dynamic_migrations/active_record/migrators/function.rb
72
73
  - lib/dynamic_migrations/active_record/migrators/index.rb
@@ -86,6 +87,9 @@ files:
86
87
  - lib/dynamic_migrations/postgres/connections.rb
87
88
  - lib/dynamic_migrations/postgres/generator.rb
88
89
  - lib/dynamic_migrations/postgres/generator/column.rb
90
+ - lib/dynamic_migrations/postgres/generator/database_migration.rb
91
+ - lib/dynamic_migrations/postgres/generator/enum.rb
92
+ - lib/dynamic_migrations/postgres/generator/extension.rb
89
93
  - lib/dynamic_migrations/postgres/generator/foreign_key_constraint.rb
90
94
  - lib/dynamic_migrations/postgres/generator/fragment.rb
91
95
  - lib/dynamic_migrations/postgres/generator/function.rb
@@ -102,11 +106,14 @@ files:
102
106
  - lib/dynamic_migrations/postgres/generator/validation.rb
103
107
  - lib/dynamic_migrations/postgres/server.rb
104
108
  - lib/dynamic_migrations/postgres/server/database.rb
109
+ - lib/dynamic_migrations/postgres/server/database/configured_extensions.rb
105
110
  - lib/dynamic_migrations/postgres/server/database/configured_schemas.rb
106
111
  - lib/dynamic_migrations/postgres/server/database/connection.rb
107
112
  - lib/dynamic_migrations/postgres/server/database/differences.rb
108
113
  - lib/dynamic_migrations/postgres/server/database/differences/to_migrations.rb
114
+ - lib/dynamic_migrations/postgres/server/database/differences/to_migrations/extensions.rb
109
115
  - lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas.rb
116
+ - lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/enums.rb
110
117
  - lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/functions.rb
111
118
  - lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables.rb
112
119
  - lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/columns.rb
@@ -116,10 +123,15 @@ files:
116
123
  - lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/triggers.rb
117
124
  - lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/unique_constraints.rb
118
125
  - lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/validations.rb
126
+ - lib/dynamic_migrations/postgres/server/database/enums_loader.rb
127
+ - lib/dynamic_migrations/postgres/server/database/extensions_loader.rb
119
128
  - lib/dynamic_migrations/postgres/server/database/keys_and_unique_constraints_loader.rb
129
+ - lib/dynamic_migrations/postgres/server/database/loaded_extensions.rb
120
130
  - lib/dynamic_migrations/postgres/server/database/loaded_schemas.rb
121
131
  - lib/dynamic_migrations/postgres/server/database/loaded_schemas_builder.rb
122
132
  - lib/dynamic_migrations/postgres/server/database/schema.rb
133
+ - lib/dynamic_migrations/postgres/server/database/schema/enum.rb
134
+ - lib/dynamic_migrations/postgres/server/database/schema/enums.rb
123
135
  - lib/dynamic_migrations/postgres/server/database/schema/function.rb
124
136
  - lib/dynamic_migrations/postgres/server/database/schema/functions.rb
125
137
  - lib/dynamic_migrations/postgres/server/database/schema/table.rb