dynamic_migrations 3.6.15 → 3.7.0

Sign up to get free protection for your applications and to get access to all the features.
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