dynamic_migrations 2.1.0 → 3.0.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 +23 -0
- data/lib/dynamic_migrations/active_record/migrators/column.rb +21 -0
- data/lib/dynamic_migrations/active_record/migrators/foreign_key_constraint.rb +112 -0
- data/lib/dynamic_migrations/active_record/migrators/function.rb +108 -0
- data/lib/dynamic_migrations/active_record/migrators/index.rb +27 -0
- data/lib/dynamic_migrations/active_record/migrators/schema.rb +21 -0
- data/lib/dynamic_migrations/active_record/migrators/table.rb +21 -0
- data/lib/dynamic_migrations/active_record/migrators/trigger.rb +109 -0
- data/lib/dynamic_migrations/active_record/migrators/unique_constraint.rb +63 -0
- data/lib/dynamic_migrations/active_record/migrators/validation.rb +67 -0
- data/lib/dynamic_migrations/active_record/migrators.rb +64 -0
- data/lib/dynamic_migrations/name_helper.rb +13 -0
- data/lib/dynamic_migrations/postgres/generator/column.rb +92 -0
- data/lib/dynamic_migrations/postgres/generator/foreign_key_constraint.rb +84 -0
- data/lib/dynamic_migrations/postgres/generator/fragment.rb +30 -0
- data/lib/dynamic_migrations/postgres/generator/function.rb +77 -0
- data/lib/dynamic_migrations/postgres/generator/index.rb +101 -0
- data/lib/dynamic_migrations/postgres/generator/primary_key.rb +55 -0
- data/lib/dynamic_migrations/postgres/generator/schema.rb +19 -0
- data/lib/dynamic_migrations/postgres/generator/schema_migrations/section.rb +37 -0
- data/lib/dynamic_migrations/postgres/generator/schema_migrations.rb +92 -0
- data/lib/dynamic_migrations/postgres/generator/table.rb +122 -0
- data/lib/dynamic_migrations/postgres/generator/trigger.rb +101 -0
- data/lib/dynamic_migrations/postgres/generator/unique_constraint.rb +79 -0
- data/lib/dynamic_migrations/postgres/generator/validation.rb +87 -0
- data/lib/dynamic_migrations/postgres/generator.rb +359 -0
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/functions.rb +68 -0
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/columns.rb +72 -0
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/foreign_key_constraints.rb +73 -0
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/indexes.rb +73 -0
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/primary_key.rb +49 -0
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/triggers.rb +73 -0
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/unique_constraints.rb +73 -0
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/validations.rb +73 -0
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables.rb +80 -0
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas.rb +48 -0
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations.rb +59 -0
- data/lib/dynamic_migrations/postgres/server/database/differences.rb +76 -16
- data/lib/dynamic_migrations/postgres/server/database/keys_and_unique_constraints_loader.rb +35 -9
- data/lib/dynamic_migrations/postgres/server/database/loaded_schemas_builder.rb +50 -26
- data/lib/dynamic_migrations/postgres/server/database/schema/function.rb +69 -0
- data/lib/dynamic_migrations/postgres/server/database/schema/functions.rb +63 -0
- data/lib/dynamic_migrations/postgres/server/database/schema/table/column.rb +6 -44
- data/lib/dynamic_migrations/postgres/server/database/schema/table/columns.rb +1 -1
- data/lib/dynamic_migrations/postgres/server/database/schema/table/foreign_key_constraint.rb +40 -5
- data/lib/dynamic_migrations/postgres/server/database/schema/table/index.rb +23 -9
- data/lib/dynamic_migrations/postgres/server/database/schema/table/primary_key.rb +21 -6
- data/lib/dynamic_migrations/postgres/server/database/schema/table/trigger.rb +151 -0
- data/lib/dynamic_migrations/postgres/server/database/schema/table/triggers.rb +66 -0
- data/lib/dynamic_migrations/postgres/server/database/schema/table/unique_constraint.rb +19 -9
- data/lib/dynamic_migrations/postgres/server/database/schema/table/validation.rb +20 -1
- data/lib/dynamic_migrations/postgres/server/database/schema/table.rb +15 -5
- data/lib/dynamic_migrations/postgres/server/database/schema/tables.rb +63 -0
- data/lib/dynamic_migrations/postgres/server/database/schema.rb +3 -49
- data/lib/dynamic_migrations/postgres/server/database/source.rb +21 -0
- data/lib/dynamic_migrations/postgres/server/database/structure_loader.rb +22 -112
- data/lib/dynamic_migrations/postgres/server/database/triggers_and_functions_loader.rb +131 -0
- data/lib/dynamic_migrations/postgres/server/database/validations_loader.rb +10 -4
- data/lib/dynamic_migrations/postgres/server/database.rb +2 -1
- data/lib/dynamic_migrations/postgres/server.rb +6 -0
- data/lib/dynamic_migrations/postgres.rb +1 -1
- data/lib/dynamic_migrations/version.rb +1 -1
- data/lib/dynamic_migrations.rb +47 -4
- metadata +44 -3
- data/lib/dynamic_migrations/postgres/data_types.rb +0 -320
@@ -0,0 +1,49 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DynamicMigrations
|
4
|
+
module Postgres
|
5
|
+
class Server
|
6
|
+
class Database
|
7
|
+
class Differences
|
8
|
+
class ToMigrations
|
9
|
+
module Schemas
|
10
|
+
module Tables
|
11
|
+
module PrimaryKey
|
12
|
+
def process_primary_key schema_name, table_name, configuration_primary_key, database_primary_key
|
13
|
+
configuration_primary_key_exists = configuration_primary_key && configuration_primary_key[:exists]
|
14
|
+
database_primary_key_exists = database_primary_key && database_primary_key[:exists]
|
15
|
+
|
16
|
+
# If the primary_key exists in the configuration but not in the database
|
17
|
+
# then we have to create it.
|
18
|
+
if configuration_primary_key_exists == true && database_primary_key_exists == false
|
19
|
+
# a migration to create the primary_key
|
20
|
+
primary_key = @database.configured_schema(schema_name).table(table_name).primary_key
|
21
|
+
@generator.add_primary_key primary_key
|
22
|
+
|
23
|
+
# If the schema exists in the database but not in the configuration
|
24
|
+
# then we need to delete it.
|
25
|
+
elsif configuration_primary_key_exists == false && database_primary_key_exists == true
|
26
|
+
# a migration to create the primary_key
|
27
|
+
primary_key = @database.loaded_schema(schema_name).table(table_name).primary_key
|
28
|
+
@generator.remove_primary_key primary_key
|
29
|
+
|
30
|
+
# If the primary_key exists in both the configuration and database representations
|
31
|
+
elsif configuration_primary_key_exists == true && database_primary_key_exists == true
|
32
|
+
# If the definition (i.e. the column names) is different then we need to update the primary key.
|
33
|
+
if configuration_primary_key.except(:exists, :description).filter { |name, attributes| attributes[:matches] == false }.any?
|
34
|
+
# recreate the primary_key
|
35
|
+
original_primary_key = @database.loaded_schema(schema_name).table(table_name).primary_key
|
36
|
+
updated_primary_key = @database.configured_schema(schema_name).table(table_name).primary_key
|
37
|
+
@generator.recreate_primary_key original_primary_key, updated_primary_key
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DynamicMigrations
|
4
|
+
module Postgres
|
5
|
+
class Server
|
6
|
+
class Database
|
7
|
+
class Differences
|
8
|
+
class ToMigrations
|
9
|
+
module Schemas
|
10
|
+
module Tables
|
11
|
+
module Triggers
|
12
|
+
def process_triggers schema_name, table_name, configuration_triggers, database_triggers
|
13
|
+
# process all the triggers
|
14
|
+
trigger_names = (configuration_triggers.keys + database_triggers.keys).uniq
|
15
|
+
trigger_names.each do |trigger_name|
|
16
|
+
process_trigger schema_name, table_name, trigger_name, configuration_triggers[trigger_name] || {}, database_triggers[trigger_name] || {}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def process_trigger schema_name, table_name, trigger_name, configuration_trigger, database_trigger
|
21
|
+
# If the trigger exists in the configuration but not in the database
|
22
|
+
# then we have to create it.
|
23
|
+
if configuration_trigger[:exists] == true && database_trigger[:exists] == false
|
24
|
+
# a migration to create the trigger
|
25
|
+
trigger = @database.configured_schema(schema_name).table(table_name).trigger(trigger_name)
|
26
|
+
@generator.add_trigger trigger
|
27
|
+
|
28
|
+
# If the schema exists in the database but not in the configuration
|
29
|
+
# then we need to delete it.
|
30
|
+
elsif configuration_trigger[:exists] == false && database_trigger[:exists] == true
|
31
|
+
# a migration to create the trigger
|
32
|
+
trigger = @database.loaded_schema(schema_name).table(table_name).trigger(trigger_name)
|
33
|
+
@generator.remove_trigger trigger
|
34
|
+
|
35
|
+
# If the trigger exists in both the configuration and database representations
|
36
|
+
# but the definition (except description, which is handled seeprately below) is different
|
37
|
+
# then we need to update the definition.
|
38
|
+
elsif configuration_trigger.except(:exists, :description).filter { |name, attributes| attributes[:matches] == false }.any?
|
39
|
+
# recreate the trigger
|
40
|
+
original_trigger = @database.loaded_schema(schema_name).table(table_name).trigger(trigger_name)
|
41
|
+
updated_trigger = @database.configured_schema(schema_name).table(table_name).trigger(trigger_name)
|
42
|
+
@generator.recreate_trigger original_trigger, updated_trigger
|
43
|
+
# does the description also need to be updated
|
44
|
+
if configuration_trigger[:description][:matches] == false
|
45
|
+
# if the description was removed
|
46
|
+
if configuration_trigger[:description].nil?
|
47
|
+
@generator.remove_trigger_comment trigger
|
48
|
+
else
|
49
|
+
@generator.set_trigger_comment trigger
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# If the trigger exists in both the configuration and database representations
|
54
|
+
# but the description is different then we need to update the description.
|
55
|
+
elsif configuration_trigger[:description][:matches] == false
|
56
|
+
trigger = @database.configured_schema(schema_name).table(table_name).trigger(trigger_name)
|
57
|
+
# if the description was removed
|
58
|
+
if configuration_trigger[:description].nil?
|
59
|
+
@generator.remove_trigger_comment trigger
|
60
|
+
else
|
61
|
+
@generator.set_trigger_comment trigger
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DynamicMigrations
|
4
|
+
module Postgres
|
5
|
+
class Server
|
6
|
+
class Database
|
7
|
+
class Differences
|
8
|
+
class ToMigrations
|
9
|
+
module Schemas
|
10
|
+
module Tables
|
11
|
+
module UniqueConstraints
|
12
|
+
def process_unique_constraints schema_name, table_name, configuration_unique_constraints, database_unique_constraints
|
13
|
+
# process all the unique_constraints
|
14
|
+
unique_constraint_names = (configuration_unique_constraints.keys + database_unique_constraints.keys).uniq
|
15
|
+
unique_constraint_names.each do |unique_constraint_name|
|
16
|
+
process_unique_constraint schema_name, table_name, unique_constraint_name, configuration_unique_constraints[unique_constraint_name] || {}, database_unique_constraints[unique_constraint_name] || {}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def process_unique_constraint schema_name, table_name, unique_constraint_name, configuration_unique_constraint, database_unique_constraint
|
21
|
+
# If the unique_constraint exists in the configuration but not in the database
|
22
|
+
# then we have to create it.
|
23
|
+
if configuration_unique_constraint[:exists] == true && database_unique_constraint[:exists] == false
|
24
|
+
# a migration to create the unique_constraint
|
25
|
+
unique_constraint = @database.configured_schema(schema_name).table(table_name).unique_constraint(unique_constraint_name)
|
26
|
+
@generator.add_unique_constraint unique_constraint
|
27
|
+
|
28
|
+
# If the schema exists in the database but not in the configuration
|
29
|
+
# then we need to delete it.
|
30
|
+
elsif configuration_unique_constraint[:exists] == false && database_unique_constraint[:exists] == true
|
31
|
+
# a migration to create the unique_constraint
|
32
|
+
unique_constraint = @database.loaded_schema(schema_name).table(table_name).unique_constraint(unique_constraint_name)
|
33
|
+
@generator.remove_unique_constraint unique_constraint
|
34
|
+
|
35
|
+
# If the unique_constraint exists in both the configuration and database representations
|
36
|
+
# but the definition (except description, which is handled seeprately below) is different
|
37
|
+
# then we need to update the definition.
|
38
|
+
elsif configuration_unique_constraint.except(:exists, :description).filter { |name, attributes| attributes[:matches] == false }.any?
|
39
|
+
# recreate the unique_constraint
|
40
|
+
original_unique_constraint = @database.loaded_schema(schema_name).table(table_name).unique_constraint(unique_constraint_name)
|
41
|
+
updated_unique_constraint = @database.configured_schema(schema_name).table(table_name).unique_constraint(unique_constraint_name)
|
42
|
+
@generator.recreate_unique_constraint original_unique_constraint, updated_unique_constraint
|
43
|
+
# does the description also need to be updated
|
44
|
+
if configuration_unique_constraint[:description][:matches] == false
|
45
|
+
# if the description was removed
|
46
|
+
if configuration_unique_constraint[:description].nil?
|
47
|
+
@generator.remove_unique_constraint_comment unique_constraint
|
48
|
+
else
|
49
|
+
@generator.set_unique_constraint_comment unique_constraint
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# If the unique_constraint exists in both the configuration and database representations
|
54
|
+
# but the description is different then we need to update the description.
|
55
|
+
elsif configuration_unique_constraint[:description][:matches] == false
|
56
|
+
unique_constraint = @database.configured_schema(schema_name).table(table_name).unique_constraint(unique_constraint_name)
|
57
|
+
# if the description was removed
|
58
|
+
if configuration_unique_constraint[:description].nil?
|
59
|
+
@generator.remove_unique_constraint_comment unique_constraint
|
60
|
+
else
|
61
|
+
@generator.set_unique_constraint_comment unique_constraint
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DynamicMigrations
|
4
|
+
module Postgres
|
5
|
+
class Server
|
6
|
+
class Database
|
7
|
+
class Differences
|
8
|
+
class ToMigrations
|
9
|
+
module Schemas
|
10
|
+
module Tables
|
11
|
+
module Validations
|
12
|
+
def process_validations schema_name, table_name, configuration_validations, database_validations
|
13
|
+
# process all the validations
|
14
|
+
validation_names = (configuration_validations.keys + database_validations.keys).uniq
|
15
|
+
validation_names.each do |validation_name|
|
16
|
+
process_validation schema_name, table_name, validation_name, configuration_validations[validation_name] || {}, database_validations[validation_name] || {}
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def process_validation schema_name, table_name, validation_name, configuration_validation, database_validation
|
21
|
+
# If the validation exists in the configuration but not in the database
|
22
|
+
# then we have to create it.
|
23
|
+
if configuration_validation[:exists] == true && database_validation[:exists] == false
|
24
|
+
# a migration to create the validation
|
25
|
+
validation = @database.configured_schema(schema_name).table(table_name).validation(validation_name)
|
26
|
+
@generator.add_validation validation
|
27
|
+
|
28
|
+
# If the schema exists in the database but not in the configuration
|
29
|
+
# then we need to delete it.
|
30
|
+
elsif configuration_validation[:exists] == false && database_validation[:exists] == true
|
31
|
+
# a migration to create the validation
|
32
|
+
validation = @database.loaded_schema(schema_name).table(table_name).validation(validation_name)
|
33
|
+
@generator.remove_validation validation
|
34
|
+
|
35
|
+
# If the validation exists in both the configuration and database representations
|
36
|
+
# but the definition (except description, which is handled seeprately below) is different
|
37
|
+
# then we need to update the definition.
|
38
|
+
elsif configuration_validation.except(:exists, :description).filter { |name, attributes| attributes[:matches] == false }.any?
|
39
|
+
# recreate the validation
|
40
|
+
original_validation = @database.loaded_schema(schema_name).table(table_name).validation(validation_name)
|
41
|
+
updated_validation = @database.configured_schema(schema_name).table(table_name).validation(validation_name)
|
42
|
+
@generator.recreate_validation original_validation, updated_validation
|
43
|
+
# does the description also need to be updated
|
44
|
+
if configuration_validation[:description][:matches] == false
|
45
|
+
# if the description was removed
|
46
|
+
if configuration_validation[:description].nil?
|
47
|
+
@generator.remove_validation_comment validation
|
48
|
+
else
|
49
|
+
@generator.set_validation_comment validation
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
# If the validation exists in both the configuration and database representations
|
54
|
+
# but the description is different then we need to update the description.
|
55
|
+
elsif configuration_validation[:description][:matches] == false
|
56
|
+
validation = @database.configured_schema(schema_name).table(table_name).validation(validation_name)
|
57
|
+
# if the description was removed
|
58
|
+
if configuration_validation[:description].nil?
|
59
|
+
@generator.remove_validation_comment validation
|
60
|
+
else
|
61
|
+
@generator.set_validation_comment validation
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables.rb
ADDED
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DynamicMigrations
|
4
|
+
module Postgres
|
5
|
+
class Server
|
6
|
+
class Database
|
7
|
+
class Differences
|
8
|
+
class ToMigrations
|
9
|
+
module Schemas
|
10
|
+
module Tables
|
11
|
+
def process_tables schema_name, configuration_tables, database_tables
|
12
|
+
# process all the tables
|
13
|
+
table_names = (configuration_tables.keys + database_tables.keys).uniq
|
14
|
+
table_names.each do |table_name|
|
15
|
+
process_table schema_name, table_name, configuration_tables[table_name] || {}, database_tables[table_name] || {}
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def process_table schema_name, table_name, configuration_table, database_table
|
20
|
+
# If the table exists in the configuration but not in the database
|
21
|
+
# then we have to create it.
|
22
|
+
if configuration_table[:exists] == true && database_table[:exists] == false
|
23
|
+
# a migration to create the table
|
24
|
+
table = @database.configured_schema(schema_name).table(table_name)
|
25
|
+
@generator.create_table table
|
26
|
+
|
27
|
+
# we process everything else after we create the table, because the other
|
28
|
+
# database objects are dependent on the table
|
29
|
+
process_dependents schema_name, table_name, configuration_table, {}
|
30
|
+
|
31
|
+
# If the schema exists in the database but not in the configuration
|
32
|
+
# then we need to delete it.
|
33
|
+
elsif configuration_table[:exists] == false && database_table[:exists] == true
|
34
|
+
# we process everything else before we drop the table, because the other
|
35
|
+
# database objects are dependent on the table
|
36
|
+
process_dependents schema_name, table_name, {}, database_table
|
37
|
+
|
38
|
+
# a migration to remove the table
|
39
|
+
table = @database.loaded_schema(schema_name).table(table_name)
|
40
|
+
@generator.drop_table table
|
41
|
+
|
42
|
+
# If the table exists in both the configuration and database representations
|
43
|
+
# but the description is different then we need to update the description.
|
44
|
+
elsif configuration_table[:description][:matches] == false
|
45
|
+
table = @database.configured_schema(schema_name).table(table_name)
|
46
|
+
# if the description was removed
|
47
|
+
if configuration_table[:description].nil?
|
48
|
+
@generator.remove_table_comment table
|
49
|
+
else
|
50
|
+
@generator.set_table_comment table
|
51
|
+
end
|
52
|
+
|
53
|
+
# process everything else
|
54
|
+
process_dependents schema_name, table_name, configuration_table, database_table
|
55
|
+
|
56
|
+
else
|
57
|
+
# process everything else
|
58
|
+
process_dependents schema_name, table_name, configuration_table, database_table
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def process_dependents schema_name, table_name, configuration_table, database_table
|
64
|
+
process_columns schema_name, table_name, configuration_table[:columns] || {}, database_table[:columns] || {}
|
65
|
+
process_foreign_key_constraints schema_name, table_name, configuration_table[:foreign_key_constraints] || {}, database_table[:foreign_key_constraints] || {}
|
66
|
+
process_indexes schema_name, table_name, configuration_table[:indexes] || {}, database_table[:indexes] || {}
|
67
|
+
process_triggers schema_name, table_name, configuration_table[:triggers] || {}, database_table[:triggers] || {}
|
68
|
+
process_unique_constraints schema_name, table_name, configuration_table[:unique_constraints] || {}, database_table[:unique_constraints] || {}
|
69
|
+
process_validations schema_name, table_name, configuration_table[:validations] || {}, database_table[:validations] || {}
|
70
|
+
# Process the primary key. The primary key is singular (max of one per table)
|
71
|
+
process_primary_key schema_name, table_name, configuration_table[:primary_key], database_table[:primary_key]
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DynamicMigrations
|
4
|
+
module Postgres
|
5
|
+
class Server
|
6
|
+
class Database
|
7
|
+
class Differences
|
8
|
+
class ToMigrations
|
9
|
+
module Schemas
|
10
|
+
def process_schema schema_name, configuration_schema, database_schema
|
11
|
+
# if the schema exists in the configuration but not in the database
|
12
|
+
# then we have to create it
|
13
|
+
if configuration_schema[:exists] == true && database_schema[:exists] == false
|
14
|
+
# a migration to create the schema
|
15
|
+
schema = @database.configured_schema schema_name
|
16
|
+
@generator.create_schema schema
|
17
|
+
|
18
|
+
# we process the tables and functions after we create the schema
|
19
|
+
# otherwise the schemas objects will not be able to be created
|
20
|
+
process_functions schema_name, configuration_schema[:functions], {}
|
21
|
+
process_tables schema_name, configuration_schema[:tables], {}
|
22
|
+
|
23
|
+
# if the schema exists in the database but not in the configuration
|
24
|
+
# then we need to delete it
|
25
|
+
elsif configuration_schema[:exists] == false && database_schema[:exists] == true
|
26
|
+
# we process the tables and functions before we drop the schema
|
27
|
+
# as this will drop any dependencies on the schema
|
28
|
+
process_functions schema_name, {}, database_schema[:functions]
|
29
|
+
process_tables schema_name, {}, database_schema[:tables]
|
30
|
+
|
31
|
+
# a migration to drop the schema
|
32
|
+
schema = @database.loaded_schema schema_name
|
33
|
+
@generator.drop_schema schema
|
34
|
+
|
35
|
+
# if the schema exists in both the configuration and database representations
|
36
|
+
# then we just need to process the tables and functions
|
37
|
+
else
|
38
|
+
process_functions schema_name, configuration_schema[:functions], database_schema[:functions]
|
39
|
+
process_tables schema_name, configuration_schema[:tables], database_schema[:tables]
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,59 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module DynamicMigrations
|
4
|
+
module Postgres
|
5
|
+
class Server
|
6
|
+
class Database
|
7
|
+
class Differences
|
8
|
+
class ToMigrations
|
9
|
+
class UnexpectedDatabaseObjectError < StandardError
|
10
|
+
end
|
11
|
+
|
12
|
+
class UnexpectedDifferencesObjectError < StandardError
|
13
|
+
end
|
14
|
+
|
15
|
+
include Schemas
|
16
|
+
include Schemas::Functions
|
17
|
+
include Schemas::Tables
|
18
|
+
include Schemas::Tables::Columns
|
19
|
+
include Schemas::Tables::ForeignKeyConstraints
|
20
|
+
include Schemas::Tables::Indexes
|
21
|
+
include Schemas::Tables::PrimaryKey
|
22
|
+
include Schemas::Tables::Triggers
|
23
|
+
include Schemas::Tables::UniqueConstraints
|
24
|
+
include Schemas::Tables::Validations
|
25
|
+
|
26
|
+
def initialize database, differences
|
27
|
+
raise UnexpectedDatabaseObjectError, database unless database.is_a? Database
|
28
|
+
@database = database
|
29
|
+
|
30
|
+
raise UnexpectedDifferencesObjectError, differences unless differences.is_a? Differences
|
31
|
+
@differences = differences
|
32
|
+
|
33
|
+
# the generator which will build the migrations
|
34
|
+
@generator = Generator.new
|
35
|
+
end
|
36
|
+
|
37
|
+
def migrations
|
38
|
+
# process all the schemas (we can fetch the schema names from either the
|
39
|
+
# configuration or the database object)
|
40
|
+
schema_names = differences[:configuration].keys
|
41
|
+
schema_names.each do |schema_name|
|
42
|
+
process_schema schema_name, differences[:configuration][schema_name], differences[:database][schema_name]
|
43
|
+
end
|
44
|
+
|
45
|
+
# return the migrations organized by schema
|
46
|
+
@generator.migrations
|
47
|
+
end
|
48
|
+
|
49
|
+
private
|
50
|
+
|
51
|
+
def differences
|
52
|
+
@differences_hash ||= @differences.to_h
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
@@ -11,6 +11,9 @@ module DynamicMigrations
|
|
11
11
|
class TableRequiredError < StandardError
|
12
12
|
end
|
13
13
|
|
14
|
+
class FunctionRequiredError < StandardError
|
15
|
+
end
|
16
|
+
|
14
17
|
class SchemaRequiredError < StandardError
|
15
18
|
end
|
16
19
|
|
@@ -53,9 +56,11 @@ module DynamicMigrations
|
|
53
56
|
raise SchemaRequiredError if schema.nil?
|
54
57
|
|
55
58
|
comparison_tables = comparison_schema.nil? ? {} : comparison_schema.tables_hash
|
59
|
+
comparison_functions = comparison_schema.nil? ? {} : comparison_schema.functions_hash
|
56
60
|
{
|
57
61
|
exists: true,
|
58
|
-
tables: compare_tables(schema.tables_hash, comparison_tables)
|
62
|
+
tables: compare_tables(schema.tables_hash, comparison_tables),
|
63
|
+
functions: compare_functions(schema.functions_hash, comparison_functions)
|
59
64
|
}
|
60
65
|
end
|
61
66
|
|
@@ -90,12 +95,16 @@ module DynamicMigrations
|
|
90
95
|
if comparison_table
|
91
96
|
comparison_primary_key = comparison_table.has_primary_key? ? comparison_table.primary_key : nil
|
92
97
|
comparison_columns = comparison_table.columns_hash
|
98
|
+
comparison_indexes = comparison_table.indexes_hash
|
99
|
+
comparison_triggers = comparison_table.triggers_hash
|
93
100
|
comparison_validations = comparison_table.validations_hash
|
94
101
|
comparison_foreign_key_constraints = comparison_table.foreign_key_constraints_hash
|
95
102
|
comparison_unique_constraints = comparison_table.unique_constraints_hash
|
96
103
|
else
|
97
104
|
comparison_primary_key = {}
|
98
105
|
comparison_columns = {}
|
106
|
+
comparison_indexes = {}
|
107
|
+
comparison_triggers = {}
|
99
108
|
comparison_validations = {}
|
100
109
|
comparison_foreign_key_constraints = {}
|
101
110
|
comparison_unique_constraints = {}
|
@@ -108,15 +117,41 @@ module DynamicMigrations
|
|
108
117
|
},
|
109
118
|
primary_key: compare_record(primary_key, comparison_primary_key, [
|
110
119
|
:name,
|
111
|
-
:
|
120
|
+
:column_names,
|
121
|
+
:description
|
112
122
|
]),
|
113
123
|
columns: compare_columns(table.columns_hash, comparison_columns),
|
124
|
+
indexes: compare_indexes(table.indexes_hash, comparison_indexes),
|
125
|
+
triggers: compare_triggers(table.triggers_hash, comparison_triggers),
|
114
126
|
validations: compare_validations(table.validations_hash, comparison_validations),
|
115
127
|
foreign_key_constraints: compare_foreign_key_constraints(table.foreign_key_constraints_hash, comparison_foreign_key_constraints),
|
116
128
|
unique_constraints: compare_unique_constraints(table.unique_constraints_hash, comparison_unique_constraints)
|
117
129
|
}
|
118
130
|
end
|
119
131
|
|
132
|
+
# compare two hash representations of a set of functions and return
|
133
|
+
# an object which represents the provided `functions` and any differences
|
134
|
+
# between it and the `comparison_functions`
|
135
|
+
def self.compare_functions functions, comparison_functions
|
136
|
+
result = {}
|
137
|
+
# the base functions
|
138
|
+
functions.each do |function_name, function|
|
139
|
+
result[function_name] = compare_record function, comparison_functions[function_name], [
|
140
|
+
:definition,
|
141
|
+
:description
|
142
|
+
]
|
143
|
+
end
|
144
|
+
# look for any in the comparison list which were not in the base list
|
145
|
+
comparison_functions.each do |function_name, function|
|
146
|
+
unless result.key? function_name
|
147
|
+
result[function_name] = {
|
148
|
+
exists: false
|
149
|
+
}
|
150
|
+
end
|
151
|
+
end
|
152
|
+
result
|
153
|
+
end
|
154
|
+
|
120
155
|
# compare two hash representations of a set of columns and return
|
121
156
|
# an object which represents the provided `columns` and any differences
|
122
157
|
# between it and the `comparison_columns`
|
@@ -130,16 +165,7 @@ module DynamicMigrations
|
|
130
165
|
:null,
|
131
166
|
:default,
|
132
167
|
:description,
|
133
|
-
:
|
134
|
-
:character_octet_length,
|
135
|
-
:numeric_precision,
|
136
|
-
:numeric_precision_radix,
|
137
|
-
:numeric_scale,
|
138
|
-
:datetime_precision,
|
139
|
-
:interval_type,
|
140
|
-
:udt_schema,
|
141
|
-
:udt_name,
|
142
|
-
:updatable
|
168
|
+
:interval_type
|
143
169
|
]
|
144
170
|
end
|
145
171
|
# look for any columns in the comparison list which were not in the base list
|
@@ -153,6 +179,37 @@ module DynamicMigrations
|
|
153
179
|
result
|
154
180
|
end
|
155
181
|
|
182
|
+
# compare two hash representations of a set of triggers and return
|
183
|
+
# an object which represents the provided `triggers` and any differences
|
184
|
+
# between it and the `comparison_triggers`
|
185
|
+
def self.compare_triggers triggers, comparison_triggers
|
186
|
+
result = {}
|
187
|
+
# the base triggers
|
188
|
+
triggers.each do |trigger_name, trigger|
|
189
|
+
# compare this trigger to the equivilent in the comparison list
|
190
|
+
result[trigger_name] = compare_record trigger, comparison_triggers[trigger_name], [
|
191
|
+
:action_timing,
|
192
|
+
:event_manipulation,
|
193
|
+
:action_order,
|
194
|
+
:action_condition,
|
195
|
+
:action_statement,
|
196
|
+
:action_orientation,
|
197
|
+
:action_reference_old_table,
|
198
|
+
:action_reference_new_table,
|
199
|
+
:description
|
200
|
+
]
|
201
|
+
end
|
202
|
+
# look for any triggers in the comparison list which were not in the base list
|
203
|
+
comparison_triggers.each do |trigger_name, trigger|
|
204
|
+
unless result.key? trigger_name
|
205
|
+
result[trigger_name] = {
|
206
|
+
exists: false
|
207
|
+
}
|
208
|
+
end
|
209
|
+
end
|
210
|
+
result
|
211
|
+
end
|
212
|
+
|
156
213
|
# compare two hash representations of a set of unique_constraints and return
|
157
214
|
# an object which represents the provided `unique_constraints` and any differences
|
158
215
|
# between it and the `comparison_unique_constraints`
|
@@ -163,7 +220,7 @@ module DynamicMigrations
|
|
163
220
|
# compare this unique_constraint to the equivilent in the comparison list
|
164
221
|
result[name] = compare_record unique_constraint, comparison_unique_constraints[name], [
|
165
222
|
:column_names,
|
166
|
-
:
|
223
|
+
:description,
|
167
224
|
:deferrable,
|
168
225
|
:initially_deferred
|
169
226
|
]
|
@@ -189,11 +246,10 @@ module DynamicMigrations
|
|
189
246
|
# compare this index to the equivilent in the comparison list
|
190
247
|
result[name] = compare_record index, comparison_indexes[name], [
|
191
248
|
:column_names,
|
249
|
+
:description,
|
192
250
|
:unique,
|
193
251
|
:where,
|
194
252
|
:type,
|
195
|
-
:deferrable,
|
196
|
-
:initially_deferred,
|
197
253
|
:order,
|
198
254
|
:nulls_position
|
199
255
|
]
|
@@ -220,6 +276,7 @@ module DynamicMigrations
|
|
220
276
|
result[name] = compare_record validation, comparison_validations[name], [
|
221
277
|
:check_clause,
|
222
278
|
:column_names,
|
279
|
+
:description,
|
223
280
|
:deferrable,
|
224
281
|
:initially_deferred
|
225
282
|
]
|
@@ -248,8 +305,11 @@ module DynamicMigrations
|
|
248
305
|
:foreign_schema_name,
|
249
306
|
:foreign_table_name,
|
250
307
|
:foreign_column_names,
|
308
|
+
:description,
|
251
309
|
:deferrable,
|
252
|
-
:initially_deferred
|
310
|
+
:initially_deferred,
|
311
|
+
:on_delete,
|
312
|
+
:on_update
|
253
313
|
]
|
254
314
|
end
|
255
315
|
# look for any foreign_key_constraints in the comparison list which were not in the base list
|