dynamic_migrations 3.6.15 → 3.7.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 (55) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +37 -0
  3. data/lib/dynamic_migrations/active_record/migrators/primary_key.rb +21 -0
  4. data/lib/dynamic_migrations/active_record/migrators.rb +1 -0
  5. data/lib/dynamic_migrations/postgres/generator/primary_key.rb +32 -0
  6. data/lib/dynamic_migrations/postgres/generator/table.rb +20 -4
  7. data/lib/dynamic_migrations/postgres/generator/table_migration.rb +1 -1
  8. data/lib/dynamic_migrations/postgres/generator/validation.rb +0 -4
  9. data/lib/dynamic_migrations/postgres/generator/validation_template_base.rb +5 -3
  10. data/lib/dynamic_migrations/postgres/generator.rb +4 -5
  11. data/lib/dynamic_migrations/postgres/server/database/connection.rb +3 -1
  12. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/functions.rb +1 -1
  13. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/foreign_key_constraints.rb +2 -2
  14. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/indexes.rb +2 -2
  15. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/triggers.rb +2 -2
  16. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/unique_constraints.rb +2 -2
  17. data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/validations.rb +2 -2
  18. data/lib/dynamic_migrations/postgres/server/database/differences.rb +3 -3
  19. data/lib/dynamic_migrations/postgres/server/database/enums_loader.rb +1 -1
  20. data/lib/dynamic_migrations/postgres/server/database/keys_and_unique_constraints_loader.rb +8 -0
  21. data/lib/dynamic_migrations/postgres/server/database/schema/function.rb +51 -2
  22. data/lib/dynamic_migrations/postgres/server/database/schema/table/column.rb +29 -2
  23. data/lib/dynamic_migrations/postgres/server/database/schema/table/foreign_key_constraint.rb +4 -7
  24. data/lib/dynamic_migrations/postgres/server/database/schema/table/foreign_key_constraints.rb +5 -0
  25. data/lib/dynamic_migrations/postgres/server/database/schema/table/trigger.rb +72 -6
  26. data/lib/dynamic_migrations/postgres/server/database/schema/table/validation.rb +95 -12
  27. data/lib/dynamic_migrations/postgres/server/database/schema/table/validations.rb +1 -1
  28. data/lib/dynamic_migrations/postgres/server/database/schema/table.rb +2 -0
  29. data/lib/dynamic_migrations/postgres/server/database/structure_loader.rb +9 -1
  30. data/lib/dynamic_migrations/postgres/server/database/triggers_and_functions_loader.rb +4 -3
  31. data/lib/dynamic_migrations/postgres/server/database/validations_loader.rb +42 -29
  32. data/lib/dynamic_migrations/postgres/server/database.rb +6 -0
  33. data/lib/dynamic_migrations/version.rb +1 -1
  34. data/lib/dynamic_migrations.rb +1 -0
  35. data/sig/dynamic_migrations/active_record/migrators/primary_key.rbs +18 -0
  36. data/sig/dynamic_migrations/postgres/generator/primary_key.rbs +2 -0
  37. data/sig/dynamic_migrations/postgres/generator/table.rbs +2 -0
  38. data/sig/dynamic_migrations/postgres/generator/validation_template_base.rbs +7 -7
  39. data/sig/dynamic_migrations/postgres/generator.rbs +1 -1
  40. data/sig/dynamic_migrations/postgres/server/database/connection.rbs +1 -1
  41. data/sig/dynamic_migrations/postgres/server/database/keys_and_unique_constraints_loader.rbs +1 -0
  42. data/sig/dynamic_migrations/postgres/server/database/schema/enum.rbs +2 -2
  43. data/sig/dynamic_migrations/postgres/server/database/schema/enums.rbs +1 -1
  44. data/sig/dynamic_migrations/postgres/server/database/schema/function.rbs +9 -0
  45. data/sig/dynamic_migrations/postgres/server/database/schema/table/column.rbs +4 -0
  46. data/sig/dynamic_migrations/postgres/server/database/schema/table/foreign_key_constraint.rbs +0 -3
  47. data/sig/dynamic_migrations/postgres/server/database/schema/table/foreign_key_constraints.rbs +1 -0
  48. data/sig/dynamic_migrations/postgres/server/database/schema/table/trigger.rbs +9 -0
  49. data/sig/dynamic_migrations/postgres/server/database/schema/table/validation.rbs +9 -1
  50. data/sig/dynamic_migrations/postgres/server/database/schema/table/validations.rbs +1 -1
  51. data/sig/dynamic_migrations/postgres/server/database/schema/table.rbs +1 -0
  52. data/sig/dynamic_migrations/postgres/server/database/structure_loader.rbs +1 -0
  53. data/sig/dynamic_migrations/postgres/server/database/validations_loader.rbs +1 -0
  54. data/sig/dynamic_migrations/postgres/server/database.rbs +1 -0
  55. metadata +4 -2
