db_schema 0.2.5 → 0.3.rc1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,29 +1,48 @@
1
+ require 'dry/equalizer'
2
+
1
3
  module DbSchema
2
4
  class Configuration
3
- attr_reader :adapter, :host, :port, :database, :user, :password
4
-
5
- def initialize(adapter: 'postgres', host: 'localhost', port: 5432, database:, user: nil, password: '', log_changes: true, dry_run: false, post_check: true)
6
- @adapter = adapter
7
- @host = host
8
- @port = port
9
- @database = database
10
- @user = user
11
- @password = password
12
- @log_changes = log_changes
13
- @dry_run = dry_run
14
- @post_check = post_check
5
+ include Dry::Equalizer(:params)
6
+
7
+ DEFAULT_VALUES = {
8
+ adapter: 'postgres',
9
+ host: 'localhost',
10
+ port: 5432,
11
+ database: nil,
12
+ user: nil,
13
+ password: '',
14
+ log_changes: true,
15
+ dry_run: false,
16
+ post_check: true
17
+ }.freeze
18
+
19
+ def initialize(params = {})
20
+ @params = DEFAULT_VALUES.merge(params)
21
+ end
22
+
23
+ def merge(new_params)
24
+ Configuration.new(@params.merge(new_params))
25
+ end
26
+
27
+ [:adapter, :host, :port, :database, :user, :password].each do |param_name|
28
+ define_method(param_name) do
29
+ @params[param_name]
30
+ end
15
31
  end
16
32
 
17
33
  def log_changes?
18
- @log_changes
34
+ @params[:log_changes]
19
35
  end
20
36
 
21
37
  def dry_run?
22
- @dry_run
38
+ @params[:dry_run]
23
39
  end
24
40
 
25
41
  def post_check_enabled?
26
- @post_check
42
+ @params[:post_check]
27
43
  end
44
+
45
+ protected
46
+ attr_reader :params
28
47
  end
29
48
  end
@@ -1,255 +1,10 @@
1
1
  require 'dry/equalizer'
2
2
 
