dynamic_migrations 1.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +13 -0
  3. data/CODE_OF_CONDUCT.md +84 -0
  4. data/LICENSE.txt +21 -0
  5. data/README.md +71 -0
  6. data/lib/dynamic_migrations/expected_boolean_error.rb +4 -0
  7. data/lib/dynamic_migrations/expected_integer_error.rb +4 -0
  8. data/lib/dynamic_migrations/expected_string_error.rb +4 -0
  9. data/lib/dynamic_migrations/expected_symbol_error.rb +4 -0
  10. data/lib/dynamic_migrations/invalid_source_error.rb +7 -0
  11. data/lib/dynamic_migrations/module_included_into_unexpected_target_error.rb +4 -0
  12. data/lib/dynamic_migrations/postgres/connections.rb +42 -0
  13. data/lib/dynamic_migrations/postgres/data_types.rb +273 -0
  14. data/lib/dynamic_migrations/postgres/server/database/configured_schemas.rb +55 -0
  15. data/lib/dynamic_migrations/postgres/server/database/connection.rb +39 -0
  16. data/lib/dynamic_migrations/postgres/server/database/differences.rb +292 -0
  17. data/lib/dynamic_migrations/postgres/server/database/keys_and_unique_constraints_loader.rb +149 -0
  18. data/lib/dynamic_migrations/postgres/server/database/loaded_schemas.rb +55 -0
  19. data/lib/dynamic_migrations/postgres/server/database/loaded_schemas_builder.rb +86 -0
  20. data/lib/dynamic_migrations/postgres/server/database/schema/table/column.rb +84 -0
  21. data/lib/dynamic_migrations/postgres/server/database/schema/table/columns.rb +58 -0
  22. data/lib/dynamic_migrations/postgres/server/database/schema/table/foreign_key_constraint.rb +132 -0
  23. data/lib/dynamic_migrations/postgres/server/database/schema/table/foreign_key_constraints.rb +62 -0
  24. data/lib/dynamic_migrations/postgres/server/database/schema/table/index.rb +144 -0
  25. data/lib/dynamic_migrations/postgres/server/database/schema/table/indexes.rb +63 -0
  26. data/lib/dynamic_migrations/postgres/server/database/schema/table/primary_key.rb +83 -0
  27. data/lib/dynamic_migrations/postgres/server/database/schema/table/unique_constraint.rb +101 -0
  28. data/lib/dynamic_migrations/postgres/server/database/schema/table/unique_constraints.rb +59 -0
  29. data/lib/dynamic_migrations/postgres/server/database/schema/table/validation.rb +90 -0
  30. data/lib/dynamic_migrations/postgres/server/database/schema/table/validations.rb +59 -0
  31. data/lib/dynamic_migrations/postgres/server/database/schema/table.rb +73 -0
  32. data/lib/dynamic_migrations/postgres/server/database/schema.rb +72 -0
  33. data/lib/dynamic_migrations/postgres/server/database/source.rb +37 -0
  34. data/lib/dynamic_migrations/postgres/server/database/structure_loader.rb +242 -0
  35. data/lib/dynamic_migrations/postgres/server/database/validations_loader.rb +81 -0
  36. data/lib/dynamic_migrations/postgres/server/database.rb +54 -0
  37. data/lib/dynamic_migrations/postgres/server.rb +33 -0
  38. data/lib/dynamic_migrations/postgres.rb +8 -0
  39. data/lib/dynamic_migrations/version.rb +5 -0
  40. data/lib/dynamic_migrations.rb +44 -0
  41. metadata +113 -0