@@ -38,6 +38,9 @@ module DynamicMigrations
38
38
  class UnexpectedTemplateError < StandardError
39
39
  end
40
40
 
41
+ class UnnormalizableActionConditionError < StandardError
42
+ end
43
+
41
44
  attr_reader :table
42
45
  attr_reader :name
43
46
  attr_reader :event_manipulation
@@ -51,7 +54,7 @@ module DynamicMigrations
51
54
  attr_reader :description
52
55
  attr_reader :template
53
56
 
54
- # initialize a new object to represent a validation in a postgres table
57
+ # initialize a new object to represent a trigger in a postgres table
55
58
  def initialize source, table, name, action_timing:, event_manipulation:, parameters:, action_orientation:, function:, action_order: nil, action_condition: nil, action_reference_old_table: nil, action_reference_new_table: nil, description: nil, template: nil
56
59
  super source
57
60
 
@@ -147,11 +150,11 @@ module DynamicMigrations
147
150
  end
148
151
  action_order
149
152
 
150
- # otherwise return the dynamically calculated action order, this is calculated
151
- # by returning this triggers index in the list of alphabetically sorted triggers
152
- # for this triggers table
153
+ # otherwise is is computed by finding the index of the trigger within a list of
154
+ # triggers that are alphabetically sorted, all of which pertain to the same event
155
+ # manipulation (such as update, insert, etc.) for this triggers table
153
156
  else
154
- pos = @table.triggers.sort_by(&:name).index(self)
157
+ pos = @table.triggers.select { |t| t.event_manipulation == event_manipulation }.sort_by(&:name).index(self)
155
158
  if pos.nil?
156
159
  raise "Trigger not found in table triggers list. This should be impossible."
157
160
  end
@@ -184,7 +187,7 @@ module DynamicMigrations
184
187
  :event_manipulation,
185
188
  :action_timing,
186
189
  :action_order,
187
- :action_condition,
190
+ :normalized_action_condition,
188
191
  :parameters,
189
192
  :action_orientation,
190
193
  :action_reference_old_table,
@@ -197,6 +200,69 @@ module DynamicMigrations
197
200
  # return the combined differences
198
201
  descriptions
199
202
  end
