dynamic_migrations 2.2.0 → 3.1.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 +28 -4
  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 +81 -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
@@ -10,11 +10,12 @@ module DynamicMigrations
10
10
  CREATE MATERIALIZED VIEW public.dynamic_migrations_keys_and_unique_constraints_cache as
11
11
  SELECT
12
12
  c.conname AS constraint_name,
13
+ pg_get_constraintdef(c.oid, true) as constraint_definition,
13
14
  CASE c.contype
14
- WHEN 'f'::"char" THEN 'FOREIGN_KEY'::text
15
- WHEN 'p'::"char" THEN 'PRIMARY_KEY'::text
16
- WHEN 'u'::"char" THEN 'UNIQUE'::text
17
- END::information_schema.character_data AS constraint_type,
15
+ WHEN 'f'::"char" THEN 'foreign_key'::text
16
+ WHEN 'p'::"char" THEN 'primary_key'::text
17
+ WHEN 'u'::"char" THEN 'unique'::text
18
+ END AS constraint_type,
18
19
  sch.nspname AS schema_name,
19
20
  tbl.relname AS table_name,
20
21
  ARRAY_AGG(col.attname ORDER BY u.attposition) AS column_names,
@@ -24,7 +25,23 @@ module DynamicMigrations
24
25
  NULLIF(ARRAY_AGG(f_col.attname ORDER BY f_u.attposition), ARRAY[null]::name[]) AS foreign_column_names,
25
26
  c.condeferrable as deferrable,
26
27
  c.condeferred as initially_deferred,
28
+ CASE c.confupdtype
29
+ WHEN 'a'::"char" THEN 'no_action'::text
30
+ WHEN 'r'::"char" THEN 'restrict'::text
31
+ WHEN 'c'::"char" THEN 'cascade'::text
32
+ WHEN 'n'::"char" THEN 'set_null'::text
33
+ WHEN 'd'::"char" THEN 'set_default'::text
34
+ END AS on_update,
35
+ CASE c.confdeltype
36
+ WHEN 'a'::"char" THEN 'no_action'::text
37
+ WHEN 'r'::"char" THEN 'restrict'::text
38
+ WHEN 'c'::"char" THEN 'cascade'::text
39
+ WHEN 'n'::"char" THEN 'set_null'::text
40
+ WHEN 'd'::"char" THEN 'set_default'::text
41
+ END AS on_delete,
27
42
  am.amname as index_type,
43
+ obj_description(c.oid, 'pg_constraint') as description,
44
+ -- in case we need to update this query in a later version of DynamicMigrations
28
45
  1 as table_version
29
46
  FROM pg_constraint c
30
47
  LEFT JOIN LATERAL UNNEST(c.conkey)
@@ -68,10 +85,10 @@ module DynamicMigrations
68
85
  LEFT JOIN pg_am am ON am.oid=index_cls.relam
69
86
 
70
87
  WHERE
71
- -- only FOREIGN_KEY, UNIQUE or PRIMARY_KEY
88
+ -- only foreign_key, unique or primary_key
72
89
  c.contype in ('f', 'u', 'p')
73
90
 
74
- GROUP BY constraint_name, constraint_type, condeferrable, condeferred, schema_name, table_name, foreign_schema_name, foreign_table_name, am.amname
91
+ GROUP BY c.oid, constraint_name, constraint_type, condeferrable, condeferred, schema_name, table_name, foreign_schema_name, foreign_table_name, am.amname
75
92
  ORDER BY schema_name, table_name;
76
93
  SQL
77
94
  connection.exec(<<~SQL)
@@ -86,12 +103,12 @@ module DynamicMigrations
86
103
  # useful hash representing the keys and indexes of your database
87
104
  def fetch_keys_and_unique_constraints
88
105
  begin
89
- rows = connection.exec_params(<<~SQL)
106
+ rows = connection.exec(<<~SQL)
90
107
  SELECT * FROM public.dynamic_migrations_keys_and_unique_constraints_cache
91
108
  SQL
92
109
  rescue PG::UndefinedTable
