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