203
+
204
+ # create a temporary table in postgres to represent this trigger and fetch
205
+ # the actual normalized check constraint directly from the database
206
+ def normalized_action_condition
207
+ if action_condition.nil?
208
+ nil
209
+ # no need to normalize action_conditions which originated from the database
210
+ elsif from_database?
211
+ action_condition
212
+ else
213
+ ac = table.schema.database.with_connection do |connection|
214
+ # wrapped in a transaction just in case something here fails, because
215
+ # we don't want the function, temporary table or trigger to be persisted
216
+ connection.exec("BEGIN")
217
+
218
+ # create the temp table and add the expected columns and constraint
219
+ connection.exec(<<~SQL)
220
+ CREATE TEMP TABLE trigger_normalized_action_condition_temp_table (
221
+ #{table.columns.map { |column| '"' + column.name.to_s + '" ' + column.temp_table_data_type.to_s }.join(", ")}
222
+ );
223
+ SQL
224
+
225
+ # create a temporary function to trigger (triggers require a function)
226
+ connection.exec(<<~SQL)
227
+ CREATE OR REPLACE FUNCTION trigger_normalized_action_condition_temp_fn() returns trigger language plpgsql AS
228
+ $$ BEGIN END $$;
229
+ SQL
230
+
231
+ # create a temporary trigger, from which we will fetch the normalized action condition
232
+ connection.exec(<<~SQL)
233
+ CREATE TRIGGER trigger_normalized_action_condition_temp_trigger
234
+ BEFORE UPDATE ON trigger_normalized_action_condition_temp_table
235
+ FOR EACH ROW
236
+ WHEN (#{action_condition})
237
+ EXECUTE FUNCTION trigger_normalized_action_condition_temp_fn();
238
+ SQL
239
+
240
+ # get the normalzed version of the action condition
241
+ rows = connection.exec(<<~SQL)
242
+ SELECT (
243
+ regexp_match(
244
+ pg_get_triggerdef(oid),
245
+ '.{35,} WHEN ((.+)) EXECUTE FUNCTION')
246
+ )[1] as action_condition
247
+ FROM pg_trigger
248
+ WHERE tgname = 'trigger_normalized_action_condition_temp_trigger'
249
+ ;
250
+ SQL
251
+
252
+ # delete the temp table and close the transaction
253
+ connection.exec("ROLLBACK")
254
+
255
+ # return the normalized action condition
256
+ rows.first["action_condition"]
257
+ end
258
+
259
+ if ac.nil?
260
+ raise UnnormalizableActionConditionError, "Failed to nomalize action condition `#{action_condition}`"
261
+ end
262
+
263
+ ac
264
+ end
265
+ end
200
266
  end
201
267
  end
202
268
  end
@@ -20,6 +20,9 @@ module DynamicMigrations
20
20
  class UnexpectedTemplateError < StandardError
21
21
  end
22
22
 
23
+ class UnnormalizableCheckClauseError < StandardError
24
+ end
25
+
23
26
  attr_reader :table
24
27
  attr_reader :name
25
28
  attr_reader :check_clause
@@ -34,22 +37,25 @@ module DynamicMigrations
34
37
  raise ExpectedTableError, table unless table.is_a? Table
35
38
  @table = table
36
39
 
37
- # assert that the provided columns is an array
38
- unless columns.is_a?(Array) && columns.count > 0
39
- raise ExpectedArrayOfColumnsError
40
- end
41
-
42
- @columns = {}
43
- columns.each do |column|
44
- add_column column
45
- end
46
-
47
40
  raise ExpectedSymbolError, name unless name.is_a? Symbol
48
41
  @name = name
49
42
 
50
43
  raise ExpectedStringError, check_clause unless check_clause.is_a? String
51
44
  @check_clause = check_clause.strip
52
45
 
46
+ # if this validation is created via configuration (apposed to being loaded) then they can be lazy loaded
47
+ unless from_configuration? && columns.nil?
48
+ # assert that the provided columns is an array
49
+ unless columns.is_a?(Array) && columns.count > 0
50
+ raise ExpectedArrayOfColumnsError
51
+ end
52
+
53
+ @columns = {}
54
+ columns.each do |column|
55
+ add_column column
56
+ end
57
+ end
58
+
53
59
  unless description.nil?
54
60
  raise ExpectedStringError, description unless description.is_a? String
55
61
  @description = description.strip
@@ -77,23 +83,100 @@ module DynamicMigrations
77
83
 
78
84
  # return an array of this validations columns
79
85
  def columns
86
+ if @columns.nil?
87
+ @columns = {}
88
+ normalized_check_clause_and_column_names[:column_names].each do |column_name|
89
+ add_column table.column(column_name)
90
+ end
91
+ end
80
92
  @columns.values
81
93
  end
82
94
 
83
95
  def column_names
84
- @columns.keys
96
+ columns.map(&:name)
85
97
  end
86
98
 
87
99
  def differences_descriptions other_validation
88
100
  method_differences_descriptions other_validation, [
89
- :check_clause,
101
+ :normalized_check_clause,
90
102
  :deferrable,
91
103
  :initially_deferred
92
104
  ]
93
105
  end
94
106
 
107
+ # create a temporary table in postgres to represent this validation and fetch
108
+ # the actual normalized check constraint directly from the database
109
+ def normalized_check_clause
110
+ # no need to normalize check_clauses which originated from the database
111
+ if from_database?
112
+ check_clause
113
+ else
114
+ normalized_check_clause_and_column_names[:check_clause]
115
+ end
116
+ end
117
+
95
118
  private
96
119
 
120
+ def normalized_check_clause_and_column_names
121
+ @normalized_check_clause_and_column_names ||= fetch_normalized_check_clause_and_column_names
122
+ end
123
+
124
+ def fetch_normalized_check_clause_and_column_names
125
+ result = table.schema.database.with_connection do |connection|
126
+ # wrapped in a transaction just in case something here fails, because
127
+ # we don't want the temporary table to be persisted
128
+ connection.exec("BEGIN")
129
+
130
+ # create the temp table and add the expected columns and constraint
131
+ connection.exec(<<~SQL)
132
+ CREATE TEMP TABLE validation_normalized_check_clause_temp_table (
133
+ #{columns.map { |column| '"' + column.name.to_s + '" ' + column.temp_table_data_type.to_s }.join(", ")},
134
+ CONSTRAINT #{name} CHECK (#{check_clause})
135
+ );
136
+ SQL
137
+
138
+ # get the normalized version of the constraint
139
+ rows = connection.exec(<<~SQL)
140
+ SELECT
141
+ pg_get_constraintdef(pg_constraint.oid) AS check_clause,
142
+ ARRAY_AGG(col.attname ORDER BY u.attposition) AS column_names
143
+ FROM pg_constraint
144
+ LEFT JOIN LATERAL UNNEST(pg_constraint.conkey)
145
+ WITH ORDINALITY AS u(attnum, attposition)
146
+ ON TRUE
147
+ LEFT JOIN pg_attribute col
148
+ ON
149
+ (col.attrelid = pg_constraint.conrelid
150
+ AND col.attnum = u.attnum)
151
+ WHERE conrelid = 'validation_normalized_check_clause_temp_table'::regclass
152
+ GROUP BY pg_constraint.oid;
153
+ SQL
154
+
155
+ # delete the temp table and close the transaction
156
+ connection.exec("ROLLBACK")
157
+
158
+ rows.first
159
+ end
160
+
161
+ if result["check_clause"].nil?
162
+ raise UnnormalizableCheckClauseError, "Failed to nomalize check clause `#{check_clause}`"
163
+ end
164
+
165
+ # extract the check clause from the result "CHECK(%check_clause%)"
166
+ matches = result["check_clause"].match(/\ACHECK \((?<inner_clause>.*)\)\z/)
167
+ if matches.nil?
168
+ raise UnnormalizableCheckClauseError, "Unparsable normalized check_clause #{result["check_clause"]}"
169
+ end
170
+
171
+ normalized_column_names = result["column_names"].gsub(/\A\{/, "").gsub(/\}\Z/, "").split(",").map { |column_name| column_name.to_sym }
172
+
173
+ # return the normalized check clause
174
+ {
175
+ check_clause: matches[:inner_clause],
176
+ column_names: normalized_column_names
177
+ }
178
+ end
179
+
97
180
  # used internally to set the columns from this objects initialize method
98
181
  def add_column column
99
182
  # assert that the provided dsl name is an array of Columns
@@ -42,7 +42,7 @@ module DynamicMigrations
42
42
  if has_validation? name
43
43
  raise(ValidationAlreadyExistsError, "Validation #{name} already exists")
44
44
  end
45
- columns = column_names.map { |column_name| column column_name }
45
+ columns = column_names&.map { |column_name| column column_name }
46
46
  included_target = self
47
47
  if included_target.is_a? Table
48
48
  new_validation = @validations[name] = Validation.new source, included_target, columns, name, check_clause, **validation_options
@@ -26,6 +26,7 @@ module DynamicMigrations
26
26
  attr_reader :schema
27
27
  attr_reader :name
28
28
  attr_reader :description
29
+ attr_reader :remote_foreign_key_constraints
29
30
 
30
31
  # initialize a new object to represent a postgres table
31
32
  def initialize source, schema, name, description: nil
@@ -47,6 +48,7 @@ module DynamicMigrations
47
48
  @validations = {}
48
49
  @indexes = {}
49
50
  @foreign_key_constraints = {}
51
+ @remote_foreign_key_constraints = []
50
52
  @triggers = {}
51
53
  @unique_constraints = {}
52
54
  end
@@ -66,6 +66,14 @@ module DynamicMigrations
66
66
  SQL
67
67
  end
68
68
 
69
+ def refresh_database_structure_cache
70
+ connection.exec(<<~SQL)
71
+ REFRESH MATERIALIZED VIEW public.dynamic_migrations_structure_cache
72
+ SQL
73
+ rescue PG::UndefinedTable
74
+ create_database_structure_cache
75
+ end
76
+
69
77
  # fetch all columns from the database and build and return a
70
78
  # useful hash representing the structure of your database
71
79
  def fetch_structure
@@ -100,7 +108,7 @@ module DynamicMigrations
100
108
 
101
109
  column[:data_type] = row["data_type"].to_sym
102
110
  column[:null] = row["is_nullable"] == "YES"
103
- column[:is_enum] = row["is_enum"] == "TRUE"
111
+ column[:is_enum] = row["is_enum"] == "t"
104
112
  column[:default] = row["column_default"]
105
113
  column[:description] = row["column_description"]
106
114
  column[:interval_type] = row["interval_type"].nil? ? nil : row["interval_type"].to_sym
@@ -91,9 +91,10 @@ module DynamicMigrations
91
91
  schema = schemas[event_object_schema] ||= {}
92
92
  table = schema[event_object_table] ||= {}
93
93
 
94
- # by convention (and to simplify things) we place these all in the same schema
95
- unless row["trigger_schema"] == row["function_schema"] && row["function_schema"] == row["event_object_schema"]
96
- raise EventTriggerProcedureSchemaMismatchError, "Expected trigger, procedure and event_object to be in the same schema for trigger '#{trigger_name}'"
94
+ # By convention (and to simplify things) we place the trigger and the triggers table in the same schema
95
+ # The function can be in a different schema (and often is, expecially for shared functions)
96
+ unless row["trigger_schema"] == row["event_object_schema"]
97
+ raise EventTriggerProcedureSchemaMismatchError, "Expected trigger and event_object to be in the same schema for trigger '#{trigger_name}'"
97
98
  end
98
99
 
99
100
  # turn the parameters into an array of strings
@@ -7,36 +7,35 @@ module DynamicMigrations
7
7
  module ValidationsLoader
8
8
  def create_database_validations_cache
9
9
  connection.exec(<<~SQL)
10
- CREATE MATERIALIZED VIEW public.dynamic_migrations_validations_cache as
11
- SELECT table_constraints.table_schema as schema_name,
12
- table_constraints.table_name,
13
- array_agg(col.column_name ORDER BY col.column_name) AS columns,
14
- table_constraints.constraint_name as validation_name,
15
- pg_get_expr(conbin, conrelid, true) as check_clause,
16
- obj_description(pgc.oid, 'pg_constraint') as description,
10
+ CREATE MATERIALIZED VIEW public.dynamic_migrations_validations_cache AS
11
+ SELECT
12
+ nspname AS schema_name,
13
+ pg_constraint_class.relname AS table_name,
14
+ array_agg(columns.column_name ORDER BY columns.column_name) AS columns,
15
+ pg_get_constraintdef(pg_constraint.oid) AS check_clause,
16
+ conname AS validation_name,
17
+ obj_description(pg_constraint.oid, 'pg_constraint') AS description,
17
18
  -- in case we need to update this query in a later version of DynamicMigrations
18
19
  1 as table_version
19
- FROM information_schema.table_constraints
20
- JOIN information_schema.check_constraints
21
- ON table_constraints.constraint_schema = check_constraints.constraint_schema
22
- AND table_constraints.constraint_name = check_constraints.constraint_name
23
- JOIN pg_namespace nsp ON nsp.nspname = check_constraints.constraint_schema
24
- JOIN pg_constraint pgc ON pgc.conname = check_constraints.constraint_name
25
- AND pgc.connamespace = nsp.oid
26
- AND pgc.contype = 'c'
27
- JOIN information_schema.columns col
28
- ON col.table_schema = table_constraints.table_schema
29
- AND col.table_name = table_constraints.table_name
30
- AND col.ordinal_position = ANY(pgc.conkey)
31
- WHERE table_constraints.constraint_schema != 'information_schema'
32
- AND table_constraints.constraint_schema != 'postgis'
33
- AND left(table_constraints.constraint_schema, 3) != 'pg_'
34
- GROUP BY
35
- pgc.oid,
36
- table_constraints.table_schema,
37
- table_constraints.table_name,
38
- table_constraints.constraint_name,
39
- check_constraints.check_clause;
20
+ FROM pg_catalog.pg_constraint
21
+ INNER JOIN pg_catalog.pg_class pg_constraint_class
22
+ ON pg_constraint_class.oid = pg_constraint.conrelid
23
+ INNER JOIN pg_catalog.pg_namespace pg_constraint_namespace
24
+ ON pg_constraint_namespace.oid = connamespace
25
+ JOIN information_schema.columns
26
+ ON columns.table_schema = nspname
27
+ AND columns.table_name = pg_constraint_class.relname
28
+ AND columns.ordinal_position = ANY(pg_constraint.conkey)
29
+ WHERE
30
+ contype = 'c'
31
+ AND nspname != 'information_schema'
32
+ AND nspname != 'postgis'
33
+ AND left(nspname, 3) != 'pg_'
34
+ GROUP BY
35
+ pg_constraint.oid,
36
+ nspname,
37
+ pg_constraint_class.relname,
38
+ conname;
40
39
  SQL
41
40
  connection.exec(<<~SQL)
42
41
  CREATE UNIQUE INDEX dynamic_migrations_validations_cache_index ON public.dynamic_migrations_validations_cache (schema_name, table_name, validation_name);
@@ -46,6 +45,14 @@ module DynamicMigrations
46
45
  SQL
47
46
  end
48
47
 
48
+ def refresh_database_validations_cache
49
+ connection.exec(<<~SQL)
50
+ REFRESH MATERIALIZED VIEW public.dynamic_migrations_validations_cache
51
+ SQL
52
+ rescue PG::UndefinedTable
53
+ create_database_validations_cache
54
+ end
55
+
49
56
  # fetch all columns from the database and build and return a
50
57
  # useful hash representing the validations of your database
51
58
  def fetch_validations
@@ -70,9 +77,15 @@ module DynamicMigrations
70
77
 
71
78
  validation_name = row["validation_name"].to_sym
72
79
 
80
+ matches = row["check_clause"].match(/\ACHECK \((?<inner_clause>.*)\)\z/)
81
+ if matches.nil?
82
+ raise StandardError, "Unparsable check_clause #{row["check_clause"]}"
83
+ end
84
+ check_clause = matches[:inner_clause]
85
+
73
86
  table[validation_name] = {
74
87
  columns: row["columns"].gsub(/\A\{/, "").gsub(/\}\Z/, "").split(",").map { |column_name| column_name.to_sym },
75
- check_clause: row["check_clause"],
88
+ check_clause: check_clause,
76
89
  description: row["description"],
77
90
  deferrable: row["deferrable"] == "TRUE",
78
91
  initially_deferred: row["initially_deferred"] == "TRUE"
@@ -55,6 +55,12 @@ module DynamicMigrations
55
55
  def differences
56
56
  Differences.new(self)
57
57
  end
58
+
59
+ def refresh_caches
60
+ refresh_database_structure_cache
61
+ refresh_database_keys_and_unique_constraints_cache
62
+ refresh_database_validations_cache
63
+ end
58
64
  end
59
65
  end
60
66
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module DynamicMigrations
4
- VERSION = "3.6.15"
4
+ VERSION = "3.7.0"
5
5
  end
@@ -95,6 +95,7 @@ require "dynamic_migrations/active_record/migrators/trigger"
95
95
  require "dynamic_migrations/active_record/migrators/table"
96
96
  require "dynamic_migrations/active_record/migrators/index"
97
97
  require "dynamic_migrations/active_record/migrators/enum"
98
+ require "dynamic_migrations/active_record/migrators/primary_key"
98
99
  require "dynamic_migrations/active_record/migrators/column"
99
100
  require "dynamic_migrations/active_record/migrators"
100
101
 
@@ -0,0 +1,18 @@
1
+ # TypeProf 0.21.7
2
+
3
+ # Classes
4
+ module DynamicMigrations
5
+ module ActiveRecord
6
+ module Migrators
7
+ module PrimaryKey
8
+ def set_primary_key_comment: (Symbol table_name, Symbol primary_key_name, String comment) -> void
9
+ def remove_primary_key_comment: (Symbol table_name, Symbol primary_key_name) -> void
10
+
11
+ # stubbing these out, as they are available on the module which includes this module
12
+ def execute: (String sql) -> void
13
+ def schema_name: () -> Symbol
14
+ def quote: (String str) -> String
15
+ end
16
+ end
17
+ end
18
+ end
@@ -8,6 +8,8 @@ module DynamicMigrations
8
8
  def add_primary_key: (Postgres::Server::Database::Schema::Table::PrimaryKey primary_key, ?String? code_comment) -> Fragment
9
9
  def remove_primary_key: (Postgres::Server::Database::Schema::Table::PrimaryKey primary_key, ?String? code_comment) -> Fragment
10
10
  def recreate_primary_key: (Postgres::Server::Database::Schema::Table::PrimaryKey original_primary_key, Postgres::Server::Database::Schema::Table::PrimaryKey updated_primary_key) -> Array[Fragment]
11
+ def set_primary_key_comment: (Postgres::Server::Database::Schema::Table::PrimaryKey primary_key, ?String? code_comment) -> Fragment
12
+ def remove_primary_key_comment: (Postgres::Server::Database::Schema::Table::PrimaryKey primary_key, ?String? code_comment) -> Fragment
11
13
 
12
14
  # these come from the generator object (which this module is included into)
13
15
  def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?, ?dependent_function: Server::Database::Schema::Function?, ?dependent_enum: Server::Database::Schema::Enum?) -> Fragment
@@ -13,6 +13,8 @@ module DynamicMigrations
13
13
  # these come from the generator object (which this module is included into)
14
14
  def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?, ?dependent_function: Server::Database::Schema::Function?, ?dependent_enum: Server::Database::Schema::Enum?) -> Fragment
