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,18 +1,29 @@
1
1
  module DbSchema
2
2
  module Reader
3
3
  class << self
4
- extend Forwardable
4
+ def read_schema(connection)
5
+ adapter(connection).read_schema(connection)
6
+ end
7
+
8
+ def read_table(table_name, connection)
9
+ adapter(connection).read_table(table_name, connection)
10
+ end
11
+
12
+ def read_enums(connection)
13
+ adapter(connection).read_enums(connection)
14
+ end
5
15
 
6
- def_delegators :adapter, :read_schema, :read_table, :read_enums, :read_extensions
16
+ def read_extensions(connection)
17
+ adapter(connection).read_extensions(connection)
18
+ end
7
19
 
8
- def adapter
9
- adapter_name = DbSchema.configuration.adapter
10
- registry.fetch(adapter_name) do |adapter_name|
20
+ private
21
+ def adapter(connection)
22
+ registry.fetch(connection.adapter_scheme) do |adapter_name|
11
23
  raise NotImplementedError, "DbSchema::Reader does not support #{adapter_name}."
12
24
  end
13
25
  end
14
26
 
15
- private
16
27
  def registry
17
28
  @registry ||= {}
18
29
  end
@@ -116,30 +127,30 @@ SELECT extname
116
127
  SQL
117
128
 
118
129
  class << self
119
- def read_schema
130
+ def read_schema(connection)
120
131
  Definitions::Schema.new(
121
- tables: read_tables,
122
- enums: read_enums,
123
- extensions: read_extensions
132
+ tables: read_tables(connection),
133
+ enums: read_enums(connection),
134
+ extensions: read_extensions(connection)
124
135
  )
125
136
  end
126
137
 
127
- def read_table(table_name)
128
- primary_key_name = DbSchema.connection.primary_key(table_name)
138
+ def read_table(table_name, connection)
139
+ primary_key_name = connection.primary_key(table_name)
129
140
 
130
- fields = DbSchema.connection[COLUMN_NAMES_QUERY, table_name.to_s].map do |column_data|
141
+ fields = connection[COLUMN_NAMES_QUERY, table_name.to_s].map do |column_data|
131
142
  build_field(column_data, primary_key: column_data[:name] == primary_key_name)
132
143
  end
133
144
 
134
- indices = indices_data_for(table_name).map do |index_data|
145
+ indices = indices_data_for(table_name, connection).map do |index_data|
135
146
  Definitions::Index.new(index_data)
136
147
  end.sort_by(&:name)
137
148
 
138
- foreign_keys = DbSchema.connection.foreign_key_list(table_name).map do |foreign_key_data|
139
- build_foreign_key(foreign_key_data)
149
+ foreign_keys = connection.foreign_key_list(table_name).map do |foreign_key_data|
150
+ build_foreign_key(foreign_key_data, connection)
140
151
  end
141
152
 
142
- checks = DbSchema.connection[CONSTRAINTS_QUERY, table_name.to_s].map do |check_data|
153
+ checks = connection[CONSTRAINTS_QUERY, table_name.to_s].map do |check_data|
143
154
  Definitions::CheckConstraint.new(
144
155
  name: check_data[:name].to_sym,
145
156
  condition: check_data[:condition]
@@ -155,13 +166,13 @@ SELECT extname
155
166
  )
156
167
  end
157
168
 
158
- def indices_data_for(table_name)
159
- column_names = DbSchema.connection[COLUMN_NAMES_QUERY, table_name.to_s].reduce({}) do |names, column|
169
+ def indices_data_for(table_name, connection)
170
+ column_names = connection[COLUMN_NAMES_QUERY, table_name.to_s].reduce({}) do |names, column|
160
171
  names.merge(column[:pos] => column[:name].to_sym)
161
172
  end
162
173
 
163
- indices_data = DbSchema.connection[INDICES_QUERY, table_name.to_s].to_a
164
- expressions_data = index_expressions_data(indices_data)
174
+ indices_data = connection[INDICES_QUERY, table_name.to_s].to_a
175
+ expressions_data = index_expressions_data(indices_data, connection)
165
176
 
