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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +7 -0
- data/lib/dynamic_migrations/active_record/migrators/enum.rb +44 -0
- data/lib/dynamic_migrations/active_record/migrators.rb +1 -0
- data/lib/dynamic_migrations/postgres/generator/database_migration.rb +14 -0
- data/lib/dynamic_migrations/postgres/generator/enum.rb +75 -0
- data/lib/dynamic_migrations/postgres/generator/extension.rb +27 -0
- data/lib/dynamic_migrations/postgres/generator/migration.rb +50 -19
- data/lib/dynamic_migrations/postgres/generator/schema_migration.rb +8 -0
- data/lib/dynamic_migrations/postgres/generator/table_migration.rb +1 -16
- data/lib/dynamic_migrations/postgres/generator.rb +25 -5
- data/lib/dynamic_migrations/postgres/server/database/configured_extensions.rb +40 -0
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/extensions.rb +30 -0
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/enums.rb +73 -0
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas.rb +3 -0
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations.rb +10 -2
- data/lib/dynamic_migrations/postgres/server/database/differences.rb +55 -3
- data/lib/dynamic_migrations/postgres/server/database/enums_loader.rb +40 -0
- data/lib/dynamic_migrations/postgres/server/database/extensions_loader.rb +26 -0
- data/lib/dynamic_migrations/postgres/server/database/loaded_extensions.rb +40 -0
- data/lib/dynamic_migrations/postgres/server/database/loaded_schemas_builder.rb +13 -1
- data/lib/dynamic_migrations/postgres/server/database/schema/enum.rb +60 -0
- data/lib/dynamic_migrations/postgres/server/database/schema/enums.rb +63 -0
- data/lib/dynamic_migrations/postgres/server/database/schema/function.rb +1 -1
- data/lib/dynamic_migrations/postgres/server/database/schema.rb +2 -0
- data/lib/dynamic_migrations/postgres/server/database/structure_loader.rb +1 -1
- data/lib/dynamic_migrations/postgres/server/database.rb +6 -0
- data/lib/dynamic_migrations/version.rb +1 -1
- data/lib/dynamic_migrations.rb +12 -0
- metadata +14 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4175e35ddf2a941304c9efec0400c7ed6d933bf982d3744eb45f2891d6806ec6
|
4
|
+
data.tar.gz: c78c493bf1660d8b2eb36fe355a07869b8ef2fdbc4a05527da51e27b56dcfa2e
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
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
|
@@ -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"
|
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"
|
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}"
|
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}"
|
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}"
|
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}"
|
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
|
-
|
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
|
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
|
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
|
data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/enums.rb
ADDED
@@ -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:
|
36
|
-
|
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
|
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
|
@@ -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
|
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
|
data/lib/dynamic_migrations.rb
CHANGED
@@ -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.
|
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-
|
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
|