15
15
  def add_column: (Postgres::Server::Database::Schema::Table::Column column, ?String? code_comment) -> Fragment
16
+ def set_column_comment: (Postgres::Server::Database::Schema::Table::Column column, ?String? code_comment) -> Fragment
17
+ def set_primary_key_comment: (Postgres::Server::Database::Schema::Table::PrimaryKey primary_key, ?String? code_comment) -> Fragment
16
18
 
17
19
  def indent: (String migration, ?Integer levels) -> String
18
20
 
@@ -6,20 +6,20 @@ module DynamicMigrations
6
6
  class Generator
7
7
  class ValidationTemplateBase
8
8
 
9
- attr_reader validation: untyped
9
+ attr_reader validation: Postgres::Server::Database::Schema::Table::Validation
10
10
  attr_reader code_comment: String?
11
11
 
12
- def initialize: (untyped validation, untyped code_comment) -> void
12
+ def initialize: (Postgres::Server::Database::Schema::Table::Validation validation, String? code_comment) -> void
13
13
 
14
14
  # abstract method (should actually be added to child classes)
15
15
  def fragment_arguments: -> {schema: Postgres::Server::Database::Schema, table: Postgres::Server::Database::Schema::Table, migration_method: Symbol, object: untyped, code_comment: String?, migration: String, dependent_function: Postgres::Server::Database::Schema::Function?}