166
177
  indices_data.map do |index|
167
178
  positions = index[:column_positions].split(' ').map(&:to_i)
@@ -197,26 +208,26 @@ SELECT extname
197
208
  end
198
209
  end
199
210
 
200
- def read_tables
201
- DbSchema.connection.tables.map do |table_name|
202
- read_table(table_name)
211
+ def read_tables(connection)
212
+ connection.tables.map do |table_name|
213
+ read_table(table_name, connection)
203
214
  end
204
215
  end
205
216
 
206
- def read_enums
207
- DbSchema.connection[ENUMS_QUERY].map do |enum_data|
217
+ def read_enums(connection)
218
+ connection[ENUMS_QUERY].map do |enum_data|
208
219
  Definitions::Enum.new(enum_data[:name].to_sym, enum_data[:values].map(&:to_sym))
209
220
  end
210
221
  end
211
222
 
212
- def read_extensions
213
- DbSchema.connection[EXTENSIONS_QUERY].map do |extension_data|
223
+ def read_extensions(connection)
224
+ connection[EXTENSIONS_QUERY].map do |extension_data|
214
225
  Definitions::Extension.new(extension_data[:extname].to_sym)
215
226
  end
216
227
  end
217
228
 
218
229
  private
219
- def index_expressions_data(indices_data)
230
+ def index_expressions_data(indices_data, connection)
220
231
  all_positions, max_position = {}, 0
221
232
 
222
233
  indices_data.each do |index_data|
@@ -230,7 +241,7 @@ SELECT extname
230
241
  end
231
242
 
232
243
  if all_positions.any?
233
- DbSchema.connection[
244
+ connection[
234
245
  EXPRESSION_INDICES_QUERY,
235
246
  Sequel.pg_array(all_positions.keys),
236
247
  Sequel.pg_array((1..max_position.succ).to_a)
@@ -318,8 +329,8 @@ SELECT extname
318
329
  )
319
330
  end
320
331
 
321
- def build_foreign_key(data)
322
- keys = if data[:key] == [primary_key_for(data[:table])]
332
+ def build_foreign_key(data, connection)
333
+ keys = if data[:key] == [primary_key_for(data[:table], connection)]
323
334
  [] # this foreign key references a primary key
324
335
  else
325
336
  data[:key]
@@ -336,15 +347,14 @@ SELECT extname
336
347
  )
337
348
  end
338
349
 
339
- def primary_key_for(table_name)
340
- if pkey = DbSchema.connection.primary_key(table_name)
350
+ def primary_key_for(table_name, connection)
351
+ if pkey = connection.primary_key(table_name)
341
352
  pkey.to_sym
342
353
  end
343
354
  end
344
355
  end
345
356
  end
346
357
 
347
- registry['postgres'] = Postgres
348
- registry['postgresql'] = Postgres
358
+ registry[:postgres] = Postgres
349
359
  end
350
360
  end
@@ -1,213 +1,189 @@
1
1
  module DbSchema
2
2
  class Runner
3
- attr_reader :changes
3
+ attr_reader :changes, :connection
4
4
 
5
- def initialize(changes)
6
- @changes = preprocess_changes(changes)
5
+ def initialize(changes, connection)
6
+ @changes = changes
7
+ @connection = connection
7
8
  end
8
9
 
9
10
  def run!
