dynamic_migrations 3.6.15 → 3.7.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +37 -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 +51 -2
- data/lib/dynamic_migrations/postgres/server/database/schema/table/column.rb +29 -2
- data/lib/dynamic_migrations/postgres/server/database/schema/table/foreign_key_constraint.rb +4 -7
- data/lib/dynamic_migrations/postgres/server/database/schema/table/foreign_key_constraints.rb +5 -0
- data/lib/dynamic_migrations/postgres/server/database/schema/table/trigger.rb +72 -6
- data/lib/dynamic_migrations/postgres/server/database/schema/table/validation.rb +95 -12
- data/lib/dynamic_migrations/postgres/server/database/schema/table/validations.rb +1 -1
- data/lib/dynamic_migrations/postgres/server/database/schema/table.rb +2 -0
- data/lib/dynamic_migrations/postgres/server/database/structure_loader.rb +9 -1
- 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 +4 -0
- data/sig/dynamic_migrations/postgres/server/database/schema/table/foreign_key_constraint.rbs +0 -3
- data/sig/dynamic_migrations/postgres/server/database/schema/table/foreign_key_constraints.rbs +1 -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 +9 -1
- data/sig/dynamic_migrations/postgres/server/database/schema/table/validations.rbs +1 -1
- data/sig/dynamic_migrations/postgres/server/database/schema/table.rbs +1 -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: 22fd29f59924e820da26858d1cf6caf04b03985ecc2fafd5f49205f5a0c2b34e
|
4
|
+
data.tar.gz: a8164cec22385ede8954df04e86c866bdb9d1ae4d420ba9107353f96e1a525e8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ec4eb2339d1ce110393eae8747c9e2aabee426d58a4e3caca8e01b7dd48ddfe99291ab903c9c7ba2e474a8b509a7185850132c1934f512c8ebe710e763243ba9
|
7
|
+
data.tar.gz: 50076bbed1405f301476ac49f0886207f9fde401c47af062fafa4095139cd3287699b8054cac4583b97422180f8fb3be935d94ac87b1ccd071a293972811eec7
|
data/CHANGELOG.md
CHANGED
@@ -1,5 +1,42 @@
|
|
1
1
|
# Changelog
|
2
2
|
|
3
|
+
## [3.7.0](https://github.com/craigulliott/dynamic_migrations/compare/v3.6.16...v3.7.0) (2023-09-27)
|
4
|
+
|
5
|
+
|
6
|
+
### Features
|
7
|
+
|
8
|
+
* providing access to foreign key constraints from both sides of the association ([48dcf1c](https://github.com/craigulliott/dynamic_migrations/commit/48dcf1cd4cdb23bc37da3e47b00f8007b8bc0f8a))
|
9
|
+
|
10
|
+
|
11
|
+
### Bug Fixes
|
12
|
+
|
13
|
+
* allowing foreign keys to the same table because they are valid and sometimes useful ([0566384](https://github.com/craigulliott/dynamic_migrations/commit/0566384a4cfeade757d9806059035477f7c41ee2))
|
14
|
+
* lazy loading column names for validations when they were configured with a nil value for columns ([439200e](https://github.com/craigulliott/dynamic_migrations/commit/439200efdedf74dddc852bf9bd35e81c1f6b4336))
|
15
|
+
* providing convenience method to retrieve columns base data type from array columns ([cd3d9bf](https://github.com/craigulliott/dynamic_migrations/commit/cd3d9bf06682335a890d9b11133d397d7bcd50af))
|
16
|
+
* semi colon at the end of function definitions is now optional ([ca9b3aa](https://github.com/craigulliott/dynamic_migrations/commit/ca9b3aa04da23605ff61b2ec14baed927145d2c3))
|
17
|
+
* structure loader was not identifying enums properly ([95276d3](https://github.com/craigulliott/dynamic_migrations/commit/95276d33f98f41eca9a9467bb6abeb458a37f16b))
|
18
|
+
|
19
|
+
## [3.6.16](https://github.com/craigulliott/dynamic_migrations/compare/v3.6.15...v3.6.16) (2023-09-16)
|
20
|
+
|
21
|
+
|
22
|
+
### Bug Fixes
|
23
|
+
|
24
|
+
* adding convenience method to call all three cache rebuild methods at once ([287a73d](https://github.com/craigulliott/dynamic_migrations/commit/287a73d96c4bfa303150e3c1f65cb514569c03b6))
|
25
|
+
* allowing functions and triggers to be in different schemas ([6df3377](https://github.com/craigulliott/dynamic_migrations/commit/6df337780a9a6b6815776a1f65afd3c8325a00fd))
|
26
|
+
* always sorting column names on validations so that they match the structure loader ([3e7e646](https://github.com/craigulliott/dynamic_migrations/commit/3e7e646e834140bcce74e357e6e84c3996b9525e))
|
27
|
+
* corrected bug where we passed nil as trigger for updating trigger comment ([c7a3677](https://github.com/craigulliott/dynamic_migrations/commit/c7a3677694130125d581f8f68e56865644d5c442))
|
28
|
+
* enum values should be strings not symbols ([080e5da](https://github.com/craigulliott/dynamic_migrations/commit/080e5daaeefa1504912e2cd4f3482af82890ee08))
|
29
|
+
* fixed bug where constraint was duplicated due to pg check_constraints table allowing duplicates ([471b6f8](https://github.com/craigulliott/dynamic_migrations/commit/471b6f82fc01770e63f657a12d01d18011c69f07))
|
30
|
+
* fixing whitespace with create table migrator syntax ([5bf1a7f](https://github.com/craigulliott/dynamic_migrations/commit/5bf1a7f9f337883ca677b1a2015dd0c41a27442c))
|
31
|
+
* generating materialized views automatically when refreshing them but they don't yet exist ([471b6f8](https://github.com/craigulliott/dynamic_migrations/commit/471b6f82fc01770e63f657a12d01d18011c69f07))
|
32
|
+
* handling default comments via templates ([3e7e646](https://github.com/craigulliott/dynamic_migrations/commit/3e7e646e834140bcce74e357e6e84c3996b9525e))
|
33
|
+
* 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))
|
34
|
+
* more strictly validating column types data types which use enums ([3e7e646](https://github.com/craigulliott/dynamic_migrations/commit/3e7e646e834140bcce74e357e6e84c3996b9525e))
|
35
|
+
* 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))
|
36
|
+
* 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))
|
37
|
+
* validations should not end with a semicolon ([9e2cc8e](https://github.com/craigulliott/dynamic_migrations/commit/9e2cc8ebf1c6da8c4741c5257c6567fc9f3668a7))
|
38
|
+
* various fixes after running a variety of real migrations from platformer ([301db01](https://github.com/craigulliott/dynamic_migrations/commit/301db01397f1cb16c6c0e08e9e8c69e1f3ec799e))
|
39
|
+
|
3
40
|
## [3.6.15](https://github.com/craigulliott/dynamic_migrations/compare/v3.6.14...v3.6.15) (2023-09-14)
|
4
41
|
|
5
42
|
|
@@ -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
|
@@ -31,7 +34,7 @@ module DynamicMigrations
|
|
31
34
|
raise ExpectedSymbolError, name unless name.is_a? Symbol
|
32
35
|
@name = name
|
33
36
|
|
34
|
-
unless definition.is_a?(String) && definition.strip != "" && definition.strip.end_with?("END;")
|
37
|
+
unless definition.is_a?(String) && definition.strip != "" && definition.strip.end_with?("END;", "END")
|
35
38
|
raise ExpectedDefinitionError, "Definition must be a string, and end with `END;`. Definition provided:\n#{definition}"
|
36
39
|
end
|
37
40
|
@definition = definition.strip
|
@@ -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,29 @@ 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
|
+
# for arrays returns the column type without the array brackets, for non arrays
|
81
|
+
# jsut returnms the column type
|
82
|
+
def base_data_type
|
83
|
+
array? ? @data_type[0..-3]&.to_sym : @data_type
|
84
|
+
end
|
85
|
+
|
86
|
+
# sometimes this system makes temporary tables in order to fetch the normalized
|
87
|
+
# version of constraint check clauses, function definitions or trigger action conditions
|
88
|
+
# because certain data types might not yet exist, we need to use alternative types
|
89
|
+
def temp_table_data_type
|
90
|
+
if enum
|
91
|
+
:text
|
92
|
+
elsif @data_type == :citext || @data_type == :"citext[]"
|
93
|
+
:text
|
94
|
+
else
|
95
|
+
@data_type
|
96
|
+
end
|
97
|
+
end
|
71
98
|
end
|
72
99
|
end
|
73
100
|
end
|
@@ -14,9 +14,6 @@ module DynamicMigrations
|
|
14
14
|
class ExpectedArrayOfColumnsError < StandardError
|
15
15
|
end
|
16
16
|
|
17
|
-
class ExpectedDifferentTablesError < StandardError
|
18
|
-
end
|
19
|
-
|
20
17
|
class DuplicateColumnError < StandardError
|
21
18
|
end
|
22
19
|
|
@@ -49,14 +46,14 @@ module DynamicMigrations
|
|
49
46
|
raise ExpectedArrayOfColumnsError
|
50
47
|
end
|
51
48
|
|
52
|
-
if table.name == foreign_table.name && table.schema.name == foreign_table.schema.name
|
53
|
-
raise ExpectedDifferentTablesError
|
54
|
-
end
|
55
|
-
|
56
49
|
# tables must be set before the columns are added
|
57
50
|
@table = table
|
58
51
|
@foreign_table = foreign_table
|
59
52
|
|
53
|
+
# add this foreign_key_constraint to the remote table (so we can always find
|
54
|
+
# these from both sides of the association)
|
55
|
+
@foreign_table.add_remote_foreign_key_constraint self
|
56
|
+
|
60
57
|
@columns = {}
|
61
58
|
columns.each do |column|
|
62
59
|
add_column column
|
data/lib/dynamic_migrations/postgres/server/database/schema/table/foreign_key_constraints.rb
CHANGED
@@ -61,6 +61,11 @@ module DynamicMigrations
|
|
61
61
|
# return the new foreign_key_constraint
|
62
62
|
new_foreign_key_constraint
|
63
63
|
end
|
64
|
+
|
65
|
+
# called automatically from the other side of the foreign key constraint to keep track of the foreign key from both sides
|
66
|
+
def add_remote_foreign_key_constraint foreign_key_constraint
|
67
|
+
@remote_foreign_key_constraints << foreign_key_constraint
|
68
|
+
end
|
64
69
|
end
|
65
70
|
end
|
66
71
|
end
|