16
16
 
17
17
  private
18
- def assert_not_deferred!: -> nil
19
- def assert_column_count!: (?Integer count) -> nil
20
- def first_column: -> untyped
21
- def value_from_check_clause: (untyped regex) -> untyped
22
- def name_and_description_options_string: (untyped default_name) -> String?
18
+ def assert_not_deferred!: -> void
19
+ def assert_column_count!: (?Integer count) -> void
20
+ def first_column: -> Postgres::Server::Database::Schema::Table::Column
21
+ def value_from_check_clause: (Regexp regex) -> untyped
22
+ def name_and_description_options_string: (Symbol default_name, ?String? default_comment) -> String?
23
23
  def indent: (String multi_line_string, ?Integer levels) -> String
24
24
 
25
25
  class TemplateError < StandardError
@@ -31,9 +31,9 @@ module DynamicMigrations
31
31
  def supported_migration_method?: (Symbol migration_method) -> bool
32
32
  def add_fragment: (migration_method: Symbol, object: untyped, migration: String, ?schema: Server::Database::Schema?, ?table: Server::Database::Schema::Table?, ?code_comment: String?, ?dependent_table: Server::Database::Schema::Table?, ?dependent_function: Server::Database::Schema::Function?, ?dependent_enum: Server::Database::Schema::Enum?) -> Fragment