10
- DbSchema.connection.transaction do
11
- changes.each do |change|
12
- case change
13
- when Changes::CreateTable
14
- self.class.create_table(change)
15
- when Changes::DropTable
16
- self.class.drop_table(change)
17
- when Changes::AlterTable
18
- self.class.alter_table(change)
19
- when Changes::CreateForeignKey
20
- self.class.create_foreign_key(change)
21
- when Changes::DropForeignKey
22
- self.class.drop_foreign_key(change)
23
- when Changes::CreateEnum
24
- self.class.create_enum(change)
25
- when Changes::DropEnum
26
- self.class.drop_enum(change)
27
- when Changes::AlterEnumValues
28
- self.class.alter_enum_values(change)
29
- when Changes::CreateExtension
30
- self.class.create_extension(change)
31
- when Changes::DropExtension
32
- self.class.drop_extension(change)
33
- end
11
+ changes.each do |change|
12
+ case change
13
+ when Operations::CreateTable
14
+ create_table(change)
15
+ when Operations::DropTable
16
+ drop_table(change)
17
+ when Operations::RenameTable
18
+ rename_table(change)
19
+ when Operations::AlterTable
20
+ alter_table(change)
21
+ when Operations::CreateForeignKey
22
+ create_foreign_key(change)
23
+ when Operations::DropForeignKey
24
+ drop_foreign_key(change)
25
+ when Operations::CreateEnum
26
+ create_enum(change)
27
+ when Operations::DropEnum
28
+ drop_enum(change)
29
+ when Operations::AlterEnumValues
30
+ alter_enum_values(change)
31
+ when Operations::CreateExtension
32
+ create_extension(change)
33
+ when Operations::DropExtension
34
+ drop_extension(change)
35
+ when Operations::ExecuteQuery
36
+ execute_query(change)
34
37
  end
35
38
  end
36
39
  end
37
40
 
38
41
  private
39
- def preprocess_changes(changes)
40
- Utils.sort_by_class(
41
- changes,
42
- [
43
- Changes::CreateExtension,
44
- Changes::DropForeignKey,
45
- Changes::AlterEnumValues,
46
- Changes::CreateEnum,
47
- Changes::CreateTable,
48
- Changes::AlterTable,
49
- Changes::DropTable,
50
- Changes::DropEnum,
51
- Changes::CreateForeignKey,
52
- Changes::DropExtension
53
- ]
54
- )
55
- end
56
-
57
- class << self
58
- def create_table(change)
59
- DbSchema.connection.create_table(change.table.name) do
60
- change.table.fields.each do |field|
61
- if field.primary_key?
62
- primary_key(field.name)
63
- else
64
- options = Runner.map_options(field.class.type, field.options)
65
- column(field.name, field.type.capitalize, options)
66
- end
42
+ def create_table(change)
43
+ connection.create_table(change.table.name) do
44
+ change.table.fields.each do |field|
45
+ if field.primary_key?
46
+ primary_key(field.name)
47
+ else
48
+ options = Runner.map_options(field.class.type, field.options)
49
+ column(field.name, field.type.capitalize, options)
67
50
  end
51
+ end
68
52
 
69
- change.table.indices.each do |index|
70
- index(
71
- index.columns_to_sequel,
72
- name: index.name,
73
- unique: index.unique?,
74
- type: index.type,
75
- where: index.condition
76
- )
77
- end
53
+ change.table.indices.each do |index|
54
+ index(
55
+ index.columns_to_sequel,
56
+ name: index.name,
57
+ unique: index.unique?,
58
+ type: index.type,
59
+ where: index.condition
60
+ )
61
+ end
78
62
 
79
- change.table.checks.each do |check|
80
- constraint(check.name, check.condition)
81
- end
63
+ change.table.checks.each do |check|
64
+ constraint(check.name, check.condition)
82
65
  end
83
66
  end
67
+ end
84
68
 
85
- def drop_table(change)
86
- DbSchema.connection.drop_table(change.name)
87
- end
69
+ def drop_table(change)
70
+ connection.drop_table(change.name)
71
+ end
88
72
 