93
110
  create_database_keys_and_unique_constraints_cache
94
- rows = connection.exec_params(<<~SQL)
111
+ rows = connection.exec(<<~SQL)
95
112
  SELECT * FROM public.dynamic_migrations_keys_and_unique_constraints_cache
96
113
  SQL
97
114
  end
@@ -111,14 +128,20 @@ module DynamicMigrations
111
128
 
112
129
  column_names = row["column_names"].gsub(/\A\{/, "").gsub(/\}\Z/, "").split(",").map { |column_name| column_name.to_sym }
113
130
 
114
- if constraint_type == :FOREIGN_KEY
131
+ description = (row["description"] == "") ? nil : row["description"]
132
+
133
+ if constraint_type == :foreign_key
115
134
  foreign_schema_name = row["foreign_schema_name"].to_sym
116
135
  foreign_table_name = row["foreign_table_name"].to_sym
117
136
  foreign_column_names = row["foreign_column_names"].gsub(/\A\{/, "").gsub(/\}\Z/, "").split(",").map { |column_name| column_name.to_sym }
137
+ on_update = row["on_update"].to_sym
138
+ on_delete = row["on_delete"].to_sym
118
139
  else
119
140
  foreign_schema_name = nil
120
141
  foreign_table_name = nil
121
142
  foreign_column_names = nil
143
+ on_update = nil
144
+ on_delete = nil
122
145
  end
123
146
 
124
147
  deferrable = row["deferrable"] == "TRUE"
@@ -137,6 +160,9 @@ module DynamicMigrations
137
160
  foreign_column_names: foreign_column_names,
138
161
  deferrable: deferrable,
139
162
  initially_deferred: initially_deferred,
163
+ on_update: on_update,
164
+ on_delete: on_delete,
165
+ description: description,
140
166
  index_type: index_type
141
167
  }
142
168
  end
@@ -8,6 +8,9 @@ module DynamicMigrations
8
8
  class UnexpectedConstrintTypeError < StandardError
9
9
  end
10
10
 
11
+ class UnexpectedTriggerSchema < StandardError
12
+ end
13
+
11
14
  # recursively process the database and build all the schemas,
12
15
  # tables and columns
13
16
  def recursively_build_schemas_from_database
@@ -17,7 +20,7 @@ module DynamicMigrations
17
20
  schema_validations = validations[schema_name]
18
21
 
19
22
  schema_definition[:tables].each do |table_name, table_definition|
20
- table = schema.add_table table_name, table_definition[:description]
23
+ table = schema.add_table table_name, description: table_definition[:description]
21
24
  table_validations = schema_validations && schema_validations[table_name]
22
25
 
23
26
  # add each table column
@@ -31,7 +34,7 @@ module DynamicMigrations
31
34
 
32
35
  # add any validations
33
36
  table_validations&.each do |validation_name, validation_definition|
34
- table.add_validation validation_name, validation_definition[:columns], validation_definition[:check_clause]
37
+ table.add_validation validation_name, validation_definition[:columns], validation_definition[:check_clause], description: validation_definition[:description], deferrable: validation_definition[:deferrable], initially_deferred: validation_definition[:initially_deferred]
35
38
  end
36
39
  end
37
40
  end
@@ -45,14 +48,14 @@ module DynamicMigrations
45
48
  keys_and_unique_constraints.each do |constraint_type, constraint_definitions|
46
49
  constraint_definitions.each do |constraint_name, constraint_definition|
47
50
  case constraint_type
48
- when :PRIMARY_KEY
49
- table.add_primary_key constraint_name, constraint_definition[:column_names], index_type: constraint_definition[:index_type]
51
+ when :primary_key
52
+ table.add_primary_key constraint_name, constraint_definition[:column_names], description: constraint_definition[:description]
50
53
 