@@ -0,0 +1,58 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DynamicMigrations
4
+ module Postgres
5
+ class Server
6
+ class Database
7
+ class Schema
8
+ class Table < Source
9
+ # This module has all the tables methods for working with columns
10
+ module Columns
11
+ class ColumnDoesNotExistError < StandardError
12
+ end
13
+
14
+ class DuplicateColumnError < StandardError
15
+ end
16
+
17
+ # returns the column object for the provided column name, and raises an
18
+ # error if the column does not exist
19
+ def column column_name
20
+ raise ExpectedSymbolError, column_name unless column_name.is_a? Symbol
21
+ raise ColumnDoesNotExistError unless has_column? column_name
22
+ @columns[column_name]
23
+ end
24
+
25
+ # returns true if this table has a column with the provided name, otherwise false
26
+ def has_column? column_name
27
+ raise ExpectedSymbolError, column_name unless column_name.is_a? Symbol
28
+ @columns.key? column_name
29
+ end
30
+
31
+ # returns an array of this tables columns
32
+ def columns
33
+ @columns.values
34
+ end
35
+
36
+ def columns_hash
37
+ @columns
38
+ end
39
+
40
+ # adds a new column to this table, and returns it
41
+ def add_column column_name, data_type, **column_options
42
+ if has_column? column_name
43
+ raise(DuplicateColumnError, "Column #{column_name} already exists")
44
+ end
45
+ included_target = self
46
+ if included_target.is_a? Table
47
+ @columns[column_name] = Column.new source, included_target, column_name, data_type, **column_options
48
+ else
49
+ raise ModuleIncludedIntoUnexpectedTargetError, included_target
50
+ end
51
+ end
52
+ end
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,132 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DynamicMigrations
4
+ module Postgres
5
+ class Server
6
+ class Database
7
+ class Schema
8
+ class Table
9
+ # This class represents a postgres foreign key constraint
10
+ class ForeignKeyConstraint < Source
11
+ class ExpectedTableError < StandardError
12
+ end
13
+
14
+ class ExpectedArrayOfColumnsError < StandardError
15
+ end
16
+
17
+ class ExpectedDifferentTablesError < StandardError
18
+ end
19
+
20
+ class DuplicateColumnError < StandardError
21
+ end
22
+
23
+ attr_reader :table
24
+ attr_reader :foreign_table
25
+ attr_reader :foreign_key_constraint_name
26
+ attr_reader :deferrable
27
+ attr_reader :initially_deferred
28
+
29
+ # initialize a new object to represent a foreign_key_constraint in a postgres table
30
+ def initialize source, table, columns, foreign_table, foreign_columns, foreign_key_constraint_name, deferrable: false, initially_deferred: false
31
+ super source
32
+
33
+ raise ExpectedTableError, table unless table.is_a? Table
34
+ raise ExpectedTableError, foreign_table unless foreign_table.is_a? Table
35
+
36
+ # assert that the provided columns is an array
37
+ unless columns.is_a?(Array) && columns.count > 0
38
+ raise ExpectedArrayOfColumnsError
39
+ end
40
+
41
+ # assert that the provided foreign columns is an array
42
+ unless foreign_columns.is_a?(Array) && foreign_columns.count > 0
43
+ raise ExpectedArrayOfColumnsError
44
+ end
45
+
46
+ if table.table_name == foreign_table.table_name && table.schema.schema_name == foreign_table.schema.schema_name
47
+ raise ExpectedDifferentTablesError
48
+ end
49
+
50
+ # tables must be set before the columns are added
51
+ @table = table
52
+ @foreign_table = foreign_table
53
+
54
+ @columns = {}
55
+ columns.each do |column|
56
+ add_column column
57
+ end
58
+
59
+ @foreign_columns = {}
60
+ foreign_columns.each do |column|
61
+ add_column column, true
62
+ end
63
+
64
+ raise ExpectedSymbolError, foreign_key_constraint_name unless foreign_key_constraint_name.is_a? Symbol
65
+ @foreign_key_constraint_name = foreign_key_constraint_name
66
+
67
+ raise ExpectedBooleanError, deferrable unless [true, false].include?(deferrable)
68
+ @deferrable = deferrable
69
+
70
+ raise ExpectedBooleanError, initially_deferred unless [true, false].include?(initially_deferred)
71
+ @initially_deferred = initially_deferred
72
+ end
73
+
74
+ def columns
75
+ @columns.values
76
+ end
77
+
78
+ def column_names
79
+ @columns.keys
80
+ end
81
+
82
+ def foreign_columns
83
+ @foreign_columns.values
84
+ end
85
+
86
+ def foreign_column_names
87
+ @foreign_columns.keys
88
+ end
89
+
90
+ def foreign_schema_name
91
+ @foreign_table.schema.schema_name
92
+ end
93
+
94
+ def foreign_table_name
95
+ @foreign_table.table_name
96
+ end
97
+
98
+ private
99
+
100
+ # used internally to set the columns from this objects initialize method
101
+ def add_column column, foreign = false
102
+ if foreign
103
+ cs = @foreign_columns
104
+ t = @foreign_table
105
+ else
106
+ cs = @columns
107
+ t = @table
108
+ end
109
+
110
+ # assert that the provided dsl name is an array of Columns
111
+ unless column.is_a? Column
112
+ raise ExpectedArrayOfColumnsError
113
+ end
114
+
115
+ # assert that the provided column exists within this foreign_key_constraints table
116
+ unless t.has_column? column.column_name
117
+ raise ExpectedArrayOfColumnsError, "One or more columns do not exist in this foreign_key_constraints table"
118
+ end
119
+
120
+ if cs.key? column.column_name
121
+ raise(DuplicateColumnError, "Column #{column.column_name} already exists")
122
+ end
123
+
124
+ cs[column.column_name] = column
125
+ end
126
+ end
127
+ end
128
+ end
129
+ end
130
+ end
131
+ end
132
+ end
@@ -0,0 +1,62 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DynamicMigrations
4
+ module Postgres
5
+ class Server
6
+ class Database
7
+ class Schema
8
+ class Table < Source
9
+ # This module has all the tables methods for working with foreign keys
10
+ module ForeignKeyConstraints
11
+ class ForeignKeyConstraintDoesNotExistError < StandardError
12
+ end
13
+
14
+ class ForeignKeyConstraintAlreadyExistsError < StandardError
15
+ end
16
+
17
+ # returns the foreign_key_constraint object for the provided foreign_key_constraint name, and raises an
18
+ # error if the foreign_key_constraint does not exist
19
+ def foreign_key_constraint foreign_key_constraint_name
20
+ raise ExpectedSymbolError, foreign_key_constraint_name unless foreign_key_constraint_name.is_a? Symbol
21
+ raise ForeignKeyConstraintDoesNotExistError unless has_foreign_key_constraint? foreign_key_constraint_name
22
+ @foreign_key_constraints[foreign_key_constraint_name]
23
+ end
24
+
25
+ # returns true if this table has a foreign_key_constraint with the provided name, otherwise false
26
+ def has_foreign_key_constraint? foreign_key_constraint_name
27
+ raise ExpectedSymbolError, foreign_key_constraint_name unless foreign_key_constraint_name.is_a? Symbol
28
+ @foreign_key_constraints.key? foreign_key_constraint_name
29
+ end
30
+
31
+ # returns an array of this tables foreign_key_constraints
32
+ def foreign_key_constraints
33
+ @foreign_key_constraints.values
34
+ end
35
+
36
+ def foreign_key_constraints_hash
37
+ @foreign_key_constraints
38
+ end
39
+
40
+ # adds a new foreign_key_constraint to this table, and returns it
41
+ def add_foreign_key_constraint foreign_key_constraint_name, column_names, foreign_schema_name, foreign_table_name, foreign_column_names, **foreign_key_constraint_options
42
+ if has_foreign_key_constraint? foreign_key_constraint_name
43
+ raise(ForeignKeyConstraintAlreadyExistsError, "foreign_key_constraint #{foreign_key_constraint_name} already exists")
44
+ end
45
+ columns = column_names.map { |column_name| column column_name }
46
+ foreign_schema = schema.database.schema foreign_schema_name, source
47
+ foreign_table = foreign_schema.table foreign_table_name
48
+ foreign_columns = foreign_column_names.map { |column_name| foreign_table.column column_name }
49
+ included_target = self
50
+ if included_target.is_a? Table
51
+ @foreign_key_constraints[foreign_key_constraint_name] = ForeignKeyConstraint.new source, included_target, columns, foreign_table, foreign_columns, foreign_key_constraint_name, **foreign_key_constraint_options
52
+ else
53
+ raise ModuleIncludedIntoUnexpectedTargetError, included_target
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
@@ -0,0 +1,144 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DynamicMigrations
4
+ module Postgres
5
+ class Server
6
+ class Database
7
+ class Schema
8
+ class Table
9
+ # This class represents a postgres table index
10
+ class Index < Source
11
+ INDEX_TYPES = [:btree, :hash, :gist, :gin, :bring, :spgist]
12
+ ORDERS = [:asc, :desc]
13
+ NULL_POSITIONS = [:first, :last]
14
+
15
+ class ExpectedTableError < StandardError
16
+ end
17
+
18
+ class ExpectedArrayOfColumnsError < StandardError
19
+ end
20
+
21
+ class UnexpectedIndexTypeError < StandardError
22
+ end
23
+
24
+ class UnexpectedOrderError < StandardError
25
+ end
26
+
27
+ class UnexpectedNullsPositionError < StandardError
28
+ end
29
+
30
+ class DuplicateColumnError < StandardError
31
+ end
32
+
33
+ attr_reader :table
34
+ attr_reader :index_name
35
+ attr_reader :unique
36
+ attr_reader :where
37
+ attr_reader :type
38
+ attr_reader :deferrable
39
+ attr_reader :initially_deferred
40
+ attr_reader :order
41
+ attr_reader :nulls_position
42
+
43
+ # initialize a new object to represent a index in a postgres table
44
+ def initialize source, table, columns, index_name, unique: false, where: nil, type: :btree, deferrable: false, initially_deferred: false, include_columns: [], order: :asc, nulls_position: :last
45
+ super source
46
+ raise ExpectedTableError, table unless table.is_a? Table
47
+ @table = table
48
+ @columns = {}
49
+ @include_columns = {}
50
+
51
+ # assert that the provided columns is an array
52
+ unless columns.is_a?(Array) && columns.count > 0
53
+ raise ExpectedArrayOfColumnsError
54
+ end
55
+
56
+ columns.each do |column|
57
+ add_column column
58
+ end
59
+
60
+ raise ExpectedSymbolError, index_name unless index_name.is_a? Symbol
61
+ @index_name = index_name
62
+
63
+ raise ExpectedBooleanError, unique unless [true, false].include?(unique)
64
+ @unique = unique
65
+
66
+ unless where.nil?
67
+ raise ExpectedStringError, where unless where.is_a? String
68
+ @where = where
69
+ end
70
+
71
+ raise UnexpectedIndexTypeError, type unless INDEX_TYPES.include?(type)
72
+ @type = type
73
+
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
+ # assert that the include_columns is an array (it's optional, so can be an empty array)
81
+ unless include_columns.is_a?(Array)
82
+ raise ExpectedArrayOfColumnsError
83
+ end
84
+
85
+ include_columns.each do |include_column|
86
+ add_column include_column, is_include_column: true
87
+ end
88
+
89
+ raise UnexpectedOrderError, order unless ORDERS.include?(order)
90
+ @order = order
91
+
92
+ raise UnexpectedNullsPositionError, nulls_position unless NULL_POSITIONS.include?(nulls_position)
93
+ @nulls_position = nulls_position
94
+ end
95
+
96
+ # return an array of this indexes columns
97
+ def columns
98
+ @columns.values
99
+ end
100
+
101
+ def column_names
102
+ @columns.keys
103
+ end
104
+
105
+ # return an array of this indexes include_columns
106
+ def include_columns
107
+ @include_columns.values
108
+ end
109
+
110
+ def include_column_names
111
+ @include_columns.keys
112
+ end
113
+
114
+ private
115
+
116
+ # used internally to set the columns from this objects initialize method
117
+ def add_column column, is_include_column: false
118
+ # assert that the provided dsl name is an array of Columns
119
+ unless column.is_a? Column
120
+ raise ExpectedArrayOfColumnsError
121
+ end
122
+
123
+ # assert that the provided column exists within this indexes table
124
+ unless @table.has_column? column.column_name
125
+ raise ExpectedArrayOfColumnsError, "One or more columns do not exist in this indexes table"
126
+ end
127
+
128
+ if @columns.key?(column.column_name) || @include_columns.key?(column.column_name)
129
+ raise(DuplicateColumnError, "Column #{column.column_name} already exists in index, or is already included")
130
+ end
131
+
132
+ if is_include_column
133
+ @include_columns[column.column_name] = column
134
+ else
135
+ @columns[column.column_name] = column
136
+ end
137
+ end
138
+ end
139
+ end
140
+ end
141
+ end
142
+ end
143
+ end
144
+ 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
8
+ class Table < Source
9
+ # This module has all the tables methods for working with indexes
10
+ module Indexes
11
+ class IndexDoesNotExistError < StandardError
12
+ end
13
+
14
+ class IndexAlreadyExistsError < StandardError
15
+ end
16
+
17
+ # returns the index object for the provided index name, and raises an
18
+ # error if the index does not exist
19
+ def index index_name
20
+ raise ExpectedSymbolError, index_name unless index_name.is_a? Symbol
21
+ raise IndexDoesNotExistError unless has_index? index_name
22
+ @indexes[index_name]
23
+ end
24
+
25
+ # returns true if this table has a index with the provided name, otherwise false
26
+ def has_index? index_name
27
+ raise ExpectedSymbolError, index_name unless index_name.is_a? Symbol
28
+ @indexes.key? index_name
29
+ end
30
+
31
+ # returns an array of this tables indexes
32
+ def indexes
33
+ @indexes.values
34
+ end
35
+
36
+ def indexes_hash
37
+ @indexes
38
+ end
39
+
40
+ # adds a new index to this table, and returns it
41
+ # include_column_names in broken out from index_options, because it is converted from an
42
+ # array of column names into an array of columns, and then recombined with the other
43
+ # options which are sent to the index initialize method
44
+ def add_index index_name, column_names, include_column_names: [], **index_options
45
+ if has_index? index_name
46
+ raise(IndexAlreadyExistsError, "index #{index_name} already exists")
47
+ end
48
+ columns = column_names.map { |column_name| column column_name }
49
+ include_columns = include_column_names.map { |column_name| column column_name }
50
+ included_target = self
51
+ if included_target.is_a? Table
52
+ @indexes[index_name] = Index.new source, included_target, columns, index_name, include_columns: include_columns, **index_options
53
+ else
54
+ raise ModuleIncludedIntoUnexpectedTargetError, included_target
55
+ end
56
+ end
57
+ end
58
+ end
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DynamicMigrations
4
+ module Postgres
5
+ class Server
6
+ class Database
7
+ class Schema
8
+ class Table
9
+ # This class represents a postgres table primary_key
10
+ class PrimaryKey < Source
11
+ INDEX_TYPES = [:btree, :gin]
12
+
13
+ class ExpectedTableError < StandardError
14
+ end
15
+
16
+ class ExpectedArrayOfColumnsError < StandardError
17
+ end
18
+
19
+ class UnexpectedIndexTypeError < StandardError
20
+ end
21
+
22
+ class DuplicateColumnError < StandardError
23
+ end
24
+
25
+ attr_reader :table
26
+ attr_reader :primary_key_name
27
+ attr_reader :index_type
28
+
29
+ # initialize a new object to represent a primary_key in a postgres table
30
+ def initialize source, table, columns, primary_key_name, index_type: :btree
31
+ super source
32
+ raise ExpectedTableError, table unless table.is_a? Table
33
+ @table = table
34
+ @columns = {}
35
+
36
+ # assert that the provided columns is an array
37
+ unless columns.is_a?(Array) && columns.count > 0
38
+ raise ExpectedArrayOfColumnsError
39
+ end
40
+
41
+ columns.each do |column|
42
+ add_column column
43
+ end
44
+
45
+ raise ExpectedSymbolError, primary_key_name unless primary_key_name.is_a? Symbol
46
+ @primary_key_name = primary_key_name
47
+
48
+ raise UnexpectedIndexTypeError, index_type unless INDEX_TYPES.include?(index_type)
49
+ @index_type = index_type
50
+ end
51
+
52
+ # return an array of this primary keys columns
53
+ def columns
54
+ @columns.values
55
+ end
56
+
57
+ private
58
+
59
+ # used internally to set the columns from this objects initialize method
60
+ def add_column column
61
+ # assert that the provided dsl name is an array of Columns
62
+ unless column.is_a? Column
63
+ raise ExpectedArrayOfColumnsError
64
+ end
65
+
66
+ # assert that the provided column exists within this primary keys table
67
+ unless @table.has_column? column.column_name
68
+ raise ExpectedArrayOfColumnsError, "One or more columns do not exist in this primary keys table"
69
+ end
70
+
71
+ if @columns.key?(column.column_name)
72
+ raise(DuplicateColumnError, "Column #{column.column_name} already exists in primary_key, or is already included")
73
+ end
74
+
75
+ @columns[column.column_name] = column
76
+ end
77
+ end
78
+ end
79
+ end
80
+ end
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,101 @@
1
+ # frozen_string_literal: true
2
+
3
+ module DynamicMigrations
4
+ module Postgres
5
+ class Server
6
+ class Database
7
+ class Schema
8
+ class Table
9
+ # This class represents a postgres table unique_constraint
10
+ class UniqueConstraint < Source
11
+ INDEX_TYPES = [:btree, :hash, :gist, :gin, :bring, :spgist]
12
+
13
+ class ExpectedTableError < StandardError
14
+ end
15
+
16
+ class ExpectedArrayOfColumnsError < StandardError
17
+ end
18
+
19
+ class UnexpectedIndexTypeError < StandardError
20
+ end
21
+
22
+ class UnexpectedOrderError < StandardError
23
+ end
24
+
25
+ class UnexpectedNullsPositionError < StandardError
26
+ end
27
+
28
+ class DuplicateColumnError < StandardError
29
+ end
30
+
31
+ attr_reader :table
32
+ attr_reader :unique_constraint_name
33
+ attr_reader :index_type
34
+ attr_reader :deferrable
35
+ attr_reader :initially_deferred
36
+
37
+ # initialize a new object to represent a unique_constraint in a postgres table
38
+ def initialize source, table, columns, unique_constraint_name, index_type: :btree, deferrable: false, initially_deferred: false
39
+ super source
40
+ raise ExpectedTableError, table unless table.is_a? Table
41
+ @table = table
42
+ @columns = {}
43
+
44
+ # assert that the provided columns is an array
45
+ unless columns.is_a?(Array) && columns.count > 0
46
+ raise ExpectedArrayOfColumnsError
47
+ end
48
+
49
+ columns.each do |column|
50
+ add_column column
51
+ end
52
+
53
+ raise ExpectedSymbolError, unique_constraint_name unless unique_constraint_name.is_a? Symbol
54
+ @unique_constraint_name = unique_constraint_name
55
+
56
+ raise UnexpectedIndexTypeError, index_type unless INDEX_TYPES.include?(index_type)
57
+ @index_type = index_type
58
+
59
+ raise ExpectedBooleanError, deferrable unless [true, false].include?(deferrable)
60
+ @deferrable = deferrable
61
+
62
+ raise ExpectedBooleanError, initially_deferred unless [true, false].include?(initially_deferred)
63
+ @initially_deferred = initially_deferred
64
+ end
65
+
66
+ # return an array of this unique_constraints columns
67
+ def columns
68
+ @columns.values
69
+ end
70
+
71
+ def column_names
72
+ @columns.keys
73
+ end
74
+
75
+ private
76
+
77
+ # used internally to set the columns from this objects initialize method
78
+ def add_column column
79
+ # assert that the provided dsl name is an array of Columns
80
+ unless column.is_a? Column
81
+ raise ExpectedArrayOfColumnsError
82
+ end
83
+
84
+ # assert that the provided column exists within this unique_constraints table
85
+ unless @table.has_column? column.column_name
86
+ raise ExpectedArrayOfColumnsError, "One or more columns do not exist in this unique_constraints table"
87
+ end
88
+
89
+ if @columns.key?(column.column_name)
90
+ raise(DuplicateColumnError, "Column #{column.column_name} already exists in unique_constraint, or is already included")
91
+ end
92
+
93
+ @columns[column.column_name] = column
94
+ end
95
+ end
96
+ end
97
+ end
98
+ end
99
+ end
100
+ end
101
+ end