89
- def alter_table(change)
90
- DbSchema.connection.alter_table(change.table_name) do
91
- Utils.sort_by_class(
92
- change.changes,
93
- [
94
- DbSchema::Changes::DropPrimaryKey,
95
- DbSchema::Changes::DropCheckConstraint,
96
- DbSchema::Changes::DropIndex,
97
- DbSchema::Changes::DropColumn,
98
- DbSchema::Changes::RenameColumn,
99
- DbSchema::Changes::AlterColumnType,
100
- DbSchema::Changes::AllowNull,
101
- DbSchema::Changes::DisallowNull,
102
- DbSchema::Changes::AlterColumnDefault,
103
- DbSchema::Changes::CreateColumn,
104
- DbSchema::Changes::CreateIndex,
105
- DbSchema::Changes::CreateCheckConstraint,
106
- DbSchema::Changes::CreatePrimaryKey
107
- ]
108
- ).each do |element|
109
- case element
110
- when Changes::CreateColumn
111
- if element.primary_key?
112
- add_primary_key(element.name)
113
- else
114
- options = Runner.map_options(element.type, element.options)
115
- add_column(element.name, element.type.capitalize, options)
116
- end
117
- when Changes::DropColumn
118
- drop_column(element.name)
119
- when Changes::RenameColumn
120
- rename_column(element.old_name, element.new_name)
121
- when Changes::AlterColumnType
122
- attributes = Runner.map_options(element.new_type, element.new_attributes)
123
- set_column_type(element.name, element.new_type.capitalize, attributes)
124
- when Changes::CreatePrimaryKey
125
- raise NotImplementedError, 'Converting an existing column to primary key is currently unsupported'
126
- when Changes::DropPrimaryKey
127
- raise NotImplementedError, 'Removing a primary key while leaving the column is currently unsupported'
128
- when Changes::AllowNull
129
- set_column_allow_null(element.name)
130
- when Changes::DisallowNull
131
- set_column_not_null(element.name)
132
- when Changes::AlterColumnDefault
133
- set_column_default(element.name, Runner.default_to_sequel(element.new_default))
134
- when Changes::CreateIndex
135
- add_index(
136
- element.index.columns_to_sequel,
137
- name: element.index.name,
138
- unique: element.index.unique?,
139
- type: element.index.type,
140
- where: element.index.condition
141
- )
142
- when Changes::DropIndex
143
- drop_index([], name: element.name)
144
- when Changes::CreateCheckConstraint
145
- add_constraint(element.check.name, element.check.condition)
146
- when Changes::DropCheckConstraint
147
- drop_constraint(element.name)
73
+ def rename_table(change)
74
+ connection.rename_table(change.old_name, change.new_name)
75
+ end
76
+
77
+ def alter_table(change)
78
+ connection.alter_table(change.table_name) do
79
+ change.changes.each do |element|
80
+ case element
81
+ when Operations::CreateColumn
82
+ if element.primary_key?
83
+ add_primary_key(element.name)
84
+ else
85
+ options = Runner.map_options(element.type, element.options)
86
+ add_column(element.name, element.type.capitalize, options)
148
87
  end
88
+ when Operations::DropColumn
89
+ drop_column(element.name)
90
+ when Operations::RenameColumn
91
+ rename_column(element.old_name, element.new_name)
92
+ when Operations::AlterColumnType
93
+ attributes = Runner.map_options(element.new_type, element.new_attributes)
94
+ set_column_type(element.name, element.new_type.capitalize, using: element.using, **attributes)
95
+ when Operations::CreatePrimaryKey
96
+ raise NotImplementedError, 'Converting an existing column to primary key is currently unsupported'
97
+ when Operations::DropPrimaryKey
98
+ raise NotImplementedError, 'Removing a primary key while leaving the column is currently unsupported'
99
+ when Operations::AllowNull
100
+ set_column_allow_null(element.name)
101
+ when Operations::DisallowNull
102
+ set_column_not_null(element.name)
103
+ when Operations::AlterColumnDefault
104
+ set_column_default(element.name, Runner.default_to_sequel(element.new_default))
105
+ when Operations::CreateIndex
106
+ add_index(
107
+ element.index.columns_to_sequel,
108
+ name: element.index.name,
109
+ unique: element.index.unique?,
110
+ type: element.index.type,
111
+ where: element.index.condition
112
+ )
113
+ when Operations::DropIndex
114
+ drop_index([], name: element.name)
115
+ when Operations::CreateCheckConstraint
116
+ add_constraint(element.check.name, element.check.condition)
117
+ when Operations::DropCheckConstraint
118
+ drop_constraint(element.name)
149
119
  end
150
120
  end
151
121
  end
122
+ end
152
123
 