51
- when :FOREIGN_KEY
52
- table.add_foreign_key_constraint constraint_name, constraint_definition[:column_names], constraint_definition[:foreign_schema_name], constraint_definition[:foreign_table_name], constraint_definition[:foreign_column_names], deferrable: constraint_definition[:deferrable], initially_deferred: constraint_definition[:initially_deferred]
54
+ when :foreign_key
55
+ table.add_foreign_key_constraint constraint_name, constraint_definition[:column_names], constraint_definition[:foreign_schema_name], constraint_definition[:foreign_table_name], constraint_definition[:foreign_column_names], description: constraint_definition[:description], deferrable: constraint_definition[:deferrable], initially_deferred: constraint_definition[:initially_deferred], on_delete: constraint_definition[:on_delete], on_update: constraint_definition[:on_update]
53
56
 
54
- when :UNIQUE
55
- table.add_unique_constraint constraint_name, constraint_definition[:column_names], deferrable: constraint_definition[:deferrable], initially_deferred: constraint_definition[:initially_deferred], index_type: constraint_definition[:index_type]
57
+ when :unique
58
+ table.add_unique_constraint constraint_name, constraint_definition[:column_names], description: constraint_definition[:description], deferrable: constraint_definition[:deferrable], initially_deferred: constraint_definition[:initially_deferred]
56
59
 
57
60
  else
58
61
  raise UnexpectedConstrintTypeError, constraint_type
@@ -61,6 +64,44 @@ module DynamicMigrations
61
64
  end
62
65
  end
63
66
  end
67
+
68
+ # add all functions and triggers (functions first, because the triggers are dependent on them)
69
+ fetch_triggers_and_functions.each do |schema_name, schema_definition|
70
+ schema_definition.each do |table_name, triggers|
71
+ # the table that this trigger works on
72
+ table = loaded_schema(schema_name).table(table_name)
73
+ # all the triggers for this table
74
+ triggers.each do |trigger_name, trigger_definition|
75
+ # the trigger and function can be in different schemas
76
+ function_schema = loaded_schema(trigger_definition[:function_schema])
77
+ trigger_schema = loaded_schema(trigger_definition[:trigger_schema])
78
+
79
+ if trigger_schema != table.schema
80
+ raise UnexpectedTriggerSchema, "Trigger schema `#{trigger_schema.name}` does not match table schema `#{table.schema.name}`"
81
+ end
82
+
83
+ # if this function does not exist locally, then add it
84
+ unless function_schema.has_function?(trigger_definition[:function_name])
85
+ function_schema.add_function trigger_definition[:function_name], trigger_definition[:function_definition], description: trigger_definition[:function_description]
86
+ end
87
+
88
+ # get the function
89
+ function = function_schema.function(trigger_definition[:function_name])
90
+
91
+ # create the trigger
92
+ table.add_trigger trigger_name, action_timing: trigger_definition[:action_timing],
93
+ event_manipulation: trigger_definition[:event_manipulation],
94
+ action_order: trigger_definition[:action_order],
95
+ action_statement: trigger_definition[:action_statement],
96
+ action_orientation: trigger_definition[:action_orientation],
97
+ function: function,
98
+ action_condition: trigger_definition[:action_condition],
99
+ action_reference_old_table: trigger_definition[:action_reference_old_table],
100
+ action_reference_new_table: trigger_definition[:action_reference_new_table],
101
+ description: trigger_definition[:description]
102
+ end
103
+ end
104
+ end
64
105
  end
65
106
  end
66
107
  end
