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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +23 -0
- data/lib/dynamic_migrations/active_record/migrators/column.rb +21 -0
- data/lib/dynamic_migrations/active_record/migrators/foreign_key_constraint.rb +112 -0
- data/lib/dynamic_migrations/active_record/migrators/function.rb +108 -0
- data/lib/dynamic_migrations/active_record/migrators/index.rb +27 -0
- data/lib/dynamic_migrations/active_record/migrators/schema.rb +21 -0
- data/lib/dynamic_migrations/active_record/migrators/table.rb +21 -0
- data/lib/dynamic_migrations/active_record/migrators/trigger.rb +109 -0
- data/lib/dynamic_migrations/active_record/migrators/unique_constraint.rb +63 -0
- data/lib/dynamic_migrations/active_record/migrators/validation.rb +67 -0
- data/lib/dynamic_migrations/active_record/migrators.rb +64 -0
- data/lib/dynamic_migrations/name_helper.rb +13 -0
- data/lib/dynamic_migrations/postgres/generator/column.rb +92 -0
- data/lib/dynamic_migrations/postgres/generator/foreign_key_constraint.rb +84 -0
- data/lib/dynamic_migrations/postgres/generator/fragment.rb +30 -0
- data/lib/dynamic_migrations/postgres/generator/function.rb +77 -0
- data/lib/dynamic_migrations/postgres/generator/index.rb +101 -0
- data/lib/dynamic_migrations/postgres/generator/primary_key.rb +55 -0
- data/lib/dynamic_migrations/postgres/generator/schema.rb +19 -0
- data/lib/dynamic_migrations/postgres/generator/schema_migrations/section.rb +37 -0
- data/lib/dynamic_migrations/postgres/generator/schema_migrations.rb +92 -0
- data/lib/dynamic_migrations/postgres/generator/table.rb +122 -0
- data/lib/dynamic_migrations/postgres/generator/trigger.rb +101 -0
- data/lib/dynamic_migrations/postgres/generator/unique_constraint.rb +79 -0
- data/lib/dynamic_migrations/postgres/generator/validation.rb +87 -0
- data/lib/dynamic_migrations/postgres/generator.rb +359 -0
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/functions.rb +68 -0
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/columns.rb +72 -0
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/foreign_key_constraints.rb +73 -0
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/indexes.rb +73 -0
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/primary_key.rb +49 -0
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/triggers.rb +73 -0
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/unique_constraints.rb +73 -0
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables/validations.rb +73 -0
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas/tables.rb +80 -0
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations/schemas.rb +48 -0
- data/lib/dynamic_migrations/postgres/server/database/differences/to_migrations.rb +59 -0
- data/lib/dynamic_migrations/postgres/server/database/differences.rb +76 -16
- data/lib/dynamic_migrations/postgres/server/database/keys_and_unique_constraints_loader.rb +35 -9
- data/lib/dynamic_migrations/postgres/server/database/loaded_schemas_builder.rb +50 -26
- data/lib/dynamic_migrations/postgres/server/database/schema/function.rb +69 -0
- data/lib/dynamic_migrations/postgres/server/database/schema/functions.rb +63 -0
- data/lib/dynamic_migrations/postgres/server/database/schema/table/column.rb +6 -44
- data/lib/dynamic_migrations/postgres/server/database/schema/table/columns.rb +1 -1
- data/lib/dynamic_migrations/postgres/server/database/schema/table/foreign_key_constraint.rb +40 -5
- data/lib/dynamic_migrations/postgres/server/database/schema/table/index.rb +23 -9
- data/lib/dynamic_migrations/postgres/server/database/schema/table/primary_key.rb +21 -6
- data/lib/dynamic_migrations/postgres/server/database/schema/table/trigger.rb +151 -0
- data/lib/dynamic_migrations/postgres/server/database/schema/table/triggers.rb +66 -0
- data/lib/dynamic_migrations/postgres/server/database/schema/table/unique_constraint.rb +19 -9
- data/lib/dynamic_migrations/postgres/server/database/schema/table/validation.rb +20 -1
- data/lib/dynamic_migrations/postgres/server/database/schema/table.rb +15 -5
- data/lib/dynamic_migrations/postgres/server/database/schema/tables.rb +63 -0
- data/lib/dynamic_migrations/postgres/server/database/schema.rb +3 -49
- data/lib/dynamic_migrations/postgres/server/database/source.rb +21 -0
- data/lib/dynamic_migrations/postgres/server/database/structure_loader.rb +22 -112
- data/lib/dynamic_migrations/postgres/server/database/triggers_and_functions_loader.rb +131 -0
- data/lib/dynamic_migrations/postgres/server/database/validations_loader.rb +10 -4
- data/lib/dynamic_migrations/postgres/server/database.rb +2 -1
- data/lib/dynamic_migrations/postgres/server.rb +6 -0
- data/lib/dynamic_migrations/postgres.rb +1 -1
- data/lib/dynamic_migrations/version.rb +1 -1
- data/lib/dynamic_migrations.rb +47 -4
- metadata +44 -3
- 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 '
|
15
|
-
WHEN 'p'::"char" THEN '
|
16
|
-
WHEN 'u'::"char" THEN '
|
17
|
-
END
|
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
|
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.
|
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.
|
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
|
-
|
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
|
-
|
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 :
|
66
|
-
table.add_primary_key constraint_name, constraint_definition[:column_names],
|
51
|
+
when :primary_key
|
52
|
+
table.add_primary_key constraint_name, constraint_definition[:column_names], description: constraint_definition[:description]
|
67
53
|
|
68
|
-
when :
|
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 :
|
72
|
-
table.add_unique_constraint constraint_name, constraint_definition[:column_names],
|
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,
|
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,
|
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 :
|
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,
|
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
|
-
|
49
|
-
|
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
|