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.
Files changed (65) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +16 -0
  3. data/lib/dynamic_migrations/active_record/migrators/column.rb +21 -0
  4. data/lib/dynamic_migrations/active_record/migrators/foreign_key_constraint.rb +112 -0
  5. data/lib/dynamic_migrations/active_record/migrators/function.rb +108 -0
  6. data/lib/dynamic_migrations/active_record/migrators/index.rb +27 -0
  7. data/lib/dynamic_migrations/active_record/migrators/schema.rb +21 -0
  8. data/lib/dynamic_migrations/active_record/migrators/table.rb +21 -0
  9. data/lib/dynamic_migrations/active_record/migrators/trigger.rb +109 -0
  10. data/lib/dynamic_migrations/active_record/migrators/unique_constraint.rb +63 -0
  11. data/lib/dynamic_migrations/active_record/migrators/validation.rb +67 -0
  12. data/lib/dynamic_migrations/active_record/migrators.rb +64 -0
  13. data/lib/dynamic_migrations/name_helper.rb +13 -0
  14. data/lib/dynamic_migrations/postgres/generator/column.rb +92 -0
  15. data/lib/dynamic_migrations/postgres/generator/foreign_key_constraint.rb +84 -0
  16. data/lib/dynamic_migrations/postgres/generator/fragment.rb +30 -0
  17. data/lib/dynamic_migrations/postgres/generator/function.rb +77 -0
  18. data/lib/dynamic_migrations/postgres/generator/index.rb +101 -0
  19. data/lib/dynamic_migrations/postgres/generator/primary_key.rb +55 -0
  20. data/lib/dynamic_migrations/postgres/generator/schema.rb +19 -0
  21. data/lib/dynamic_migrations/postgres/generator/schema_migrations/section.rb +37 -0
  22. data/lib/dynamic_migrations/postgres/generator/schema_migrations.rb +92 -0
  23. data/lib/dynamic_migrations/postgres/generator/table.rb +122 -0
  24. data/lib/dynamic_migrations/postgres/generator/trigger.rb +101 -0
  25. data/lib/dynamic_migrations/postgres/generator/unique_constraint.rb +79 -0
  26. data/lib/dynamic_migrations/postgres/generator/validation.rb +87 -0
  27. data/lib/dynamic_migrations/postgres/generator.rb +359 -0
  28. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/functions.rb +68 -0
  29. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/columns.rb +72 -0
  30. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/foreign_key_constraints.rb +73 -0
  31. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/indexes.rb +73 -0
  32. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/primary_key.rb +49 -0
  33. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/triggers.rb +73 -0
  34. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/unique_constraints.rb +73 -0
  35. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/validations.rb +73 -0
  36. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables.rb +80 -0
  37. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas.rb +48 -0
  38. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations.rb +59 -0
  39. data/lib/dynamic_migrations/postgres/server/database/differences.rb +75 -6
  40. data/lib/dynamic_migrations/postgres/server/database/keys_and_unique_constraints_loader.rb +35 -9
  41. data/lib/dynamic_migrations/postgres/server/database/loaded_schemas_builder.rb +49 -8
  42. data/lib/dynamic_migrations/postgres/server/database/schema/function.rb +69 -0
  43. data/lib/dynamic_migrations/postgres/server/database/schema/functions.rb +63 -0
  44. data/lib/dynamic_migrations/postgres/server/database/schema/table/column.rb +4 -0
  45. data/lib/dynamic_migrations/postgres/server/database/schema/table/columns.rb +1 -1
  46. data/lib/dynamic_migrations/postgres/server/database/schema/table/foreign_key_constraint.rb +40 -5
  47. data/lib/dynamic_migrations/postgres/server/database/schema/table/index.rb +23 -9
  48. data/lib/dynamic_migrations/postgres/server/database/schema/table/primary_key.rb +21 -6
  49. data/lib/dynamic_migrations/postgres/server/database/schema/table/trigger.rb +151 -0
  50. data/lib/dynamic_migrations/postgres/server/database/schema/table/triggers.rb +66 -0
  51. data/lib/dynamic_migrations/postgres/server/database/schema/table/unique_constraint.rb +19 -9
  52. data/lib/dynamic_migrations/postgres/server/database/schema/table/validation.rb +20 -1
  53. data/lib/dynamic_migrations/postgres/server/database/schema/table.rb +15 -5
  54. data/lib/dynamic_migrations/postgres/server/database/schema/tables.rb +63 -0
  55. data/lib/dynamic_migrations/postgres/server/database/schema.rb +3 -49
  56. data/lib/dynamic_migrations/postgres/server/database/source.rb +21 -0
  57. data/lib/dynamic_migrations/postgres/server/database/structure_loader.rb +6 -6
  58. data/lib/dynamic_migrations/postgres/server/database/triggers_and_functions_loader.rb +131 -0
  59. data/lib/dynamic_migrations/postgres/server/database/validations_loader.rb +10 -4
  60. data/lib/dynamic_migrations/postgres/server/database.rb +2 -1
  61. data/lib/dynamic_migrations/postgres/server.rb +6 -0
  62. data/lib/dynamic_migrations/postgres.rb +1 -1
  63. data/lib/dynamic_migrations/version.rb +1 -1
  64. data/lib/dynamic_migrations.rb +47 -3
  65. 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
@@ -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
- :index_type
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
- :index_type,
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