dynamic_migrations 2.2.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +16 -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 +75 -6
- 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 +49 -8
- 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 +4 -0
- 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 +6 -6
- 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 -3
- metadata +44 -2
@@ -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`
|
@@ -144,6 +179,37 @@ module DynamicMigrations
|
|
144
179
|
result
|
145
180
|
end
|
146
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
|
+
|
147
213
|
# compare two hash representations of a set of unique_constraints and return
|
148
214
|
# an object which represents the provided `unique_constraints` and any differences
|
149
215
|
# between it and the `comparison_unique_constraints`
|
@@ -154,7 +220,7 @@ module DynamicMigrations
|
|
154
220
|
# compare this unique_constraint to the equivilent in the comparison list
|
155
221
|
result[name] = compare_record unique_constraint, comparison_unique_constraints[name], [
|
156
222
|
:column_names,
|
157
|
-
:
|
223
|
+
:description,
|
158
224
|
:deferrable,
|
159
225
|
:initially_deferred
|
160
226
|
]
|
@@ -180,11 +246,10 @@ module DynamicMigrations
|
|
180
246
|
# compare this index to the equivilent in the comparison list
|
181
247
|
result[name] = compare_record index, comparison_indexes[name], [
|
182
248
|
:column_names,
|
249
|
+
:description,
|
183
250
|
:unique,
|
184
251
|
:where,
|
185
252
|
:type,
|
186
|
-
:deferrable,
|
187
|
-
:initially_deferred,
|
188
253
|
:order,
|
189
254
|
:nulls_position
|
190
255
|
]
|
@@ -211,6 +276,7 @@ module DynamicMigrations
|
|
211
276
|
result[name] = compare_record validation, comparison_validations[name], [
|
212
277
|
:check_clause,
|
213
278
|
:column_names,
|
279
|
+
:description,
|
214
280
|
:deferrable,
|
215
281
|
:initially_deferred
|
216
282
|
]
|
@@ -239,8 +305,11 @@ module DynamicMigrations
|
|
239
305
|
:foreign_schema_name,
|
240
306
|
:foreign_table_name,
|
241
307
|
:foreign_column_names,
|
308
|
+
:description,
|
242
309
|
:deferrable,
|
243
|
-
:initially_deferred
|
310
|
+
:initially_deferred,
|
311
|
+
:on_delete,
|
312
|
+
:on_update
|
244
313
|
]
|
245
314
|
end
|
246
315
|
# look for any foreign_key_constraints in the comparison list which were not in the base list
|