@@ -0,0 +1,69 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DynamicMigrations
4
+ module Postgres
5
+ class Server
6
+ class Database
7
+ class Schema
8
+ # This class represents a postgres function.
9
+ class Function < Source
10
+ class ExpectedSchemaError < StandardError
11
+ end
12
+
13
+ class ExpectedDefinitionError < StandardError
14
+ end
15
+
16
+ attr_reader :schema
17
+ attr_reader :name
18
+ attr_reader :definition
19
+ attr_reader :description
20
+ attr_reader :triggers
21
+
22
+ # initialize a new object to represent a postgres function
23
+ def initialize source, schema, name, definition, description: nil
24
+ super source
25
+
26
+ @triggers ||= []
27
+
28
+ raise ExpectedSchemaError, schema unless schema.is_a? Schema
29
+ @schema = schema
30
+
31
+ raise ExpectedSymbolError, name unless name.is_a? Symbol
32
+ @name = name
33
+
34
+ unless definition.is_a?(String) && definition.strip != ""
35
+ raise ExpectedDefinitionError, definition
36
+ end
37
+ @definition = definition
38
+
39
+ unless description.nil?
40
+ raise ExpectedStringError, description unless description.is_a? String
41
+ @description = description
42
+ end
43
+ end
44
+
45
+ # returns true if this function has a description, otehrwise false
46
+ def has_description?
47
+ !@description.nil?
48
+ end
49
+
50
+ # returns all the triggers which are associated with this function
51
+ def add_trigger trigger
52
+ # this should never happen, but adding it just in case
53
+ unless trigger.source == source
54
+ raise "Internal error - trigger source `#{trigger.source}` does not match function source `#{source}`"
55
+ end
56
+ @triggers << trigger
57
+ end
58
+
59
+ def differences_descriptions other_function
60
+ method_differences_descriptions other_function, [
61
+ :definition
62
+ ]
63
+ end
64
+ end
65
+ end
66
+ end
67
+ end
68
+ end
69
+ end
@@ -0,0 +1,63 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DynamicMigrations
4
+ module Postgres
5
+ class Server
6
+ class Database
7
+ class Schema < Source
8
+ module Functions
9
+ class FunctionAlreadyExistsError < StandardError
10
+ end
11
+
12
+ class FunctionDoesNotExistError < StandardError
13
+ end
14
+
15
+ # create and add a new function from a provided function name
16
+ def add_function function_name, definition, description: nil
17
+ raise ExpectedSymbolError, function_name unless function_name.is_a? Symbol
18
+ if has_function? function_name
19
+ raise(FunctionAlreadyExistsError, "Function #{function_name} already exists")
20
+ end
21
+ included_target = self
22
+ if included_target.is_a? Schema
23
+ new_function = @functions[function_name] = Function.new source, included_target, function_name, definition, description: description
24
+ else
25
+ raise ModuleIncludedIntoUnexpectedTargetError, included_target
26
+ end
27
+ # sort the hash so that the functions are in alphabetical order by name
28
+ sorted_functions = {}
29
+ @functions.keys.sort.each do |function_name|
30
+ sorted_functions[function_name] = @functions[function_name]
31
+ end
32
+ @functions = sorted_functions
33
+ # return the new function
34
+ new_function
35
+ end
36
+
37
+ # return a function by its name, raises an error if the function does not exist
38
+ def function function_name
39
+ raise ExpectedSymbolError, function_name unless function_name.is_a? Symbol
40
+ raise FunctionDoesNotExistError unless has_function? function_name
41
+ @functions[function_name]
42
+ end
43
+
44
+ # returns true/false representing if a function with the provided name exists
45
+ def has_function? function_name
46
+ raise ExpectedSymbolError, function_name unless function_name.is_a? Symbol
47
+ @functions.key? function_name
48
+ end
49
+
50
+ # returns an array of all functions in the schema
51
+ def functions
52
+ @functions.values
53
+ end
54
+
55
+ def functions_hash
56
+ @functions
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -44,6 +44,10 @@ module DynamicMigrations
44
44
  def has_description?
45
45
  !@description.nil?
46
46
  end
47
+
48
+ def array?
49
+ @data_type.end_with? "[]"
50
+ end
47
51
  end
48
52
  end
49
53
  end
@@ -18,7 +18,7 @@ module DynamicMigrations
18
18
  # error if the column does not exist
19
19
  def column name
20
20
  raise ExpectedSymbolError, name unless name.is_a? Symbol
21
- raise ColumnDoesNotExistError unless has_column? name
21
+ raise ColumnDoesNotExistError, name unless has_column? name
22
22
  @columns[name]
23
23
  end
24
24
 
@@ -20,14 +20,20 @@ module DynamicMigrations
20
20
  class DuplicateColumnError < StandardError
