dynamic_migrations 3.6.15 → 3.6.16
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +21 -0
- data/lib/dynamic_migrations/active_record/migrators/primary_key.rb +21 -0
- data/lib/dynamic_migrations/active_record/migrators.rb +1 -0
- data/lib/dynamic_migrations/postgres/generator/primary_key.rb +32 -0
- data/lib/dynamic_migrations/postgres/generator/table.rb +20 -4
- data/lib/dynamic_migrations/postgres/generator/table_migration.rb +1 -1
- data/lib/dynamic_migrations/postgres/generator/validation.rb +0 -4
- data/lib/dynamic_migrations/postgres/generator/validation_template_base.rb +5 -3
- data/lib/dynamic_migrations/postgres/generator.rb +4 -5
- data/lib/dynamic_migrations/postgres/server/database/connection.rb +3 -1
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/functions.rb +1 -1
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/foreign_key_constraints.rb +2 -2
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/indexes.rb +2 -2
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/triggers.rb +2 -2
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/unique_constraints.rb +2 -2
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/validations.rb +2 -2
- data/lib/dynamic_migrations/postgres/server/database/differences.rb +3 -3
- data/lib/dynamic_migrations/postgres/server/database/enums_loader.rb +1 -1
- data/lib/dynamic_migrations/postgres/server/database/keys_and_unique_constraints_loader.rb +8 -0
- data/lib/dynamic_migrations/postgres/server/database/schema/function.rb +50 -1
- data/lib/dynamic_migrations/postgres/server/database/schema/table/column.rb +23 -2
- data/lib/dynamic_migrations/postgres/server/database/schema/table/trigger.rb +71 -5
- data/lib/dynamic_migrations/postgres/server/database/schema/table/validation.rb +57 -2
- data/lib/dynamic_migrations/postgres/server/database/structure_loader.rb +8 -0
- data/lib/dynamic_migrations/postgres/server/database/triggers_and_functions_loader.rb +4 -3
- data/lib/dynamic_migrations/postgres/server/database/validations_loader.rb +42 -29
- data/lib/dynamic_migrations/postgres/server/database.rb +6 -0
- data/lib/dynamic_migrations/version.rb +1 -1
- data/lib/dynamic_migrations.rb +1 -0
- data/sig/dynamic_migrations/active_record/migrators/primary_key.rbs +18 -0
- data/sig/dynamic_migrations/postgres/generator/primary_key.rbs +2 -0
- data/sig/dynamic_migrations/postgres/generator/table.rbs +2 -0
- data/sig/dynamic_migrations/postgres/generator/validation_template_base.rbs +7 -7
- data/sig/dynamic_migrations/postgres/generator.rbs +1 -1
- data/sig/dynamic_migrations/postgres/server/database/connection.rbs +1 -1
- data/sig/dynamic_migrations/postgres/server/database/keys_and_unique_constraints_loader.rbs +1 -0
- data/sig/dynamic_migrations/postgres/server/database/schema/enum.rbs +2 -2
- data/sig/dynamic_migrations/postgres/server/database/schema/enums.rbs +1 -1
- data/sig/dynamic_migrations/postgres/server/database/schema/function.rbs +9 -0
- data/sig/dynamic_migrations/postgres/server/database/schema/table/column.rbs +2 -0
- data/sig/dynamic_migrations/postgres/server/database/schema/table/trigger.rbs +9 -0
- data/sig/dynamic_migrations/postgres/server/database/schema/table/validation.rbs +6 -0
- data/sig/dynamic_migrations/postgres/server/database/structure_loader.rbs +1 -0
- data/sig/dynamic_migrations/postgres/server/database/validations_loader.rbs +1 -0
- data/sig/dynamic_migrations/postgres/server/database.rbs +1 -0
- metadata +4 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 166ee1f91202640e9ad50fd80c0cb4fade2993ba6ca873ff4bdbf207d939ce81
|
4
|
+
data.tar.gz: e23bc180aa98886aecd575a4b869d595d08f4d90136a59e7de46b7f42b6cbe11
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: e3b9df7db4f4eed952f7144c52eda7a46447d66cdb83e44fff32f97f335cfb78e03ebd87d0e000f781b8c596a21615ccff085933032c8e2534d900864b242f36
|
7
|
+
data.tar.gz: e0ce6d30f2d346dbbb69ae506674aef00dc49eefe04c48d7cf7c8e81e06fea11fe5afb33e7822e87302c1d514d8be5da16070ecbc622829e51bfecc87f650885
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,26 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [3.6.16](https://github.com/craigulliott/dynamic_migrations/compare/v3.6.15...v3.6.16) (2023-09-16)
|
4
|
+
|
5
|
+
|
6
|
+
### Bug Fixes
|
7
|
+
|
8
|
+
* adding convenience method to call all three cache rebuild methods at once ([287a73d](https://github.com/craigulliott/dynamic_migrations/commit/287a73d96c4bfa303150e3c1f65cb514569c03b6))
|
9
|
+
* allowing functions and triggers to be in different schemas ([6df3377](https://github.com/craigulliott/dynamic_migrations/commit/6df337780a9a6b6815776a1f65afd3c8325a00fd))
|
10
|
+
* always sorting column names on validations so that they match the structure loader ([3e7e646](https://github.com/craigulliott/dynamic_migrations/commit/3e7e646e834140bcce74e357e6e84c3996b9525e))
|
11
|
+
* corrected bug where we passed nil as trigger for updating trigger comment ([c7a3677](https://github.com/craigulliott/dynamic_migrations/commit/c7a3677694130125d581f8f68e56865644d5c442))
|
12
|
+
* enum values should be strings not symbols ([080e5da](https://github.com/craigulliott/dynamic_migrations/commit/080e5daaeefa1504912e2cd4f3482af82890ee08))
|
13
|
+
* fixed bug where constraint was duplicated due to pg check_constraints table allowing duplicates ([471b6f8](https://github.com/craigulliott/dynamic_migrations/commit/471b6f82fc01770e63f657a12d01d18011c69f07))
|
14
|
+
* fixing whitespace with create table migrator syntax ([5bf1a7f](https://github.com/craigulliott/dynamic_migrations/commit/5bf1a7f9f337883ca677b1a2015dd0c41a27442c))
|
15
|
+
* generating materialized views automatically when refreshing them but they don't yet exist ([471b6f8](https://github.com/craigulliott/dynamic_migrations/commit/471b6f82fc01770e63f657a12d01d18011c69f07))
|
16
|
+
* handling default comments via templates ([3e7e646](https://github.com/craigulliott/dynamic_migrations/commit/3e7e646e834140bcce74e357e6e84c3996b9525e))
|
17
|
+
* methods to refresh caches because this needs to be performed before and after migrations are generated and run ([ab72670](https://github.com/craigulliott/dynamic_migrations/commit/ab72670e5fc7d379aed86cf72be956cdc39ed620))
|
18
|
+
* more strictly validating column types data types which use enums ([3e7e646](https://github.com/craigulliott/dynamic_migrations/commit/3e7e646e834140bcce74e357e6e84c3996b9525e))
|
19
|
+
* removed code which was stripping empty lines from migrations, but inadvertently removing empty lines from within SQL statements ([3e7e646](https://github.com/craigulliott/dynamic_migrations/commit/3e7e646e834140bcce74e357e6e84c3996b9525e))
|
20
|
+
* updating action order so that its sequential based on the event manipulation type (update, insert etc.) ([3e7e646](https://github.com/craigulliott/dynamic_migrations/commit/3e7e646e834140bcce74e357e6e84c3996b9525e))
|
21
|
+
* validations should not end with a semicolon ([9e2cc8e](https://github.com/craigulliott/dynamic_migrations/commit/9e2cc8ebf1c6da8c4741c5257c6567fc9f3668a7))
|
22
|
+
* various fixes after running a variety of real migrations from platformer ([301db01](https://github.com/craigulliott/dynamic_migrations/commit/301db01397f1cb16c6c0e08e9e8c69e1f3ec799e))
|
23
|
+
|
3
24
|
## [3.6.15](https://github.com/craigulliott/dynamic_migrations/compare/v3.6.14...v3.6.15) (2023-09-14)
|
4
25
|
|
5
26
|
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module DynamicMigrations
|
2
|
+
module ActiveRecord
|
3
|
+
module Migrators
|
4
|
+
module PrimaryKey
|
5
|
+
# add a comment to the primary_key
|
6
|
+
def set_primary_key_comment table_name, primary_key_name, comment
|
7
|
+
execute <<~SQL
|
8
|
+
COMMENT ON CONSTRAINT #{primary_key_name} ON #{schema_name}.#{table_name} IS #{quote comment};
|
9
|
+
SQL
|
10
|
+
end
|
11
|
+
|
12
|
+
# remove a primary_key comment
|
13
|
+
def remove_primary_key_comment table_name, primary_key_name
|
14
|
+
execute <<~SQL
|
15
|
+
COMMENT ON CONSTRAINT #{primary_key_name} ON #{schema_name}.#{table_name} IS NULL;
|
16
|
+
SQL
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -59,6 +59,38 @@ module DynamicMigrations
|
|
59
59
|
# return the new fragments (the main reason to return them here is for the specs)
|
60
60
|
[removal_fragment, recreation_fragment]
|
61
61
|
end
|
62
|
+
|
63
|
+
# add a comment to a primary_key
|
64
|
+
def set_primary_key_comment primary_key, code_comment = nil
|
65
|
+
description = primary_key.description
|
66
|
+
|
67
|
+
if description.nil?
|
68
|
+
raise MissingDescriptionError, "Missing required description for primary_key `#{primary_key.name}` in table `#{primary_key.table.schema.name}.#{primary_key.table.name}`"
|
69
|
+
end
|
70
|
+
|
71
|
+
add_fragment schema: primary_key.table.schema,
|
72
|
+
table: primary_key.table,
|
73
|
+
migration_method: :set_primary_key_comment,
|
74
|
+
object: primary_key,
|
75
|
+
code_comment: code_comment,
|
76
|
+
migration: <<~RUBY
|
77
|
+
set_primary_key_comment :#{primary_key.table.name}, :#{primary_key.name}, <<~COMMENT
|
78
|
+
#{indent description}
|
79
|
+
COMMENT
|
80
|
+
RUBY
|
81
|
+
end
|
82
|
+
|
83
|
+
# remove the comment from a primary_key
|
84
|
+
def remove_primary_key_comment primary_key, code_comment = nil
|
85
|
+
add_fragment schema: primary_key.table.schema,
|
86
|
+
table: primary_key.table,
|
87
|
+
migration_method: :remove_primary_key_comment,
|
88
|
+
object: primary_key,
|
89
|
+
code_comment: code_comment,
|
90
|
+
migration: <<~RUBY
|
91
|
+
remove_primary_key_comment :#{primary_key.table.name}, :#{primary_key.name}
|
92
|
+
RUBY
|
93
|
+
end
|
62
94
|
end
|
63
95
|
end
|
64
96
|
end
|
@@ -93,10 +93,20 @@ module DynamicMigrations
|
|
93
93
|
lines = []
|
94
94
|
timestamps = []
|
95
95
|
columns.each do |column|
|
96
|
-
# skip the :id
|
97
|
-
|
98
|
-
|
96
|
+
# skip creating the :id column as it is handled by the table_options
|
97
|
+
# method, but add the comment if there is one
|
98
|
+
if column.name == :id
|
99
|
+
unless column.description.nil?
|
100
|
+
set_column_comment column
|
101
|
+
end
|
102
|
+
next
|
103
|
+
end
|
104
|
+
# skip creating the :created_at and :updated_at column as it is handled
|
105
|
+
# by the table_options method, but add the comments
|
99
106
|
if column.name == :created_at || column.name == :updated_at
|
107
|
+
unless column.description.nil?
|
108
|
+
set_column_comment column
|
109
|
+
end
|
100
110
|
timestamps << column.name
|
101
111
|
next
|
102
112
|
end
|
@@ -115,7 +125,7 @@ module DynamicMigrations
|
|
115
125
|
if column.description.nil?
|
116
126
|
raise NoTableColumnCommentError, "Refusing to generate create_table migration, no description was provided for `#{column.table.schema.name}`.`#{column.table.name}` column `#{column.name}`"
|
117
127
|
end
|
118
|
-
options[:comment] = <<~RUBY
|
128
|
+
options[:comment] = <<~RUBY.strip
|
119
129
|
<<~COMMENT
|
120
130
|
#{indent column.description}
|
121
131
|
COMMENT
|
@@ -163,6 +173,12 @@ module DynamicMigrations
|
|
163
173
|
elsif pk_column_names.count > 1
|
164
174
|
options << "primary_key: [:#{pk_column_names.join(", :")}]"
|
165
175
|
end
|
176
|
+
|
177
|
+
# if the primary key has a description, then add it seperately
|
178
|
+
if table.primary_key.description
|
179
|
+
set_primary_key_comment table.primary_key
|
180
|
+
end
|
181
|
+
|
166
182
|
end
|
167
183
|
|
168
184
|
options << "comment: table_comment"
|
@@ -17,7 +17,7 @@ module DynamicMigrations
|
|
17
17
|
add_structure_template [:remove_table_comment, :set_table_comment], "Tables"
|
18
18
|
add_structure_template [:add_column], "Additional Columns"
|
19
19
|
add_structure_template [:change_column, :remove_column_comment, :set_column_comment], "Update Columns"
|
20
|
-
add_structure_template [:add_primary_key], "Primary Key"
|
20
|
+
add_structure_template [:add_primary_key, :set_primary_key_comment, :remove_primary_key_comment], "Primary Key"
|
21
21
|
add_structure_template [:add_index, :set_index_comment], "Indexes"
|
22
22
|
add_structure_template [:add_foreign_key, :set_foreign_key_constraint_comment, :remove_foreign_key_constraint_comment], "Foreign Keys"
|
23
23
|
add_structure_template [:add_validation, :add_unique_constraint, :set_validation_comment, :remove_validation_comment, :set_unique_constraint_comment, :remove_unique_constraint_comment], "Validations"
|
@@ -57,10 +57,6 @@ module DynamicMigrations
|
|
57
57
|
options_syntax = options.map { |k, v| "#{k}: #{v}" }.join(", ")
|
58
58
|
|
59
59
|
validation_sql = validation.check_clause.strip
|
60
|
-
# ensure that the validation ends with a semicolon
|
61
|
-
unless validation_sql.end_with? ";"
|
62
|
-
validation_sql << ";"
|
63
|
-
end
|
64
60
|
|
65
61
|
add_fragment schema: validation.table.schema,
|
66
62
|
table: validation.table,
|
@@ -46,14 +46,16 @@ module DynamicMigrations
|
|
46
46
|
matches[:value]
|
47
47
|
end
|
48
48
|
|
49
|
-
def name_and_description_options_string default_name
|
49
|
+
def name_and_description_options_string default_name, default_comment = nil
|
50
50
|
options = {}
|
51
51
|
# we only need to provide a name if it is different than the default
|
52
52
|
unless @validation.name == default_name
|
53
53
|
options[:name] = @validation.name
|
54
54
|
end
|
55
|
-
# only provide a comment if it is not nil
|
56
|
-
|
55
|
+
# only provide a comment if it is not nil and not equal to the provided
|
56
|
+
# default_comment, if it is the same as the default then we wont want to show
|
57
|
+
# it in the migration files
|
58
|
+
unless @validation.description.nil? || @validation.description == default_comment
|
57
59
|
options[:comment] = <<~RUBY
|
58
60
|
<<~COMMENT
|
59
61
|
#{indent @validation.description || ""}
|
@@ -243,9 +243,8 @@ module DynamicMigrations
|
|
243
243
|
# This method is called from within the various modules which are included to this class.
|
244
244
|
# It locally stores all the fragments which will later be organized into different migrations.
|
245
245
|
def add_fragment migration_method:, object:, migration:, schema: nil, table: nil, code_comment: nil, dependent_table: nil, dependent_function: nil, dependent_enum: nil
|
246
|
-
# Remove any empty lines and whitespace from the beginning or the end of the migration
|
247
|
-
|
248
|
-
final_migration = strip_empty_lines(migration).strip
|
246
|
+
# Remove any empty lines and whitespace from the beginning or the end of the migration
|
247
|
+
final_migration = trim_lines migration
|
249
248
|
fragment = Fragment.new(schema&.name, table&.name, migration_method, object.name, code_comment, final_migration)
|
250
249
|
|
251
250
|
if dependent_table
|
@@ -272,8 +271,8 @@ module DynamicMigrations
|
|
272
271
|
multi_line_string.gsub("\n", "\n#{spaces}")
|
273
272
|
end
|
274
273
|
|
275
|
-
def
|
276
|
-
|
274
|
+
def trim_lines string
|
275
|
+
string.split("\n").map(&:rstrip).join("\n")
|
277
276
|
end
|
278
277
|
end
|
279
278
|
end
|
@@ -42,10 +42,12 @@ module DynamicMigrations
|
|
42
42
|
# perform work with the connection
|
43
43
|
# todo: `yield connection` would have been preferred, but rbs/steep doesnt understand that syntax
|
44
44
|
if block.is_a? Proc
|
45
|
-
block.call connection
|
45
|
+
result = block.call connection
|
46
46
|
end
|
47
47
|
# close the connection
|
48
48
|
disconnect
|
49
|
+
# return whever was returned from within the block
|
50
|
+
result
|
49
51
|
end
|
50
52
|
end
|
51
53
|
end
|
data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/functions.rb
CHANGED
@@ -33,7 +33,7 @@ module DynamicMigrations
|
|
33
33
|
|
34
34
|
# If the function exists in both the configuration and database representations
|
35
35
|
# but the definition is different then we need to update the definition.
|
36
|
-
elsif configuration_function[:
|
36
|
+
elsif configuration_function[:normalized_definition][:matches] == false
|
37
37
|
function = @database.configured_schema(schema_name).function(function_name)
|
38
38
|
@generator.update_function function
|
39
39
|
# does the description also need to be updated
|
@@ -44,9 +44,9 @@ module DynamicMigrations
|
|
44
44
|
if configuration_foreign_key_constraint[:description][:matches] == false
|
45
45
|
# if the description was removed
|
46
46
|
if configuration_foreign_key_constraint[:description].nil?
|
47
|
-
@generator.remove_foreign_key_constraint_comment
|
47
|
+
@generator.remove_foreign_key_constraint_comment updated_foreign_key_constraint
|
48
48
|
else
|
49
|
-
@generator.set_foreign_key_constraint_comment
|
49
|
+
@generator.set_foreign_key_constraint_comment updated_foreign_key_constraint
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
@@ -44,9 +44,9 @@ module DynamicMigrations
|
|
44
44
|
if configuration_index[:description][:matches] == false
|
45
45
|
# if the description was removed
|
46
46
|
if configuration_index[:description].nil?
|
47
|
-
@generator.remove_index_comment
|
47
|
+
@generator.remove_index_comment updated_index
|
48
48
|
else
|
49
|
-
@generator.set_index_comment
|
49
|
+
@generator.set_index_comment updated_index
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
@@ -44,9 +44,9 @@ module DynamicMigrations
|
|
44
44
|
if configuration_trigger[:description][:matches] == false
|
45
45
|
# if the description was removed
|
46
46
|
if configuration_trigger[:description].nil?
|
47
|
-
@generator.remove_trigger_comment
|
47
|
+
@generator.remove_trigger_comment updated_trigger
|
48
48
|
else
|
49
|
-
@generator.set_trigger_comment
|
49
|
+
@generator.set_trigger_comment updated_trigger
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
@@ -44,9 +44,9 @@ module DynamicMigrations
|
|
44
44
|
if configuration_unique_constraint[:description][:matches] == false
|
45
45
|
# if the description was removed
|
46
46
|
if configuration_unique_constraint[:description].nil?
|
47
|
-
@generator.remove_unique_constraint_comment
|
47
|
+
@generator.remove_unique_constraint_comment updated_unique_constraint
|
48
48
|
else
|
49
|
-
@generator.set_unique_constraint_comment
|
49
|
+
@generator.set_unique_constraint_comment updated_unique_constraint
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
@@ -44,9 +44,9 @@ module DynamicMigrations
|
|
44
44
|
if configuration_validation[:description][:matches] == false
|
45
45
|
# if the description was removed
|
46
46
|
if configuration_validation[:description].nil?
|
47
|
-
@generator.remove_validation_comment
|
47
|
+
@generator.remove_validation_comment updated_validation
|
48
48
|
else
|
49
|
-
@generator.set_validation_comment
|
49
|
+
@generator.set_validation_comment updated_validation
|
50
50
|
end
|
51
51
|
end
|
52
52
|
|
@@ -172,7 +172,7 @@ module DynamicMigrations
|
|
172
172
|
# the base functions
|
173
173
|
functions.each do |function_name, function|
|
174
174
|
result[function_name] = compare_record function, comparison_functions[function_name], [
|
175
|
-
:
|
175
|
+
:normalized_definition,
|
176
176
|
:description
|
177
177
|
]
|
178
178
|
end
|
@@ -249,7 +249,7 @@ module DynamicMigrations
|
|
249
249
|
:action_timing,
|
250
250
|
:event_manipulation,
|
251
251
|
:action_order,
|
252
|
-
:
|
252
|
+
:normalized_action_condition,
|
253
253
|
:parameters,
|
254
254
|
:action_orientation,
|
255
255
|
:action_reference_old_table,
|
@@ -332,7 +332,7 @@ module DynamicMigrations
|
|
332
332
|
validations.each do |name, validation|
|
333
333
|
# compare this validation to the equivilent in the comparison list
|
334
334
|
result[name] = compare_record validation, comparison_validations[name], [
|
335
|
-
:
|
335
|
+
:normalized_check_clause,
|
336
336
|
:column_names,
|
337
337
|
:description,
|
338
338
|
:deferrable,
|
@@ -22,7 +22,7 @@ module DynamicMigrations
|
|
22
22
|
rows.each do |row|
|
23
23
|
schema_name = row["schema_name"].to_sym
|
24
24
|
enum_name = row["enum_name"].to_sym
|
25
|
-
enum_value = row["enum_value"]
|
25
|
+
enum_value = row["enum_value"]
|
26
26
|
|
27
27
|
schema = schemas[schema_name] ||= {}
|
28
28
|
enum = schema[enum_name] ||= {
|
@@ -99,6 +99,14 @@ module DynamicMigrations
|
|
99
99
|
SQL
|
100
100
|
end
|
101
101
|
|
102
|
+
def refresh_database_keys_and_unique_constraints_cache
|
103
|
+
connection.exec(<<~SQL)
|
104
|
+
REFRESH MATERIALIZED VIEW public.dynamic_migrations_keys_and_unique_constraints_cache
|
105
|
+
SQL
|
106
|
+
rescue PG::UndefinedTable
|
107
|
+
create_database_keys_and_unique_constraints_cache
|
108
|
+
end
|
109
|
+
|
102
110
|
# fetch all required data from the database and build and return a
|
103
111
|
# useful hash representing the keys and indexes of your database
|
104
112
|
def fetch_keys_and_unique_constraints
|
@@ -13,6 +13,9 @@ module DynamicMigrations
|
|
13
13
|
class ExpectedDefinitionError < StandardError
|
14
14
|
end
|
15
15
|
|
16
|
+
class UnnormalizableDefinitionError < StandardError
|
17
|
+
end
|
18
|
+
|
16
19
|
attr_reader :schema
|
17
20
|
attr_reader :name
|
18
21
|
attr_reader :definition
|
@@ -59,9 +62,55 @@ module DynamicMigrations
|
|
59
62
|
|
60
63
|
def differences_descriptions other_function
|
61
64
|
method_differences_descriptions other_function, [
|
62
|
-
:
|
65
|
+
:normalized_definition
|
63
66
|
]
|
64
67
|
end
|
68
|
+
|
69
|
+
# temporarily create a function in postgres and fetch the actual
|
70
|
+
# normalized definition directly from the database
|
71
|
+
def normalized_definition
|
72
|
+
# no need to normalize definitions which originated from the database
|
73
|
+
if from_database?
|
74
|
+
definition
|
75
|
+
else
|
76
|
+
@normalized_definition ||= fetch_normalized_definition
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
private
|
81
|
+
|
82
|
+
def fetch_normalized_definition
|
83
|
+
fn_def = schema.database.with_connection do |connection|
|
84
|
+
# wrapped in a transaction just in case something here fails, because
|
85
|
+
# we don't want the function to be persisted
|
86
|
+
connection.exec("BEGIN")
|
87
|
+
|
88
|
+
# create a temporary function, from which we will fetch the normalized definition
|
89
|
+
connection.exec(<<~SQL)
|
90
|
+
CREATE OR REPLACE FUNCTION normalized_definition_temp_fn() returns trigger language plpgsql AS
|
91
|
+
$$#{definition}$$;
|
92
|
+
SQL
|
93
|
+
|
94
|
+
# get the normalzed version of the definition
|
95
|
+
rows = connection.exec(<<~SQL)
|
96
|
+
SELECT prosrc AS function_definition
|
97
|
+
FROM pg_proc
|
98
|
+
WHERE proname = 'normalized_definition_temp_fn';
|
99
|
+
SQL
|
100
|
+
|
101
|
+
# delete the temp table and close the transaction
|
102
|
+
connection.exec("ROLLBACK")
|
103
|
+
|
104
|
+
# return the normalized function definition
|
105
|
+
rows.first["function_definition"]
|
106
|
+
end
|
107
|
+
|
108
|
+
if fn_def.nil?
|
109
|
+
raise UnnormalizableDefinitionError, "Failed to nomalize action condition `#{definition}`"
|
110
|
+
end
|
111
|
+
|
112
|
+
fn_def
|
113
|
+
end
|
65
114
|
end
|
66
115
|
end
|
67
116
|
end
|
@@ -36,7 +36,11 @@ module DynamicMigrations
|
|
36
36
|
@data_type = data_type
|
37
37
|
|
38
38
|
@null = null
|
39
|
-
|
39
|
+
|
40
|
+
unless default.nil?
|
41
|
+
raise ExpectedStringError, default unless default.is_a? String
|
42
|
+
@default = default
|
43
|
+
end
|
40
44
|
|
41
45
|
unless description.nil?
|
42
46
|
raise ExpectedStringError, description unless description.is_a? String
|
@@ -50,7 +54,7 @@ module DynamicMigrations
|
|
50
54
|
unless enum.is_a? Enum
|
51
55
|
raise UnexpectedEnumError, "#{enum} is not a valid enum"
|
52
56
|
end
|
53
|
-
|
57
|
+
if (array? && @data_type != :"#{enum.full_name}[]") || (!array? && @data_type != enum.full_name)
|
54
58
|
raise UnexpectedEnumError, "enum `#{enum.full_name}` does not match this column's data type `#{@data_type}`"
|
55
59
|
end
|
56
60
|
@enum = enum
|
@@ -68,6 +72,23 @@ module DynamicMigrations
|
|
68
72
|
def array?
|
69
73
|
@data_type.end_with? "[]"
|
70
74
|
end
|
75
|
+
|
76
|
+
def enum?
|
77
|
+
!@enum.nil?
|
78
|
+
end
|
79
|
+
|
80
|
+
# sometimes this system makes temporary tables in order to fetch the normalized
|
81
|
+
# version of constraint check clauses, function definitions or trigger action conditions
|
82
|
+
# because certain data types might not yet exist, we need to use alternative types
|
83
|
+
def temp_table_data_type
|
84
|
+
if enum
|
85
|
+
:text
|
86
|
+
elsif @data_type == :citext || @data_type == :"citext[]"
|
87
|
+
:text
|
88
|
+
else
|
89
|
+
@data_type
|
90
|
+
end
|
91
|
+
end
|
71
92
|
end
|
72
93
|
end
|
73
94
|
end
|
@@ -38,6 +38,9 @@ module DynamicMigrations
|
|
38
38
|
class UnexpectedTemplateError < StandardError
|
39
39
|
end
|
40
40
|
|
41
|
+
class UnnormalizableActionConditionError < StandardError
|
42
|
+
end
|
43
|
+
|
41
44
|
attr_reader :table
|
42
45
|
attr_reader :name
|
43
46
|
attr_reader :event_manipulation
|
@@ -147,11 +150,11 @@ module DynamicMigrations
|
|
147
150
|
end
|
148
151
|
action_order
|
149
152
|
|
150
|
-
# otherwise
|
151
|
-
#
|
152
|
-
# for this triggers table
|
153
|
+
# otherwise is is computed by finding the index of the trigger within a list of
|
154
|
+
# triggers that are alphabetically sorted, all of which pertain to the same event
|
155
|
+
# manipulation (such as update, insert, etc.) for this triggers table
|
153
156
|
else
|
154
|
-
pos = @table.triggers.sort_by(&:name).index(self)
|
157
|
+
pos = @table.triggers.select { |t| t.event_manipulation == event_manipulation }.sort_by(&:name).index(self)
|
155
158
|
if pos.nil?
|
156
159
|
raise "Trigger not found in table triggers list. This should be impossible."
|
157
160
|
end
|
@@ -184,7 +187,7 @@ module DynamicMigrations
|
|
184
187
|
:event_manipulation,
|
185
188
|
:action_timing,
|
186
189
|
:action_order,
|
187
|
-
:
|
190
|
+
:normalized_action_condition,
|
188
191
|
:parameters,
|
189
192
|
:action_orientation,
|
190
193
|
:action_reference_old_table,
|
@@ -197,6 +200,69 @@ module DynamicMigrations
|
|
197
200
|
# return the combined differences
|
198
201
|
descriptions
|
199
202
|
end
|
203
|
+
|
204
|
+
# create a temporary table in postgres to represent this validation and fetch
|
205
|
+
# the actual normalized check constraint directly from the database
|
206
|
+
def normalized_action_condition
|
207
|
+
if action_condition.nil?
|
208
|
+
nil
|
209
|
+
# no need to normalize action_conditions which originated from the database
|
210
|
+
elsif from_database?
|
211
|
+
action_condition
|
212
|
+
else
|
213
|
+
ac = table.schema.database.with_connection do |connection|
|
214
|
+
# wrapped in a transaction just in case something here fails, because
|
215
|
+
# we don't want the function, temporary table or trigger to be persisted
|
216
|
+
connection.exec("BEGIN")
|
217
|
+
|
218
|
+
# create the temp table and add the expected columns and constraint
|
219
|
+
connection.exec(<<~SQL)
|
220
|
+
CREATE TEMP TABLE trigger_normalized_action_condition_temp_table (
|
221
|
+
#{table.columns.map { |column| '"' + column.name.to_s + '" ' + column.temp_table_data_type.to_s }.join(", ")}
|
222
|
+
);
|
223
|
+
SQL
|
224
|
+
|
225
|
+
# create a temporary function to trigger (triggers require a function)
|
226
|
+
connection.exec(<<~SQL)
|
227
|
+
CREATE OR REPLACE FUNCTION trigger_normalized_action_condition_temp_fn() returns trigger language plpgsql AS
|
228
|
+
$$ BEGIN END $$;
|
229
|
+
SQL
|
230
|
+
|
231
|
+
# create a temporary trigger, from which we will fetch the normalized action condition
|
232
|
+
connection.exec(<<~SQL)
|
233
|
+
CREATE TRIGGER trigger_normalized_action_condition_temp_trigger
|
234
|
+
BEFORE UPDATE ON trigger_normalized_action_condition_temp_table
|
235
|
+
FOR EACH ROW
|
236
|
+
WHEN (#{action_condition})
|
237
|
+
EXECUTE FUNCTION trigger_normalized_action_condition_temp_fn();
|
238
|
+
SQL
|
239
|
+
|
240
|
+
# get the normalzed version of the action condition
|
241
|
+
rows = connection.exec(<<~SQL)
|
242
|
+
SELECT (
|
243
|
+
regexp_match(
|
244
|
+
pg_get_triggerdef(oid),
|
245
|
+
'.{35,} WHEN ((.+)) EXECUTE FUNCTION')
|
246
|
+
)[1] as action_condition
|
247
|
+
FROM pg_trigger
|
248
|
+
WHERE tgname = 'trigger_normalized_action_condition_temp_trigger'
|
249
|
+
;
|
250
|
+
SQL
|
251
|
+
|
252
|
+
# delete the temp table and close the transaction
|
253
|
+
connection.exec("ROLLBACK")
|
254
|
+
|
255
|
+
# return the normalized action condition
|
256
|
+
rows.first["action_condition"]
|
257
|
+
end
|
258
|
+
|
259
|
+
if ac.nil?
|
260
|
+
raise UnnormalizableActionConditionError, "Failed to nomalize action condition `#{action_condition}`"
|
261
|
+
end
|
262
|
+
|
263
|
+
ac
|
264
|
+
end
|
265
|
+
end
|
200
266
|
end
|
201
267
|
end
|
202
268
|
end
|
@@ -20,6 +20,9 @@ module DynamicMigrations
|
|
20
20
|
class UnexpectedTemplateError < StandardError
|
21
21
|
end
|
22
22
|
|
23
|
+
class UnnormalizableCheckClauseError < StandardError
|
24
|
+
end
|
25
|
+
|
23
26
|
attr_reader :table
|
24
27
|
attr_reader :name
|
25
28
|
attr_reader :check_clause
|
@@ -81,19 +84,71 @@ module DynamicMigrations
|
|
81
84
|
end
|
82
85
|
|
83
86
|
def column_names
|
84
|
-
@columns.keys
|
87
|
+
@columns.keys.sort
|
85
88
|
end
|
86
89
|
|
87
90
|
def differences_descriptions other_validation
|
88
91
|
method_differences_descriptions other_validation, [
|
89
|
-
:
|
92
|
+
:normalized_check_clause,
|
90
93
|
:deferrable,
|
91
94
|
:initially_deferred
|
92
95
|
]
|
93
96
|
end
|
94
97
|
|
98
|
+
# create a temporary table in postgres to represent this validation and fetch
|
99
|
+
# the actual normalized check constraint directly from the database
|
100
|
+
def normalized_check_clause
|
101
|
+
# no need to normalize check_clauses which originated from the database
|
102
|
+
if from_database?
|
103
|
+
check_clause
|
104
|
+
else
|
105
|
+
@normalized_check_clause ||= fetch_normalized_check_clause
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
95
109
|
private
|
96
110
|
|
111
|
+
def fetch_normalized_check_clause
|
112
|
+
ncc = table.schema.database.with_connection do |connection|
|
113
|
+
# wrapped in a transaction jsut in case something here fails, because
|
114
|
+
# we don't want the temporary table to be persisted
|
115
|
+
connection.exec("BEGIN")
|
116
|
+
|
117
|
+
# create the temp table and add the expected columns and constraint
|
118
|
+
connection.exec(<<~SQL)
|
119
|
+
CREATE TEMP TABLE validation_normalized_check_clause_temp_table (
|
120
|
+
#{columns.map { |column| '"' + column.name.to_s + '" ' + column.temp_table_data_type.to_s }.join(", ")},
|
121
|
+
CONSTRAINT #{name} CHECK (#{check_clause})
|
122
|
+
);
|
123
|
+
SQL
|
124
|
+
|
125
|
+
# get the normalzed version of the constraint
|
126
|
+
rows = connection.exec(<<~SQL)
|
127
|
+
SELECT pg_get_constraintdef(pg_constraint.oid) AS check_clause
|
128
|
+
FROM pg_constraint
|
129
|
+
WHERE conrelid = 'validation_normalized_check_clause_temp_table'::regclass;
|
130
|
+
SQL
|
131
|
+
|
132
|
+
# delete the temp table and close the transaction
|
133
|
+
connection.exec("ROLLBACK")
|
134
|
+
|
135
|
+
# return the normalized check clause
|
136
|
+
rows.first["check_clause"]
|
137
|
+
end
|
138
|
+
|
139
|
+
if ncc.nil?
|
140
|
+
raise UnnormalizableCheckClauseError, "Failed to nomalize check clause `#{check_clause}`"
|
141
|
+
end
|
142
|
+
|
143
|
+
# extract the check clause from the result "CHECK(%check_clause%)"
|
144
|
+
matches = ncc.match(/\ACHECK \((?<inner_clause>.*)\)\z/)
|
145
|
+
if matches.nil?
|
146
|
+
raise UnnormalizableCheckClauseError, "Unparsable normalized check_clause #{ncc}"
|
147
|
+
end
|
148
|
+
|
149
|
+
matches[:inner_clause]
|
150
|
+
end
|
151
|
+
|
97
152
|
# used internally to set the columns from this objects initialize method
|
98
153
|
def add_column column
|
99
154
|
# assert that the provided dsl name is an array of Columns
|
@@ -66,6 +66,14 @@ module DynamicMigrations
|
|
66
66
|
SQL
|
67
67
|
end
|
68
68
|
|
69
|
+
def refresh_database_structure_cache
|
70
|
+
connection.exec(<<~SQL)
|
71
|
+
REFRESH MATERIALIZED VIEW public.dynamic_migrations_structure_cache
|
72
|
+
SQL
|
73
|
+
rescue PG::UndefinedTable
|
74
|
+
create_database_structure_cache
|
75
|
+
end
|
76
|
+
|
69
77
|
# fetch all columns from the database and build and return a
|
70
78
|
# useful hash representing the structure of your database
|
71
79
|
def fetch_structure
|
@@ -91,9 +91,10 @@ module DynamicMigrations
|
|
91
91
|
schema = schemas[event_object_schema] ||= {}
|
92
92
|
table = schema[event_object_table] ||= {}
|
93
93
|
|
94
|
-
#
|
95
|
-
|
96
|
-
|
94
|
+
# By convention (and to simplify things) we place the trigger and the triggers table in the same schema
|
95
|
+
# The function can be in a different schema (and often is, expecially for shared functions)
|
96
|
+
unless row["trigger_schema"] == row["event_object_schema"]
|
97
|
+
raise EventTriggerProcedureSchemaMismatchError, "Expected trigger and event_object to be in the same schema for trigger '#{trigger_name}'"
|
97
98
|
end
|
98
99
|
|
99
100
|
# turn the parameters into an array of strings
|
@@ -7,36 +7,35 @@ module DynamicMigrations
|
|
7
7
|
module ValidationsLoader
|
8
8
|
def create_database_validations_cache
|
9
9
|
connection.exec(<<~SQL)
|
10
|
-
CREATE MATERIALIZED VIEW public.dynamic_migrations_validations_cache
|
11
|
-
SELECT
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
10
|
+
CREATE MATERIALIZED VIEW public.dynamic_migrations_validations_cache AS
|
11
|
+
SELECT
|
12
|
+
nspname AS schema_name,
|
13
|
+
pg_constraint_class.relname AS table_name,
|
14
|
+
array_agg(columns.column_name ORDER BY columns.column_name) AS columns,
|
15
|
+
pg_get_constraintdef(pg_constraint.oid) AS check_clause,
|
16
|
+
conname AS validation_name,
|
17
|
+
obj_description(pg_constraint.oid, 'pg_constraint') AS description,
|
17
18
|
-- in case we need to update this query in a later version of DynamicMigrations
|
18
19
|
1 as table_version
|
19
|
-
FROM
|
20
|
-
JOIN
|
21
|
-
ON
|
22
|
-
|
23
|
-
|
24
|
-
JOIN
|
25
|
-
|
26
|
-
AND
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
table_constraints.constraint_name,
|
39
|
-
check_constraints.check_clause;
|
20
|
+
FROM pg_catalog.pg_constraint
|
21
|
+
INNER JOIN pg_catalog.pg_class pg_constraint_class
|
22
|
+
ON pg_constraint_class.oid = pg_constraint.conrelid
|
23
|
+
INNER JOIN pg_catalog.pg_namespace pg_constraint_namespace
|
24
|
+
ON pg_constraint_namespace.oid = connamespace
|
25
|
+
JOIN information_schema.columns
|
26
|
+
ON columns.table_schema = nspname
|
27
|
+
AND columns.table_name = pg_constraint_class.relname
|
28
|
+
AND columns.ordinal_position = ANY(pg_constraint.conkey)
|
29
|
+
WHERE
|
30
|
+
contype = 'c'
|
31
|
+
AND nspname != 'information_schema'
|
32
|
+
AND nspname != 'postgis'
|
33
|
+
AND left(nspname, 3) != 'pg_'
|
34
|
+
GROUP BY
|
35
|
+
pg_constraint.oid,
|
36
|
+
nspname,
|
37
|
+
pg_constraint_class.relname,
|
38
|
+
conname;
|
40
39
|
SQL
|
41
40
|
connection.exec(<<~SQL)
|
42
41
|
CREATE UNIQUE INDEX dynamic_migrations_validations_cache_index ON public.dynamic_migrations_validations_cache (schema_name, table_name, validation_name);
|
@@ -46,6 +45,14 @@ module DynamicMigrations
|
|
46
45
|
SQL
|
47
46
|
end
|
48
47
|
|
48
|
+
def refresh_database_validations_cache
|
49
|
+
connection.exec(<<~SQL)
|
50
|
+
REFRESH MATERIALIZED VIEW public.dynamic_migrations_validations_cache
|
51
|
+
SQL
|
52
|
+
rescue PG::UndefinedTable
|
53
|
+
create_database_validations_cache
|
54
|
+
end
|
55
|
+
|
49
56
|
# fetch all columns from the database and build and return a
|
50
57
|
# useful hash representing the validations of your database
|
51
58
|
def fetch_validations
|
@@ -70,9 +77,15 @@ module DynamicMigrations
|
|
70
77
|
|
71
78
|
validation_name = row["validation_name"].to_sym
|
72
79
|
|
80
|
+
matches = row["check_clause"].match(/\ACHECK \((?<inner_clause>.*)\)\z/)
|
81
|
+
if matches.nil?
|
82
|
+
raise StandardError, "Unparsable check_clause #{row["check_clause"]}"
|
83
|
+
end
|
84
|
+
check_clause = matches[:inner_clause]
|
85
|
+
|
73
86
|
table[validation_name] = {
|
74
87
|
columns: row["columns"].gsub(/\A\{/, "").gsub(/\}\Z/, "").split(",").map { |column_name| column_name.to_sym },
|
75
|
-
check_clause:
|
88
|
+
check_clause: check_clause,
|
76
89
|
description: row["description"],
|
77
90
|
deferrable: row["deferrable"] == "TRUE",
|
78
91
|
initially_deferred: row["initially_deferred"] == "TRUE"
|
@@ -55,6 +55,12 @@ module DynamicMigrations
|
|
55
55
|
def differences
|
56
56
|
Differences.new(self)
|
57
57
|
end
|
58
|
+
|
59
|
+
def refresh_caches
|
60
|
+
refresh_database_structure_cache
|
61
|
+
refresh_database_keys_and_unique_constraints_cache
|
62
|
+
refresh_database_validations_cache
|
63
|
+
end
|
58
64
|
end
|
59
65
|
end
|
60
66
|
end
|
data/lib/dynamic_migrations.rb
CHANGED
@@ -95,6 +95,7 @@ require "dynamic_migrations/active_record/migrators/trigger"
|
|
95
95
|
require "dynamic_migrations/active_record/migrators/table"
|
96
96
|
require "dynamic_migrations/active_record/migrators/index"
|
97
97
|
require "dynamic_migrations/active_record/migrators/enum"
|
98
|
+
require "dynamic_migrations/active_record/migrators/primary_key"
|
98
99
|
require "dynamic_migrations/active_record/migrators/column"
|
99
100
|
require "dynamic_migrations/active_record/migrators"
|
100
101
|
|
@@ -0,0 +1,18 @@
|
|
1
|
+
# TypeProf 0.21.7
|
2
|
+
|
3
|
+
# Classes
|
4
|
+
module DynamicMigrations
|
5
|
+
module ActiveRecord
|
6
|
+
module Migrators
|
7
|
+
module PrimaryKey
|
8
|
+
def set_primary_key_comment: (Symbol table_name, Symbol primary_key_name, String comment) -> void
|
9
|
+
def remove_primary_key_comment: (Symbol table_name, Symbol primary_key_name) -> void
|
10
|
+
|
11
|
+
# stubbing these out, as they are available on the module which includes this module
|
12
|
+
def execute: (String sql) -> void
|
13
|
+
def schema_name: () -> Symbol
|
14
|
+
def quote: (String str) -> String
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
@@ -8,6 +8,8 @@ module DynamicMigrations
|
|
8
8
|
def add_primary_key: (Postgres::Server::Database::Schema::Table::PrimaryKey primary_key, ?String? code_comment) -> Fragment
|
9
9
|
def remove_primary_key: (Postgres::Server::Database::Schema::Table::PrimaryKey primary_key, ?String? code_comment) -> Fragment
|
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
|
+
def set_primary_key_comment: (Postgres::Server::Database::Schema::Table::PrimaryKey primary_key, ?String? code_comment) -> Fragment
|
12
|
+
def remove_primary_key_comment: (Postgres::Server::Database::Schema::Table::PrimaryKey primary_key, ?String? code_comment) -> Fragment
|
11
13
|
|
12
14
|
# these come from the generator object (which this module is included into)
|
13
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
|
@@ -13,6 +13,8 @@ module DynamicMigrations
|
|
13
13
|
# these come from the generator object (which this module is included into)
|
14
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 add_column: (Postgres::Server::Database::Schema::Table::Column column, ?String? code_comment) -> Fragment
|
16
|
+
def set_column_comment: (Postgres::Server::Database::Schema::Table::Column column, ?String? code_comment) -> Fragment
|
17
|
+
def set_primary_key_comment: (Postgres::Server::Database::Schema::Table::PrimaryKey primary_key, ?String? code_comment) -> Fragment
|
16
18
|
|
17
19
|
def indent: (String migration, ?Integer levels) -> String
|
18
20
|
|
@@ -6,20 +6,20 @@ module DynamicMigrations
|
|
6
6
|
class Generator
|
7
7
|
class ValidationTemplateBase
|
8
8
|
|
9
|
-
attr_reader validation:
|
9
|
+
attr_reader validation: Postgres::Server::Database::Schema::Table::Validation
|
10
10
|
attr_reader code_comment: String?
|
11
11
|
|
12
|
-
def initialize: (
|
12
|
+
def initialize: (Postgres::Server::Database::Schema::Table::Validation validation, String? code_comment) -> void
|
13
13
|
|
14
14
|
# abstract method (should actually be added to child classes)
|
15
15
|
def fragment_arguments: -> {schema: Postgres::Server::Database::Schema, table: Postgres::Server::Database::Schema::Table, migration_method: Symbol, object: untyped, code_comment: String?, migration: String, dependent_function: Postgres::Server::Database::Schema::Function?}
|
16
16
|
|
17
17
|
private
|
18
|
-
def assert_not_deferred!: ->
|
19
|
-
def assert_column_count!: (?Integer count) ->
|
20
|
-
def first_column: ->
|
21
|
-
def value_from_check_clause: (
|
22
|
-
def name_and_description_options_string: (
|
18
|
+
def assert_not_deferred!: -> void
|
19
|
+
def assert_column_count!: (?Integer count) -> void
|
20
|
+
def first_column: -> Postgres::Server::Database::Schema::Table::Column
|
21
|
+
def value_from_check_clause: (Regexp regex) -> untyped
|
22
|
+
def name_and_description_options_string: (Symbol default_name, ?String? default_comment) -> String?
|
23
23
|
def indent: (String multi_line_string, ?Integer levels) -> String
|
24
24
|
|
25
25
|
class TemplateError < StandardError
|
@@ -31,9 +31,9 @@ module DynamicMigrations
|
|
31
31
|
def supported_migration_method?: (Symbol migration_method) -> bool
|
32
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
|
-
def strip_empty_lines: (String migration) -> String
|
35
34
|
def tsort_each_node: -> Enumerator[untyped, untyped]
|
36
35
|
def tsort_each_child: (untyped node) -> untyped
|
36
|
+
def trim_lines: (String migration) -> String
|
37
37
|
|
38
38
|
class ExpectedSymbolError < StandardError
|
39
39
|
end
|
@@ -8,7 +8,7 @@ module DynamicMigrations
|
|
8
8
|
def connect: -> PG::Connection
|
9
9
|
def connection: -> PG::Connection
|
10
10
|
def disconnect: -> void
|
11
|
-
def with_connection: ->
|
11
|
+
def with_connection: -> untyped
|
12
12
|
|
13
13
|
# these come from the database object (which this module is included into)
|
14
14
|
def name: -> Symbol
|
@@ -5,6 +5,7 @@ module DynamicMigrations
|
|
5
5
|
module KeysAndUniqueConstraintsLoader
|
6
6
|
def create_database_keys_and_unique_constraints_cache: -> void
|
7
7
|
def fetch_keys_and_unique_constraints: -> Hash[untyped, untyped]
|
8
|
+
def refresh_database_keys_and_unique_constraints_cache: -> void
|
8
9
|
|
9
10
|
# these come from the database object (which this module is included into)
|
10
11
|
def connection: -> PG::Connection
|
@@ -9,10 +9,10 @@ module DynamicMigrations
|
|
9
9
|
class Enum < Source
|
10
10
|
attr_reader schema: Schema
|
11
11
|
attr_reader name: Symbol
|
12
|
-
attr_reader values: Array[
|
12
|
+
attr_reader values: Array[String]
|
13
13
|
attr_reader description: String?
|
14
14
|
attr_reader columns: Array[Table::Column]
|
15
|
-
def initialize: (database_or_configuration source, Schema schema, Symbol name, Array[
|
15
|
+
def initialize: (database_or_configuration source, Schema schema, Symbol name, Array[String] values, ?description: String?) -> void
|
16
16
|
def full_name: -> Symbol
|
17
17
|
def has_description?: -> bool
|
18
18
|
def add_column: (Schema::Table::Column column) -> void
|
@@ -9,7 +9,7 @@ module DynamicMigrations
|
|
9
9
|
module Enums
|
10
10
|
@enums: Hash[Symbol, Enum]
|
11
11
|
|
12
|
-
def add_enum: (Symbol enum_name, Array[
|
12
|
+
def add_enum: (Symbol enum_name, Array[String] values, ?description: String?) -> nil
|
13
13
|
def enum: (Symbol enum_name) -> Enum
|
14
14
|
def has_enum?: (Symbol enum_name) -> bool
|
15
15
|
def enums: -> Array[Enum]
|
@@ -7,6 +7,8 @@ module DynamicMigrations
|
|
7
7
|
class Database
|
8
8
|
class Schema
|
9
9
|
class Function < Source
|
10
|
+
@normalized_definition: String?
|
11
|
+
|
10
12
|
attr_reader schema: Schema
|
11
13
|
attr_reader name: Symbol
|
12
14
|
attr_reader definition: String
|
@@ -16,12 +18,19 @@ module DynamicMigrations
|
|
16
18
|
def has_description?: -> bool
|
17
19
|
def add_trigger: (Schema::Table::Trigger trigger) -> void
|
18
20
|
def differences_descriptions: (Function other_function) -> Array[String]
|
21
|
+
def normalized_definition: -> String
|
22
|
+
|
23
|
+
private
|
24
|
+
def fetch_normalized_definition: -> String
|
19
25
|
|
20
26
|
class ExpectedSchemaError < StandardError
|
21
27
|
end
|
22
28
|
|
23
29
|
class ExpectedDefinitionError < StandardError
|
24
30
|
end
|
31
|
+
|
32
|
+
class UnnormalizableDefinitionError < StandardError
|
33
|
+
end
|
25
34
|
end
|
26
35
|
end
|
27
36
|
end
|
@@ -18,6 +18,8 @@ module DynamicMigrations
|
|
18
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
|
19
19
|
def has_description?: -> bool
|
20
20
|
def array?: -> bool
|
21
|
+
def enum?: -> bool
|
22
|
+
def temp_table_data_type: -> Symbol
|
21
23
|
|
22
24
|
class ExpectedTableError < StandardError
|
23
25
|
end
|
@@ -9,6 +9,8 @@ module DynamicMigrations
|
|
9
9
|
class Table
|
10
10
|
class Trigger < Source
|
11
11
|
@action_order: Integer?
|
12
|
+
@normalized_action_condition: String?
|
13
|
+
|
12
14
|
attr_reader table: Table
|
13
15
|
attr_reader name: Symbol
|
14
16
|
attr_reader event_manipulation: Symbol
|
@@ -26,6 +28,10 @@ module DynamicMigrations
|
|
26
28
|
def action_order: -> Integer
|
27
29
|
def has_description?: -> false
|
28
30
|
def differences_descriptions: (Trigger other_trigger) -> Array[String]
|
31
|
+
def normalized_action_condition: -> String?
|
32
|
+
|
33
|
+
private
|
34
|
+
def fetch_normalized_action_condition: -> String
|
29
35
|
|
30
36
|
class ExpectedTableError < StandardError
|
31
37
|
end
|
@@ -56,6 +62,9 @@ module DynamicMigrations
|
|
56
62
|
|
57
63
|
class UnexpectedTemplateError < StandardError
|
58
64
|
end
|
65
|
+
|
66
|
+
class UnnormalizableActionConditionError < StandardError
|
67
|
+
end
|
59
68
|
end
|
60
69
|
end
|
61
70
|
end
|
@@ -6,6 +6,7 @@ module DynamicMigrations
|
|
6
6
|
class Table
|
7
7
|
class Validation < Source
|
8
8
|
@columns: Hash[Symbol, Column]
|
9
|
+
@normalized_check_clause: String?
|
9
10
|
|
10
11
|
attr_reader table: Table
|
11
12
|
attr_reader name: Symbol
|
@@ -20,8 +21,11 @@ module DynamicMigrations
|
|
20
21
|
def column_names: -> Array[Symbol]
|
21
22
|
def has_description?: -> bool
|
22
23
|
def differences_descriptions: (Validation other_validation) -> Array[String]
|
24
|
+
def normalized_check_clause: -> String
|
23
25
|
|
24
26
|
private
|
27
|
+
def fetch_normalized_check_clause: -> String
|
28
|
+
|
25
29
|
def add_column: (Column column) -> void
|
26
30
|
|
27
31
|
class ExpectedTableError < StandardError
|
@@ -39,6 +43,8 @@ module DynamicMigrations
|
|
39
43
|
class UnexpectedTemplateError < StandardError
|
40
44
|
end
|
41
45
|
|
46
|
+
class UnnormalizableCheckClauseError < StandardError
|
47
|
+
end
|
42
48
|
end
|
43
49
|
end
|
44
50
|
end
|
@@ -8,6 +8,7 @@ module DynamicMigrations
|
|
8
8
|
def recursively_load_database_structure: -> void
|
9
9
|
def fetch_schema_names: -> Array[String]
|
10
10
|
def fetch_table_names: (Symbol schema_name) -> Array[String]
|
11
|
+
def refresh_database_structure_cache: -> void
|
11
12
|
|
12
13
|
# these come from the database object (which this module is included into)
|
13
14
|
def connection: -> PG::Connection
|
@@ -5,6 +5,7 @@ module DynamicMigrations
|
|
5
5
|
module ValidationsLoader
|
6
6
|
def create_database_validations_cache: -> void
|
7
7
|
def fetch_validations: -> Hash[untyped, untyped]
|
8
|
+
def refresh_database_validations_cache: -> void
|
8
9
|
|
9
10
|
# these come from the database object (which this module is included into)
|
10
11
|
def connection: -> PG::Connection
|
@@ -25,6 +25,7 @@ module DynamicMigrations
|
|
25
25
|
def initialize: (Server server, Symbol name) -> void
|
26
26
|
def schema: (Symbol schema_name, database_or_configuration source) -> untyped
|
27
27
|
def differences: -> Differences
|
28
|
+
def refresh_caches: -> void
|
28
29
|
|
29
30
|
class ExpectedServerError < StandardError
|
30
31
|
end
|
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.6.
|
4
|
+
version: 3.6.16
|
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-09-
|
11
|
+
date: 2023-09-16 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pg
|
@@ -71,6 +71,7 @@ files:
|
|
71
71
|
- lib/dynamic_migrations/active_record/migrators/foreign_key_constraint.rb
|
72
72
|
- lib/dynamic_migrations/active_record/migrators/function.rb
|
73
73
|
- lib/dynamic_migrations/active_record/migrators/index.rb
|
74
|
+
- lib/dynamic_migrations/active_record/migrators/primary_key.rb
|
74
75
|
- lib/dynamic_migrations/active_record/migrators/table.rb
|
75
76
|
- lib/dynamic_migrations/active_record/migrators/trigger.rb
|
76
77
|
- lib/dynamic_migrations/active_record/migrators/unique_constraint.rb
|
@@ -162,6 +163,7 @@ files:
|
|
162
163
|
- sig/dynamic_migrations/active_record/migrators/foreign_key_constraint.rbs
|
163
164
|
- sig/dynamic_migrations/active_record/migrators/function.rbs
|
164
165
|
- sig/dynamic_migrations/active_record/migrators/index.rbs
|
166
|
+
- sig/dynamic_migrations/active_record/migrators/primary_key.rbs
|
165
167
|
- sig/dynamic_migrations/active_record/migrators/table.rbs
|
166
168
|
- sig/dynamic_migrations/active_record/migrators/trigger.rbs
|
167
169
|
- sig/dynamic_migrations/active_record/migrators/unique_constraint.rbs
|