153
- def create_foreign_key(change)
154
- DbSchema.connection.alter_table(change.table_name) do
155
- add_foreign_key(change.foreign_key.fields, change.foreign_key.table, change.foreign_key.options)
156
- end
124
+ def create_foreign_key(change)
125
+ connection.alter_table(change.table_name) do
126
+ add_foreign_key(change.foreign_key.fields, change.foreign_key.table, change.foreign_key.options)
157
127
  end
128
+ end
158
129
 
159
- def drop_foreign_key(change)
160
- DbSchema.connection.alter_table(change.table_name) do
161
- drop_foreign_key([], name: change.fkey_name)
162
- end
130
+ def drop_foreign_key(change)
131
+ connection.alter_table(change.table_name) do
132
+ drop_foreign_key([], name: change.fkey_name)
163
133
  end
134
+ end
164
135
 
165
- def create_enum(change)
166
- DbSchema.connection.create_enum(change.enum.name, change.enum.values)
167
- end
136
+ def create_enum(change)
137
+ connection.create_enum(change.enum.name, change.enum.values)
138
+ end
168
139
 
169
- def drop_enum(change)
170
- DbSchema.connection.drop_enum(change.name)
171
- end
140
+ def drop_enum(change)
141
+ connection.drop_enum(change.name)
142
+ end
172
143
 
173
- def alter_enum_values(change)
174
- change.enum_fields.each do |field_data|
175
- DbSchema.connection.alter_table(field_data[:table_name]) do
176
- set_column_type(field_data[:field_name], :VARCHAR)
177
- set_column_default(field_data[:field_name], nil)
178
- end
144
+ def alter_enum_values(change)
145
+ change.enum_fields.each do |field_data|
146
+ connection.alter_table(field_data[:table_name]) do
147
+ set_column_type(field_data[:field_name], :VARCHAR)
148
+ set_column_default(field_data[:field_name], nil)
179
149
  end
150
+ end
180
151
 
181
- DbSchema.connection.drop_enum(change.enum_name)
182
- DbSchema.connection.create_enum(change.enum_name, change.new_values)
152
+ connection.drop_enum(change.enum_name)
153
+ connection.create_enum(change.enum_name, change.new_values)
183
154
 
184
- change.enum_fields.each do |field_data|
185
- DbSchema.connection.alter_table(field_data[:table_name]) do
186
- field_type = if field_data[:array]
187
- "#{change.enum_name}[]"
188
- else
189
- change.enum_name
190
- end
155
+ change.enum_fields.each do |field_data|
156
+ connection.alter_table(field_data[:table_name]) do
157
+ field_type = if field_data[:array]
158
+ "#{change.enum_name}[]"
159
+ else
160
+ change.enum_name
161
+ end
191
162
 
192
- set_column_type(
193
- field_data[:field_name],
194
- field_type,
195
- using: "#{field_data[:field_name]}::#{field_type}"
196
- )
163
+ set_column_type(
164
+ field_data[:field_name],
165
+ field_type,
166
+ using: "#{field_data[:field_name]}::#{field_type}"
167
+ )
197
168
 
198
- set_column_default(field_data[:field_name], field_data[:new_default]) unless field_data[:new_default].nil?
199
- end
169
+ set_column_default(field_data[:field_name], field_data[:new_default]) unless field_data[:new_default].nil?
200
170
  end
201
171
  end
172
+ end
202
173
 
203
- def create_extension(change)
204
- DbSchema.connection.run(%Q(CREATE EXTENSION "#{change.extension.name}"))
205
- end
174
+ def create_extension(change)
175
+ connection.run(%Q(CREATE EXTENSION "#{change.extension.name}"))
176
+ end
206
177
 
207
- def drop_extension(change)
208
- DbSchema.connection.run(%Q(DROP EXTENSION "#{change.name}"))
209
- end
178
+ def drop_extension(change)
179
+ connection.run(%Q(DROP EXTENSION "#{change.name}"))
180
+ end
210
181
 
182
+ def execute_query(change)
183
+ connection.run(change.query)
184
+ end
185
+
186
+ class << self
211
187
  def map_options(type, options)
212
188
  mapping = case type
213
189
  when :char, :varchar, :bit, :varbit