db_schema 0.2.5 → 0.3.rc1

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.
@@ -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