33
33
  def indent: (String migration, ?Integer levels) -> String
34
- def strip_empty_lines: (String migration) -> String
35
34
  def tsort_each_node: -> Enumerator[untyped, untyped]
36
35
  def tsort_each_child: (untyped node) -> untyped
36
+ def trim_lines: (String migration) -> String
37
37
 
38
38
  class ExpectedSymbolError < StandardError
39
39
  end
@@ -8,7 +8,7 @@ module DynamicMigrations
8
8
  def connect: -> PG::Connection
9
9
  def connection: -> PG::Connection
10
10
  def disconnect: -> void
11
- def with_connection: -> void
11
+ def with_connection: -> untyped
12
12
 
13
13
  # these come from the database object (which this module is included into)
14
14
  def name: -> Symbol
@@ -5,6 +5,7 @@ module DynamicMigrations
5
5
  module KeysAndUniqueConstraintsLoader
6
6
  def create_database_keys_and_unique_constraints_cache: -> void
7
7
  def fetch_keys_and_unique_constraints: -> Hash[untyped, untyped]
8
+ def refresh_database_keys_and_unique_constraints_cache: -> void
8
9
 
9
10
  # these come from the database object (which this module is included into)
10
11
  def connection: -> PG::Connection
@@ -9,10 +9,10 @@ module DynamicMigrations
9
9
  class Enum < Source