3
- module DbSchema
4
- module Definitions
5
- class Schema
6
- include Dry::Equalizer(:tables, :enums, :extensions)
7
- attr_reader :tables, :enums, :extensions
8
- attr_writer :tables
9
-
10
- def initialize(tables: [], enums: [], extensions: [])
11
- @tables = tables
12
- @enums = enums
13
- @extensions = extensions
14
- end
15
-
16
- def [](table_name)
17
- tables.find { |table| table.name == table_name } || NullTable.new
18
- end
19
- end
20
-
21
- class Table
22
- include Dry::Equalizer(:name, :fields, :indices, :checks, :foreign_keys)
23
- attr_reader :name, :fields, :indices, :checks, :foreign_keys
24
-
25
- def initialize(name, fields: [], indices: [], checks: [], foreign_keys: [])
26
- @name = name.to_sym
27
- @fields = fields
28
- @indices = indices
29
- @checks = checks
30
- @foreign_keys = foreign_keys
31
- end
32
-
33
- def has_expressions?
34
- fields.any?(&:default_is_expression?) ||
35
- indices.any?(&:has_expressions?) ||
36
- checks.any?
37
- end
38
-
39
- def [](field_name)
40
- fields.find { |field| field.name == field_name }
41
- end
42
-
43
- def with_name(new_name)
44
- Table.new(
45
- new_name,
46
- fields: fields,
47
- indices: indices,
48
- checks: checks,
49
- foreign_keys: foreign_keys
50
- )
51
- end
52
-
53
- def with_fields(new_fields)
54
- Table.new(
55
- name,
56
- fields: new_fields,
57
- indices: indices,
58
- checks: checks,
59
- foreign_keys: foreign_keys
60
- )
61
- end
62
-
63
- def with_indices(new_indices)
64
- Table.new(
65
- name,
66
- fields: fields,
67
- indices: new_indices,
68
- checks: checks,
69
- foreign_keys: foreign_keys
70
- )
71
- end
72
-
73
- def with_foreign_keys(new_foreign_keys)
74
- Table.new(
75
- name,
76
- fields: fields,
77
- indices: indices,
78
- checks: checks,
79
- foreign_keys: new_foreign_keys
80
- )
81
- end
82
- end
83
-
84
- class NullTable < Table
85
- def initialize; end
86
- end
87
-
88
- class Index
89
- include Dry::Equalizer(:name, :columns, :unique?, :type, :condition)
90
- attr_reader :name, :columns, :type, :condition
91
-
92
- def initialize(name:, columns:, unique: false, type: :btree, condition: nil)
93
- @name = name.to_sym
94
- @columns = columns
95
- @unique = unique
96
- @type = type
97
- @condition = condition
98
- end
99
-
100
- def unique?
101
- @unique
102
- end
103
-
104
- def btree?
105
- type == :btree
106
- end
107
-
108
- def columns_to_sequel
109
- if btree?
110
- columns.map(&:ordered_expression)
111
- else
112
- columns.map(&:to_sequel)
113
- end
114
- end
115
-
116
- def has_expressions?
117
- !condition.nil? || columns.any?(&:expression?)
118
- end
119
-
120
- def with_name(new_name)
121
- Index.new(
122
- name: new_name,
123
- columns: columns,
124
- unique: unique?,
125
- type: type,
126
- condition: condition
127
- )
128
- end
129
-
130
- class Column
131
- include Dry::Equalizer(:name, :order, :nulls)
132
- attr_reader :name, :order, :nulls
133
-
134
- def initialize(name, order: :asc, nulls: order == :asc ? :last : :first)
135
- @name = name
136
- @order = order
137
- @nulls = nulls
138
- end
139
-
140
- def asc?
141
- @order == :asc
142
- end
143
-
144
- def desc?
145
- @order == :desc
146
- end
147
-
148
- def ordered_expression
149
- if asc?
150
- Sequel.asc(to_sequel, nulls: nulls)
151
- else
152
- Sequel.desc(to_sequel, nulls: nulls)
153
- end
154
- end
155
- end
156
-
157
- class TableField < Column
158
- def expression?
159
- false
160
- end
161
-
162
- def index_name_segment
163
- name
164
- end
165
-
166
- def to_sequel
167
- name
168
- end
169
- end
170
-
171
- class Expression < Column
172
- def expression?
173
- true
174
- end
175
-
176
- def index_name_segment
177
- name.scan(/\b[A-Za-z0-9_]+\b/).join('_')
178
- end
179
-
180
- def to_sequel
181
- Sequel.lit("(#{name})")
182
- end
183
- end
184
- end
185
-
186
- class ForeignKey
187
- include Dry::Equalizer(:name, :fields, :table, :keys, :on_update, :on_delete, :deferrable?)
188
- attr_reader :name, :fields, :table, :keys, :on_update, :on_delete
189
-
190
- def initialize(name:, fields:, table:, keys: [], on_update: :no_action, on_delete: :no_action, deferrable: false)
191
- @name = name
192
- @fields = fields
193
- @table = table
194
- @keys = keys
195
- @on_update = on_update
196
- @on_delete = on_delete
197
- @deferrable = deferrable
198
- end
199
-
200
- def references_primary_key?
201
- keys.empty?
202
- end
203
-
204
- def deferrable?
205
- @deferrable
206
- end
207
-
208
- def options
209
- {
210
- deferrable: deferrable?,
211
- name: name,
212
- on_delete: on_delete,
213
- on_update: on_update
214
- }.tap do |options|
215
- options[:key] = keys unless references_primary_key?
216
- end
217
- end
218
- end
219
-
220
- class CheckConstraint
221
- include Dry::Equalizer(:name, :condition)
222
- attr_reader :name, :condition
223
-
224
- def initialize(name:, condition:)
225
- @name = name.to_sym
226
- @condition = condition
227
- end
228
- end
229
-
230
- class Enum
231
- include Dry::Equalizer(:name, :values)
232
- attr_reader :name, :values
233
-
234
- def initialize(name, values)
235
- @name = name
236
- @values = values
237
- end
238
-
239
- def with_name(new_name)
240
- Enum.new(new_name, values)
241
- end
242
- end
243
-
244
- class Extension
245
- include Dry::Equalizer(:name)
246
- attr_reader :name
247
-
248
- def initialize(name)
249
- @name = name
250
- end
251
- end
252
- end
253
- end
254
-
3
+ require_relative 'definitions/schema'
4
+ require_relative 'definitions/table'
255
5
  require_relative 'definitions/field'