21
21
  end
22
22
 
23
+ class UnexpectedReferentialActionError < StandardError
24
+ end
25
+
23
26
  attr_reader :table
24
27
  attr_reader :foreign_table
25
28
  attr_reader :name
26
29
  attr_reader :deferrable
27
30
  attr_reader :initially_deferred
31
+ attr_reader :on_delete
32
+ attr_reader :on_update
33
+ attr_reader :description
28
34
 
29
35
  # initialize a new object to represent a foreign_key_constraint in a postgres table
30
- def initialize source, table, columns, foreign_table, foreign_columns, name, deferrable: false, initially_deferred: false
36
+ def initialize source, table, columns, foreign_table, foreign_columns, name, description: nil, deferrable: false, initially_deferred: false, on_delete: :no_action, on_update: :no_action
31
37
  super source
32
38
 
33
39
  raise ExpectedTableError, table unless table.is_a? Table
@@ -64,11 +70,27 @@ module DynamicMigrations
64
70
  raise ExpectedSymbolError, name unless name.is_a? Symbol
65
71
  @name = name
66
72
 
73
+ unless description.nil?
74
+ raise ExpectedStringError, description unless description.is_a? String
75
+ @description = description
76
+ end
77
+
67
78
  raise ExpectedBooleanError, deferrable unless [true, false].include?(deferrable)
68
79
  @deferrable = deferrable
69
80
 
70
81
  raise ExpectedBooleanError, initially_deferred unless [true, false].include?(initially_deferred)
71
82
  @initially_deferred = initially_deferred
83
+
84
+ raise UnexpectedReferentialActionError, on_delete unless [:no_action, :restrict, :cascade, :set_null, :set_default].include?(on_delete)
85
+ @on_delete = on_delete
86
+
87
+ raise UnexpectedReferentialActionError, on_update unless [:no_action, :restrict, :cascade, :set_null, :set_default].include?(on_update)
88
+ @on_update = on_update
89
+ end
90
+
91
+ # return true if this has a description, otherwise false
92
+ def has_description?
93
+ !@description.nil?
72
94
  end
73
95
 
74
96
  def columns
@@ -83,10 +105,6 @@ module DynamicMigrations
83
105
  @foreign_columns.values
84
106
  end
85
107
 
86
- def foreign_column_names
87
- @foreign_columns.keys
88
- end
89
-
90
108
  def foreign_schema_name
91
109
  @foreign_table.schema.name
92
110
  end
@@ -95,6 +113,23 @@ module DynamicMigrations
95
113
  @foreign_table.name
96
114
  end
97
115
 
116
+ def foreign_column_names
117
+ @foreign_columns.keys
118
+ end
119
+
120
+ def differences_descriptions other_foreign_key_constraint
121
+ method_differences_descriptions other_foreign_key_constraint, [
122
+ :column_names,
123
+ :foreign_schema_name,
124
+ :foreign_table_name,
125
+ :foreign_column_names,
126
+ :deferrable,
127
+ :initially_deferred,
128
+ :on_delete,
129
+ :on_update
130
+ ]
131
+ end
132
+
98
133
  private
99
134
 
100
135
  # used internally to set the columns from this objects initialize method
@@ -35,13 +35,12 @@ module DynamicMigrations
35
35
  attr_reader :unique
36
36
  attr_reader :where
37
37
  attr_reader :type
38
- attr_reader :deferrable
39
- attr_reader :initially_deferred
40
38
  attr_reader :order
41
39
  attr_reader :nulls_position
40
+ attr_reader :description
42
41
 
43
42
  # initialize a new object to represent a index in a postgres table
44
- def initialize source, table, columns, name, unique: false, where: nil, type: :btree, deferrable: false, initially_deferred: false, include_columns: [], order: :asc, nulls_position: :last
43
+ def initialize source, table, columns, name, description: nil, unique: false, where: nil, type: :btree, include_columns: [], order: :asc, nulls_position: :last
45
44
  super source
46
45
  raise ExpectedTableError, table unless table.is_a? Table