10
10
  attr_reader schema: Schema
11
11
  attr_reader name: Symbol
12
- attr_reader values: Array[Symbol]
12
+ attr_reader values: Array[String]
13
13
  attr_reader description: String?
14
14
  attr_reader columns: Array[Table::Column]
15
- def initialize: (database_or_configuration source, Schema schema, Symbol name, Array[Symbol] values, ?description: String?) -> void
15
+ def initialize: (database_or_configuration source, Schema schema, Symbol name, Array[String] values, ?description: String?) -> void
16
16
  def full_name: -> Symbol
17
17
  def has_description?: -> bool
18
18
  def add_column: (Schema::Table::Column column) -> void
@@ -9,7 +9,7 @@ module DynamicMigrations
9
9
  module Enums
10
10
  @enums: Hash[Symbol, Enum]
11
11
 
12
- def add_enum: (Symbol enum_name, Array[Symbol] values, ?description: String?) -> nil
12
+ def add_enum: (Symbol enum_name, Array[String] values, ?description: String?) -> nil
13
13
  def enum: (Symbol enum_name) -> Enum
14
14
  def has_enum?: (Symbol enum_name) -> bool
15
15
  def enums: -> Array[Enum]
@@ -7,6 +7,8 @@ module DynamicMigrations
7
7
  class Database
