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
@@ -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,38 +20,21 @@ 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
24
27
  table_definition[:columns].each do |column_name, column_definition|
25
- # we only need these for arrays and user-defined types
26
- # (user-defined is usually ENUMS)
27
- if [:ARRAY, :"USER-DEFINED"].include? column_definition[:data_type]
28
- udt_schema = column_definition[:udt_schema]
29
- udt_name = column_definition[:udt_name]
30
- else
31
- udt_schema = nil
32
- udt_name = nil
33
- end
34
-
35
28
  table.add_column column_name, column_definition[:data_type],
36
29
  null: column_definition[:null],
37
30
  default: column_definition[:default],
38
31
  description: column_definition[:description],
39
- character_maximum_length: column_definition[:character_maximum_length],
40
- character_octet_length: column_definition[:character_octet_length],
41
- numeric_precision: column_definition[:numeric_precision],
42
- numeric_precision_radix: column_definition[:numeric_precision_radix],
43
- numeric_scale: column_definition[:numeric_scale],
44
- datetime_precision: column_definition[:datetime_precision],
45
- udt_schema: udt_schema,
46
- udt_name: udt_name
32
+ interval_type: column_definition[:interval_type]
47
33
  end
48
34
 
49
35
  # add any validations
50
36
  table_validations&.each do |validation_name, validation_definition|
51
- 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]
52
38
  end
53
39
  end
54
40
  end
@@ -62,14 +48,14 @@ module DynamicMigrations
62
48
  keys_and_unique_constraints.each do |constraint_type, constraint_definitions|
63
49
  constraint_definitions.each do |constraint_name, constraint_definition|
64
50
  case constraint_type
65
- when :PRIMARY_KEY
66
- 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]
67
53
 
68
- when :FOREIGN_KEY
69
- 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]
70
56
 
71
- when :UNIQUE
72
- 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]
73
59
 
74
60
  else
75
61
  raise UnexpectedConstrintTypeError, constraint_type
@@ -78,6 +64,44 @@ module DynamicMigrations
78
64
  end
79
65
  end
80
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
81
105
  end
82
106
  end
83
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
@@ -13,23 +13,14 @@ module DynamicMigrations
13
13
 
14
14
  attr_reader :table
15
15
  attr_reader :name
16
+ attr_reader :data_type
16
17
  attr_reader :description
17
18
  attr_reader :null
18
19
  attr_reader :default
19
- attr_reader :data_type
20
- attr_reader :character_maximum_length
21
- attr_reader :character_octet_length
22
- attr_reader :numeric_precision
23
- attr_reader :numeric_precision_radix
24
- attr_reader :numeric_scale
25
- attr_reader :datetime_precision
26
20
  attr_reader :interval_type
27
- attr_reader :udt_schema
28
- attr_reader :udt_name
29
- attr_reader :updatable
30
21
 
31
22
  # initialize a new object to represent a column in a postgres table
32
- def initialize source, table, name, data_type, null: true, default: nil, description: nil, character_maximum_length: nil, character_octet_length: nil, numeric_precision: nil, numeric_precision_radix: nil, numeric_scale: nil, datetime_precision: nil, interval_type: nil, udt_schema: nil, udt_name: nil, updatable: true
23
+ def initialize source, table, name, data_type, null: true, default: nil, description: nil, interval_type: nil
33
24
  super source
34
25
  raise ExpectedTableError, table unless table.is_a? Table
35
26
  @table = table
@@ -38,9 +29,7 @@ module DynamicMigrations
38
29
  @name = name
39
30
 
40
31
  @data_type = data_type
41
-
42
32
  @null = null
43
-
44
33
  @default = default
45
34
 
46
35
  unless description.nil?
@@ -48,44 +37,17 @@ module DynamicMigrations
48
37
  @description = description
49
38
  end
50
39
 
51
- # apply any defaults for this data type
52
- character_maximum_length = character_maximum_length.nil? ? DataTypes.default_for(data_type, :character_maximum_length) : character_maximum_length
53
- character_octet_length = character_octet_length.nil? ? DataTypes.default_for(data_type, :character_octet_length) : character_octet_length
54
- numeric_precision = numeric_precision.nil? ? DataTypes.default_for(data_type, :numeric_precision) : numeric_precision
55
- numeric_precision_radix = numeric_precision_radix.nil? ? DataTypes.default_for(data_type, :numeric_precision_radix) : numeric_precision_radix
56
- numeric_scale = numeric_scale.nil? ? DataTypes.default_for(data_type, :numeric_scale) : numeric_scale
57
- datetime_precision = datetime_precision.nil? ? DataTypes.default_for(data_type, :datetime_precision) : datetime_precision
58
- interval_type = interval_type.nil? ? DataTypes.default_for(data_type, :interval_type) : interval_type
59
- udt_schema = udt_schema.nil? ? DataTypes.default_for(data_type, :udt_schema) : udt_schema
60
- udt_name = udt_name.nil? ? DataTypes.default_for(data_type, :udt_name) : udt_name
61
-
62
- DataTypes.validate_column_properties!(data_type,
63
- character_maximum_length: character_maximum_length,
64
- character_octet_length: character_octet_length,
65
- numeric_precision: numeric_precision,
66
- numeric_precision_radix: numeric_precision_radix,
67
- numeric_scale: numeric_scale,
68
- datetime_precision: datetime_precision,
69
- interval_type: interval_type,
70
- udt_schema: udt_schema,
71
- udt_name: udt_name)
72
-
73
- @character_maximum_length = character_maximum_length
74
- @character_octet_length = character_octet_length
75
- @numeric_precision = numeric_precision
76
- @numeric_precision_radix = numeric_precision_radix
77
- @numeric_scale = numeric_scale
78
- @datetime_precision = datetime_precision
79
40
  @interval_type = interval_type
80
- @udt_schema = udt_schema
81
- @udt_name = udt_name
82
- @updatable = updatable
83
41
  end
84
42
 
85
43
  # return true if this column has a description, otherwise false
86
44
  def has_description?
87
45
  !@description.nil?
88
46
  end
47
+
48
+ def array?
49
+ @data_type.end_with? "[]"
50
+ end
89
51
  end
90
52
  end
91
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