dynamic_migrations 1.0.0

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