8
8
  class Schema
9
9
  class Function < Source
10
+ @normalized_definition: String?
11
+
10
12
  attr_reader schema: Schema
11
13
  attr_reader name: Symbol
12
14
  attr_reader definition: String
@@ -16,12 +18,19 @@ module DynamicMigrations
16
18
  def has_description?: -> bool
17
19
  def add_trigger: (Schema::Table::Trigger trigger) -> void
18
20
  def differences_descriptions: (Function other_function) -> Array[String]
21
+ def normalized_definition: -> String
22
+
23
+ private
24
+ def fetch_normalized_definition: -> String
19
25
 
20
26
  class ExpectedSchemaError < StandardError
21
27
  end
22
28
 
23
29
  class ExpectedDefinitionError < StandardError
24
30
  end
31
+
32
+ class UnnormalizableDefinitionError < StandardError
33
+ end
25
34
  end
26
35
  end
27
36
  end
@@ -18,6 +18,10 @@ module DynamicMigrations
18
18
  def initialize: (database_or_configuration source, Table table, Symbol name, Symbol data_type, ?null: bool, ?default: untyped, ?description: String?, ?interval_type: Symbol?, ?enum: Enum?) -> void
19
19
  def has_description?: -> bool
20
20
  def array?: -> bool
21
+ def enum?: -> bool
22
+ def temp_table_data_type: -> Symbol
23
+ # untyped because we cant specify this logic in rbs yet (compiler is concerned this might be nil)
24
+ def base_data_type: -> untyped
21
25
 
22
26
  class ExpectedTableError < StandardError
23
27
  end
@@ -38,9 +38,6 @@ module DynamicMigrations
38
38
  class ExpectedArrayOfColumnsError < StandardError
39
39
  end
40
40
 
41
- class ExpectedDifferentTablesError < StandardError
42
- end
43
-
44
41
  class DuplicateColumnError < StandardError
45
42
  end
46
43
 
@@ -12,6 +12,7 @@ module DynamicMigrations
12
12
  def foreign_key_constraints: -> Array[ForeignKeyConstraint]
13
13
  def foreign_key_constraints_hash: -> Hash[Symbol, ForeignKeyConstraint]
14
14
  def add_foreign_key_constraint: (Symbol name, Array[Symbol] column_names, Symbol foreign_schema_name, Symbol foreign_table_name, Array[Symbol] foreign_column_names, **untyped) -> untyped
15
+ def add_remote_foreign_key_constraint: (ForeignKeyConstraint foreign_key_constraint) -> untyped
15
16
 
16
17
  # these come from the table object (which this module is included into)
17
18
  def source: -> database_or_configuration