47
46
  @table = table
@@ -60,6 +59,11 @@ module DynamicMigrations
60
59
  raise ExpectedSymbolError, name unless name.is_a? Symbol
61
60
  @name = name
62
61
 
62
+ unless description.nil?
63
+ raise ExpectedStringError, description unless description.is_a? String
64
+ @description = description
65
+ end
66
+
63
67
  raise ExpectedBooleanError, unique unless [true, false].include?(unique)
64
68
  @unique = unique
65
69
 
@@ -71,12 +75,6 @@ module DynamicMigrations
71
75
  raise UnexpectedIndexTypeError, type unless INDEX_TYPES.include?(type)
72
76
  @type = type
73
77
 
74
- raise ExpectedBooleanError, deferrable unless [true, false].include?(deferrable)
75
- @deferrable = deferrable
76
-
77
- raise ExpectedBooleanError, initially_deferred unless [true, false].include?(initially_deferred)
78
- @initially_deferred = initially_deferred
79
-
80
78
  # assert that the include_columns is an array (it's optional, so can be an empty array)
81
79
  unless include_columns.is_a?(Array)
82
80
  raise ExpectedArrayOfColumnsError
@@ -93,6 +91,11 @@ module DynamicMigrations
93
91
  @nulls_position = nulls_position
94
92
  end
95
93
 
94
+ # return true if this has a description, otherwise false
95
+ def has_description?
96
+ !@description.nil?
97
+ end
98
+
96
99
  # return an array of this indexes columns
97
100
  def columns
98
101
  @columns.values
@@ -111,6 +114,17 @@ module DynamicMigrations
111
114
  @include_columns.keys
112
115
  end
113
116
 
117
+ def differences_descriptions other_index
118
+ method_differences_descriptions other_index, [
119
+ :column_names,
120
+ :unique,
121
+ :where,
122
+ :type,
123
+ :order,
124
+ :nulls_position
125
+ ]
126
+ end
127
+
114
128
  private
115
129
 
116
130
  # used internally to set the columns from this objects initialize method
@@ -8,8 +8,6 @@ module DynamicMigrations
8
8
  class Table
9
9
  # This class represents a postgres table primary_key
10
10
  class PrimaryKey < Source
11
- INDEX_TYPES = [:btree, :gin]
12
-
13
11
  class ExpectedTableError < StandardError
14
12
  end
15
13
 
@@ -24,10 +22,10 @@ module DynamicMigrations
24
22
 
25
23
  attr_reader :table
26
24
  attr_reader :name
27
- attr_reader :index_type
25
+ attr_reader :description
28
26
 
29
27
  # initialize a new object to represent a primary_key in a postgres table
30
- def initialize source, table, columns, name, index_type: :btree
28
+ def initialize source, table, columns, name, description: nil
31
29
  super source
32
30
  raise ExpectedTableError, table unless table.is_a? Table
33
31
  @table = table
@@ -45,8 +43,15 @@ module DynamicMigrations
45
43
  raise ExpectedSymbolError, name unless name.is_a? Symbol
46
44
  @name = name
47
45
 
48
- raise UnexpectedIndexTypeError, index_type unless INDEX_TYPES.include?(index_type)
49
- @index_type = index_type
46
+ unless description.nil?
47
+ raise ExpectedStringError, description unless description.is_a? String
48
+ @description = description
49
+ end
50
+ end
51
+
52
+ # return true if this has a description, otherwise false
53
+ def has_description?
54
+ !@description.nil?
50
55
  end
51
56
 
52
57
  # return an array of this primary keys columns
@@ -54,6 +59,16 @@ module DynamicMigrations
54
59
  @columns.values
55
60
  end
56
61
 
62
+ def column_names
63
+ @columns.keys
64
+ end
65
+
66
+ def differences_descriptions other_primary_key
67
+ method_differences_descriptions other_primary_key, [
68
+ :column_names
69
+ ]
70
+ end
71
+
57
72
  private
58
73
 
59
74
  # used internally to set the columns from this objects initialize method