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.
Files changed (66) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +23 -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 +76 -16
  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 +50 -26
  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 +6 -44
  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 +22 -112
  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 -4
  65. metadata +44 -3
  66. 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
@@ -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`
@@ -130,16 +165,7 @@ module DynamicMigrations
130
165
  :null,
131
166
  :default,
132
167
  :description,
133
- :character_maximum_length,
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
- :index_type,
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