6
+ require_relative 'definitions/index'
7
+ require_relative 'definitions/foreign_key'
8
+ require_relative 'definitions/check_constraint'
9
+ require_relative 'definitions/enum'
10
+ require_relative 'definitions/extension'
@@ -0,0 +1,17 @@
1
+ module DbSchema
2
+ module Definitions
3
+ class CheckConstraint
4
+ include Dry::Equalizer(:name, :condition)
5
+ attr_reader :name, :condition
6
+
7
+ def initialize(name:, condition:)
8
+ @name = name.to_sym
9
+ @condition = condition
10
+ end
11
+ end
12
+
13
+ class NullCheckConstraint < CheckConstraint
14
+ def initialize; end
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,21 @@
1
+ module DbSchema
2
+ module Definitions
3
+ class Enum
4
+ include Dry::Equalizer(:name, :values)
5
+ attr_reader :name, :values
6
+
7
+ def initialize(name, values)
8
+ @name = name
9
+ @values = values
10
+ end
11
+
12
+ def with_name(new_name)
13
+ Enum.new(new_name, values)
14
+ end
15
+ end
16
+
17
+ class NullEnum < Enum
18
+ def initialize; end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,12 @@
1
+ module DbSchema
2
+ module Definitions
3
+ class Extension
4
+ include Dry::Equalizer(:name)
5
+ attr_reader :name
6
+
7
+ def initialize(name)
8
+ @name = name
9
+ end
10
+ end
11
+ end
12
+ end
@@ -94,5 +94,11 @@ module DbSchema
94
94
  end
95
95
  end
96
96
  end
97
+
98
+ class NullField < Field::Base
99
+ def initialize
100
+ super(nil)
101
+ end
102
+ end
97
103
  end
98
104
  end
@@ -0,0 +1,41 @@
1
+ module DbSchema
2
+ module Definitions
3
+ class ForeignKey
4
+ include Dry::Equalizer(:name, :fields, :table, :keys, :on_update, :on_delete, :deferrable?)
5
+ attr_reader :name, :fields, :table, :keys, :on_update, :on_delete
6
+
7
+ def initialize(name:, fields:, table:, keys: [], on_update: :no_action, on_delete: :no_action, deferrable: false)
8
+ @name = name
9
+ @fields = fields
10
+ @table = table
11
+ @keys = keys
12
+ @on_update = on_update
13
+ @on_delete = on_delete
14
+ @deferrable = deferrable
15
+ end
16
+
17
+ def references_primary_key?
18
+ keys.empty?
19
+ end
20
+
21
+ def deferrable?
22
+ @deferrable
23
+ end
24
+
25
+ def options
26
+ {
27
+ deferrable: deferrable?,
28
+ name: name,
29
+ on_delete: on_delete,
30
+ on_update: on_update
31
+ }.tap do |options|
32
+ options[:key] = keys unless references_primary_key?
33
+ end
34
+ end
35
+ end
36
+
37
+ class NullForeignKey < ForeignKey
38
+ def initialize; end
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,56 @@
1
+ module DbSchema
2
+ module Definitions
3
+ class Index
4
+ include Dry::Equalizer(:name, :columns, :unique?, :type, :condition)
5
+ attr_reader :name, :columns, :type, :condition
6
+
7
+ def initialize(name:, columns:, unique: false, type: :btree, condition: nil)
8
+ @name = name.to_sym
9
+ @columns = columns
10
+ @unique = unique
11
+ @type = type
12
+ @condition = condition
13
+ end
14
+
15
+ def unique?
16
+ @unique
17
+ end
18
+
19
+ def btree?
20
+ type == :btree
21
+ end
22
+
23
+ def columns_to_sequel
24
+ if btree?
25
+ columns.map(&:ordered_expression)
26
+ else
27
+ columns.map(&:to_sequel)
28
+ end
29
+ end
30
+
31
+ def has_expressions?
32
+ !condition.nil? || columns.any?(&:expression?)
33
+ end
34
+
35
+ def with_name(new_name)
36
+ Index.new(
37
+ name: new_name,
38
+ columns: columns,
39
+ unique: unique?,
40
+ type: type,
41
+ condition: condition
42
+ )
43
+ end
44
+ end
45
+
46
+ class NullIndex < Index
47
+ def initialize
48
+ @columns = []
49
+ end
50
+ end
51
+ end
52
+ end
53
+
54
+ require_relative 'index/column'
55
+ require_relative 'index/table_field'
56
+ require_relative 'index/expression'