db_schema 0.3.1 → 0.4
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.
- checksums.yaml +5 -5
- data/README.md +7 -3
- data/db_schema.gemspec +2 -1
- data/lib/db_schema.rb +4 -3
- data/lib/db_schema/normalizer.rb +2 -2
- data/lib/db_schema/reader.rb +8 -350
- data/lib/db_schema/version.rb +1 -1
- metadata +22 -43
- data/lib/db_schema/definitions.rb +0 -10
- data/lib/db_schema/definitions/check_constraint.rb +0 -21
- data/lib/db_schema/definitions/enum.rb +0 -23
- data/lib/db_schema/definitions/extension.rb +0 -12
- data/lib/db_schema/definitions/field.rb +0 -47
- data/lib/db_schema/definitions/field/array.rb +0 -30
- data/lib/db_schema/definitions/field/base.rb +0 -108
- data/lib/db_schema/definitions/field/binary.rb +0 -9
- data/lib/db_schema/definitions/field/bit_string.rb +0 -15
- data/lib/db_schema/definitions/field/boolean.rb +0 -9
- data/lib/db_schema/definitions/field/character.rb +0 -19
- data/lib/db_schema/definitions/field/custom.rb +0 -32
- data/lib/db_schema/definitions/field/datetime.rb +0 -30
- data/lib/db_schema/definitions/field/extensions/chkpass.rb +0 -9
- data/lib/db_schema/definitions/field/extensions/citext.rb +0 -9
- data/lib/db_schema/definitions/field/extensions/cube.rb +0 -9
- data/lib/db_schema/definitions/field/extensions/hstore.rb +0 -9
- data/lib/db_schema/definitions/field/extensions/isn.rb +0 -37
- data/lib/db_schema/definitions/field/extensions/ltree.rb +0 -9
- data/lib/db_schema/definitions/field/extensions/seg.rb +0 -9
- data/lib/db_schema/definitions/field/geometric.rb +0 -33
- data/lib/db_schema/definitions/field/json.rb +0 -13
- data/lib/db_schema/definitions/field/monetary.rb +0 -9
- data/lib/db_schema/definitions/field/network.rb +0 -17
- data/lib/db_schema/definitions/field/numeric.rb +0 -30
- data/lib/db_schema/definitions/field/range.rb +0 -29
- data/lib/db_schema/definitions/field/text_search.rb +0 -13
- data/lib/db_schema/definitions/field/uuid.rb +0 -9
- data/lib/db_schema/definitions/foreign_key.rb +0 -44
- data/lib/db_schema/definitions/index.rb +0 -66
- data/lib/db_schema/definitions/index/column.rb +0 -32
- data/lib/db_schema/definitions/index/expression.rb +0 -19
- data/lib/db_schema/definitions/index/table_field.rb +0 -19
- data/lib/db_schema/definitions/schema.rb +0 -36
- data/lib/db_schema/definitions/table.rb +0 -130
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 63847549e7e2a6350f2804c5a2a251388f6b65ff206d51fc34403b4a56d883aa
|
4
|
+
data.tar.gz: a2d2ff387fa992afac8764cd6a0c5dff3b5f34bcd1f632d4fcb3ec216f13360c
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8d2793a8eed21c593be07e7c5a067a86e0d2566938f99e410808d3657898b37abaab8e1db1adff8ff8b8c311fb123204b05713f650cf9ff2de882689f2ebabf0
|
7
|
+
data.tar.gz: c2b2e6dca0d6c7df815bf8e8e060bb3b35727bd02ccd8c18c943c6f7373777d1e77151f0ba87f0f64014affc371848e8e05dfa6fd0a6c9387fc340caa42bfccc
|
data/README.md
CHANGED
@@ -50,10 +50,11 @@ But you would lose it even with manual migrations.
|
|
50
50
|
|
51
51
|
## Installation
|
52
52
|
|
53
|
-
Add
|
53
|
+
Add these lines to your application's Gemfile:
|
54
54
|
|
55
55
|
``` ruby
|
56
|
-
gem 'db_schema', '~> 0.
|
56
|
+
gem 'db_schema', '~> 0.4.0'
|
57
|
+
gem 'db_schema-reader-postgres', '~> 0.1.1'
|
57
58
|
```
|
58
59
|
|
59
60
|
And then execute:
|
@@ -65,9 +66,12 @@ $ bundle
|
|
65
66
|
Or install it yourself as:
|
66
67
|
|
67
68
|
``` sh
|
68
|
-
$ gem install db_schema
|
69
|
+
$ gem install db_schema db_schema-reader-postgres
|
69
70
|
```
|
70
71
|
|
72
|
+
The `db_schema-reader-postgres` [gem](https://github.com/db-schema/reader-postgres) is a PostgreSQL adapter
|
73
|
+
for `DbSchema::Reader` (a module which is responsible for reading the current database schema).
|
74
|
+
|
71
75
|
## Usage
|
72
76
|
|
73
77
|
First you need to configure DbSchema so it knows how to connect to your database. This should happen
|
data/db_schema.gemspec
CHANGED
@@ -20,6 +20,7 @@ Gem::Specification.new do |spec|
|
|
20
20
|
|
21
21
|
spec.add_runtime_dependency 'sequel'
|
22
22
|
spec.add_runtime_dependency 'dry-equalizer', '~> 0.2'
|
23
|
+
spec.add_runtime_dependency 'db_schema-definitions', '~> 0.1.1'
|
23
24
|
|
24
25
|
spec.add_development_dependency 'bundler', '~> 1.11'
|
25
26
|
spec.add_development_dependency 'rake', '~> 10.0'
|
@@ -31,5 +32,5 @@ Gem::Specification.new do |spec|
|
|
31
32
|
spec.add_development_dependency 'terminal-notifier'
|
32
33
|
spec.add_development_dependency 'terminal-notifier-guard'
|
33
34
|
|
34
|
-
spec.add_development_dependency '
|
35
|
+
spec.add_development_dependency 'db_schema-reader-postgres', '~> 0.1.1'
|
35
36
|
end
|
data/lib/db_schema.rb
CHANGED
@@ -114,7 +114,8 @@ module DbSchema
|
|
114
114
|
end
|
115
115
|
|
116
116
|
def run_migrations(migrations, connection)
|
117
|
-
|
117
|
+
reader = Reader.reader_for(connection)
|
118
|
+
@current_schema = reader.read_schema
|
118
119
|
|
119
120
|
migrations.reduce(@current_schema) do |schema, migration|
|
120
121
|
migrator = Migrator.new(migration)
|
@@ -122,7 +123,7 @@ module DbSchema
|
|
122
123
|
if migrator.applicable?(schema)
|
123
124
|
log_migration(migration) if configuration.log_changes?
|
124
125
|
migrator.run!(connection)
|
125
|
-
|
126
|
+
reader.read_schema
|
126
127
|
else
|
127
128
|
schema
|
128
129
|
end
|
@@ -145,7 +146,7 @@ module DbSchema
|
|
145
146
|
end
|
146
147
|
|
147
148
|
def perform_post_check(desired_schema, connection)
|
148
|
-
unapplied_changes = Changes.between(desired_schema, Reader.
|
149
|
+
unapplied_changes = Changes.between(desired_schema, Reader.reader_for(connection).read_schema)
|
149
150
|
return if unapplied_changes.empty?
|
150
151
|
|
151
152
|
readable_changes = if unapplied_changes.respond_to?(:ai)
|
data/lib/db_schema/normalizer.rb
CHANGED
@@ -28,7 +28,7 @@ module DbSchema
|
|
28
28
|
|
29
29
|
private
|
30
30
|
def create_extensions!
|
31
|
-
operations = (schema.extensions - Reader.
|
31
|
+
operations = (schema.extensions - Reader.reader_for(connection).read_extensions).map do |extension|
|
32
32
|
Operations::CreateExtension.new(extension)
|
33
33
|
end
|
34
34
|
|
@@ -85,7 +85,7 @@ module DbSchema
|
|
85
85
|
end
|
86
86
|
|
87
87
|
def read_temporary_table
|
88
|
-
temporary_table = Reader.read_table(temporary_table_name
|
88
|
+
temporary_table = Reader.reader_for(connection).read_table(temporary_table_name)
|
89
89
|
|
90
90
|
temporary_table.with_name(table.name)
|
91
91
|
.with_fields(rename_types_back(temporary_table.fields))
|
data/lib/db_schema/reader.rb
CHANGED
@@ -1,360 +1,18 @@
|
|
1
1
|
module DbSchema
|
2
2
|
module Reader
|
3
3
|
class << self
|
4
|
-
def
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
adapter(connection).read_table(table_name, connection)
|
10
|
-
end
|
11
|
-
|
12
|
-
def read_enums(connection)
|
13
|
-
adapter(connection).read_enums(connection)
|
14
|
-
end
|
15
|
-
|
16
|
-
def read_extensions(connection)
|
17
|
-
adapter(connection).read_extensions(connection)
|
18
|
-
end
|
19
|
-
|
20
|
-
private
|
21
|
-
def adapter(connection)
|
22
|
-
registry.fetch(connection.adapter_scheme) do |adapter_name|
|
23
|
-
raise NotImplementedError, "DbSchema::Reader does not support #{adapter_name}."
|
24
|
-
end
|
25
|
-
end
|
26
|
-
|
27
|
-
def registry
|
28
|
-
@registry ||= {}
|
29
|
-
end
|
30
|
-
end
|
31
|
-
|
32
|
-
module Postgres
|
33
|
-
DEFAULT_VALUE = /\A(
|
34
|
-
('(?<date>\d{4}-\d{2}-\d{2})'::date)
|
35
|
-
|
|
36
|
-
('(?<time>\d{4}-\d{2}-\d{2}\s\d{2}:\d{2}:\d{2}([+-]\d{2})?)'::timestamp)
|
37
|
-
|
|
38
|
-
('(?<string>.*)')
|
39
|
-
|
|
40
|
-
(?<float>\d+\.\d+)
|
41
|
-
|
|
42
|
-
(?<integer>\d+)
|
43
|
-
|
|
44
|
-
(?<boolean>true|false)
|
45
|
-
)/x
|
46
|
-
|
47
|
-
COLUMN_NAMES_QUERY = <<-SQL.freeze
|
48
|
-
SELECT c.column_name AS name,
|
49
|
-
c.ordinal_position AS pos,
|
50
|
-
c.column_default AS default,
|
51
|
-
c.is_nullable AS null,
|
52
|
-
c.data_type AS type,
|
53
|
-
c.udt_name AS custom_type_name,
|
54
|
-
c.character_maximum_length AS char_length,
|
55
|
-
c.numeric_precision AS num_precision,
|
56
|
-
c.numeric_scale AS num_scale,
|
57
|
-
c.datetime_precision AS dt_precision,
|
58
|
-
c.interval_type,
|
59
|
-
e.data_type AS element_type,
|
60
|
-
e.udt_name AS element_custom_type_name
|
61
|
-
FROM information_schema.columns AS c
|
62
|
-
LEFT JOIN information_schema.element_types AS e
|
63
|
-
ON e.object_catalog = c.table_catalog
|
64
|
-
AND e.object_schema = c.table_schema
|
65
|
-
AND e.object_name = c.table_name
|
66
|
-
AND e.object_type = 'TABLE'
|
67
|
-
AND e.collection_type_identifier = c.dtd_identifier
|
68
|
-
WHERE c.table_schema = 'public'
|
69
|
-
AND c.table_name = ?
|
70
|
-
SQL
|
71
|
-
|
72
|
-
CONSTRAINTS_QUERY = <<-SQL.freeze
|
73
|
-
SELECT conname AS name,
|
74
|
-
pg_get_expr(conbin, conrelid, true) AS condition
|
75
|
-
FROM pg_constraint, pg_class
|
76
|
-
WHERE conrelid = pg_class.oid
|
77
|
-
AND relname = ?
|
78
|
-
AND contype = 'c'
|
79
|
-
SQL
|
80
|
-
|
81
|
-
INDEXES_QUERY = <<-SQL.freeze
|
82
|
-
SELECT relname AS name,
|
83
|
-
indkey AS column_positions,
|
84
|
-
indisunique AS unique,
|
85
|
-
indoption AS index_options,
|
86
|
-
pg_get_expr(indpred, indrelid, true) AS condition,
|
87
|
-
amname AS index_type,
|
88
|
-
indexrelid AS index_oid
|
89
|
-
FROM pg_class, pg_index
|
90
|
-
LEFT JOIN pg_opclass
|
91
|
-
ON pg_opclass.oid = ANY(pg_index.indclass::int[])
|
92
|
-
LEFT JOIN pg_am
|
93
|
-
ON pg_am.oid = pg_opclass.opcmethod
|
94
|
-
WHERE pg_class.oid = pg_index.indexrelid
|
95
|
-
AND pg_class.oid IN (
|
96
|
-
SELECT indexrelid
|
97
|
-
FROM pg_index, pg_class
|
98
|
-
WHERE pg_class.relname = ?
|
99
|
-
AND pg_class.oid = pg_index.indrelid
|
100
|
-
AND indisprimary != 't'
|
101
|
-
)
|
102
|
-
GROUP BY name, column_positions, indisunique, index_options, condition, index_type, index_oid
|
103
|
-
SQL
|
104
|
-
|
105
|
-
EXPRESSION_INDEXES_QUERY = <<-SQL.freeze
|
106
|
-
WITH index_ids AS (SELECT unnest(?) AS index_id),
|
107
|
-
elements AS (SELECT unnest(?) AS element)
|
108
|
-
SELECT index_id,
|
109
|
-
array_agg(pg_get_indexdef(index_id, element, 't')) AS definitions
|
110
|
-
FROM index_ids, elements
|
111
|
-
GROUP BY index_id;
|
112
|
-
SQL
|
113
|
-
|
114
|
-
ENUMS_QUERY = <<-SQL.freeze
|
115
|
-
SELECT t.typname AS name,
|
116
|
-
array_agg(e.enumlabel ORDER BY e.enumsortorder) AS values
|
117
|
-
FROM pg_enum AS e
|
118
|
-
JOIN pg_type AS t
|
119
|
-
ON t.oid = e.enumtypid
|
120
|
-
GROUP BY name
|
121
|
-
SQL
|
122
|
-
|
123
|
-
EXTENSIONS_QUERY = <<-SQL.freeze
|
124
|
-
SELECT extname
|
125
|
-
FROM pg_extension
|
126
|
-
WHERE extname != 'plpgsql'
|
127
|
-
SQL
|
128
|
-
|
129
|
-
class << self
|
130
|
-
def read_schema(connection)
|
131
|
-
Definitions::Schema.new(
|
132
|
-
tables: read_tables(connection),
|
133
|
-
enums: read_enums(connection),
|
134
|
-
extensions: read_extensions(connection)
|
135
|
-
)
|
136
|
-
end
|
137
|
-
|
138
|
-
def read_table(table_name, connection)
|
139
|
-
primary_key_name = connection.primary_key(table_name)
|
140
|
-
|
141
|
-
fields = connection[COLUMN_NAMES_QUERY, table_name.to_s].map do |column_data|
|
142
|
-
build_field(column_data, primary_key: column_data[:name] == primary_key_name)
|
143
|
-
end
|
144
|
-
|
145
|
-
indexes = indexes_data_for(table_name, connection).map do |index_data|
|
146
|
-
Definitions::Index.new(index_data)
|
147
|
-
end.sort_by(&:name)
|
148
|
-
|
149
|
-
foreign_keys = connection.foreign_key_list(table_name).map do |foreign_key_data|
|
150
|
-
build_foreign_key(foreign_key_data, connection)
|
151
|
-
end
|
152
|
-
|
153
|
-
checks = connection[CONSTRAINTS_QUERY, table_name.to_s].map do |check_data|
|
154
|
-
Definitions::CheckConstraint.new(
|
155
|
-
name: check_data[:name].to_sym,
|
156
|
-
condition: check_data[:condition]
|
157
|
-
)
|
158
|
-
end
|
159
|
-
|
160
|
-
Definitions::Table.new(
|
161
|
-
table_name,
|
162
|
-
fields: fields,
|
163
|
-
indexes: indexes,
|
164
|
-
checks: checks,
|
165
|
-
foreign_keys: foreign_keys
|
166
|
-
)
|
167
|
-
end
|
168
|
-
|
169
|
-
def indexes_data_for(table_name, connection)
|
170
|
-
column_names = connection[COLUMN_NAMES_QUERY, table_name.to_s].reduce({}) do |names, column|
|
171
|
-
names.merge(column[:pos] => column[:name].to_sym)
|
172
|
-
end
|
173
|
-
|
174
|
-
indexes_data = connection[INDEXES_QUERY, table_name.to_s].to_a
|
175
|
-
expressions_data = index_expressions_data(indexes_data, connection)
|
176
|
-
|
177
|
-
indexes_data.map do |index|
|
178
|
-
positions = index[:column_positions].split(' ').map(&:to_i)
|
179
|
-
options = index[:index_options].split(' ').map(&:to_i)
|
180
|
-
|
181
|
-
columns = positions.zip(options).map do |column_position, column_order_options|
|
182
|
-
options = case column_order_options
|
183
|
-
when 0
|
184
|
-
{}
|
185
|
-
when 3
|
186
|
-
{ order: :desc }
|
187
|
-
when 2
|
188
|
-
{ nulls: :first }
|
189
|
-
when 1
|
190
|
-
{ order: :desc, nulls: :last }
|
191
|
-
end
|
192
|
-
|
193
|
-
if column_position.zero?
|
194
|
-
expression = expressions_data.fetch(index[:index_oid]).shift
|
195
|
-
DbSchema::Definitions::Index::Expression.new(expression, **options)
|
196
|
-
else
|
197
|
-
DbSchema::Definitions::Index::TableField.new(column_names.fetch(column_position), **options)
|
198
|
-
end
|
199
|
-
end
|
200
|
-
|
201
|
-
{
|
202
|
-
name: index[:name].to_sym,
|
203
|
-
columns: columns,
|
204
|
-
unique: index[:unique],
|
205
|
-
type: index[:index_type].to_sym,
|
206
|
-
condition: index[:condition]
|
207
|
-
}
|
208
|
-
end
|
209
|
-
end
|
210
|
-
|
211
|
-
def read_tables(connection)
|
212
|
-
connection.tables.map do |table_name|
|
213
|
-
read_table(table_name, connection)
|
214
|
-
end
|
215
|
-
end
|
216
|
-
|
217
|
-
def read_enums(connection)
|
218
|
-
connection[ENUMS_QUERY].map do |enum_data|
|
219
|
-
Definitions::Enum.new(enum_data[:name].to_sym, enum_data[:values].map(&:to_sym))
|
220
|
-
end
|
221
|
-
end
|
222
|
-
|
223
|
-
def read_extensions(connection)
|
224
|
-
connection[EXTENSIONS_QUERY].map do |extension_data|
|
225
|
-
Definitions::Extension.new(extension_data[:extname].to_sym)
|
226
|
-
end
|
227
|
-
end
|
228
|
-
|
229
|
-
private
|
230
|
-
def index_expressions_data(indexes_data, connection)
|
231
|
-
all_positions, max_position = {}, 0
|
232
|
-
|
233
|
-
indexes_data.each do |index_data|
|
234
|
-
positions = index_data[:column_positions].split(' ').map(&:to_i)
|
235
|
-
expression_positions = positions.each_index.select { |i| positions[i].zero? }
|
236
|
-
|
237
|
-
if expression_positions.any?
|
238
|
-
all_positions[index_data[:index_oid]] = expression_positions
|
239
|
-
max_position = [max_position, expression_positions.max].max
|
240
|
-
end
|
241
|
-
end
|
242
|
-
|
243
|
-
if all_positions.any?
|
244
|
-
connection[
|
245
|
-
EXPRESSION_INDEXES_QUERY,
|
246
|
-
Sequel.pg_array(all_positions.keys),
|
247
|
-
Sequel.pg_array((1..max_position.succ).to_a)
|
248
|
-
].each_with_object({}) do |index_data, indexes_data|
|
249
|
-
index_id = index_data[:index_id]
|
250
|
-
expressions = all_positions[index_id].map { |pos| index_data[:definitions][pos] }
|
251
|
-
|
252
|
-
indexes_data[index_id] = expressions
|
253
|
-
end
|
254
|
-
else
|
255
|
-
{}
|
256
|
-
end
|
257
|
-
end
|
258
|
-
|
259
|
-
def build_field(data, primary_key: false)
|
260
|
-
type = data[:type].to_sym.downcase
|
261
|
-
if type == :'user-defined'
|
262
|
-
type = data[:custom_type_name].to_sym
|
263
|
-
end
|
264
|
-
|
265
|
-
nullable = (data[:null] != 'NO')
|
266
|
-
|
267
|
-
unless primary_key || data[:default].nil?
|
268
|
-
default = if match = DEFAULT_VALUE.match(data[:default])
|
269
|
-
if match[:date]
|
270
|
-
Date.parse(match[:date])
|
271
|
-
elsif match[:time]
|
272
|
-
Time.parse(match[:time])
|
273
|
-
elsif match[:string]
|
274
|
-
match[:string]
|
275
|
-
elsif match[:integer]
|
276
|
-
match[:integer].to_i
|
277
|
-
elsif match[:float]
|
278
|
-
match[:float].to_f
|
279
|
-
elsif match[:boolean]
|
280
|
-
match[:boolean] == 'true'
|
281
|
-
end
|
282
|
-
else
|
283
|
-
data[:default].to_sym
|
284
|
-
end
|
285
|
-
end
|
286
|
-
|
287
|
-
options = case type
|
288
|
-
when :character, :'character varying', :bit, :'bit varying'
|
289
|
-
Utils.rename_keys(
|
290
|
-
Utils.filter_by_keys(data, :char_length),
|
291
|
-
char_length: :length
|
292
|
-
)
|
293
|
-
when :numeric
|
294
|
-
Utils.rename_keys(
|
295
|
-
Utils.filter_by_keys(data, :num_precision, :num_scale),
|
296
|
-
num_precision: :precision,
|
297
|
-
num_scale: :scale
|
298
|
-
)
|
299
|
-
when :interval
|
300
|
-
Utils.rename_keys(
|
301
|
-
Utils.filter_by_keys(data, :dt_precision, :interval_type),
|
302
|
-
dt_precision: :precision
|
303
|
-
) do |attributes|
|
304
|
-
if interval_type = attributes.delete(:interval_type)
|
305
|
-
attributes[:fields] = interval_type.gsub(/\(\d\)/, '').downcase.to_sym
|
306
|
-
end
|
307
|
-
end
|
308
|
-
when :array
|
309
|
-
Utils.rename_keys(
|
310
|
-
Utils.filter_by_keys(data, :element_type, :element_custom_type_name)
|
311
|
-
) do |attributes|
|
312
|
-
attributes[:element_type] = if attributes[:element_type] == 'USER-DEFINED'
|
313
|
-
attributes[:element_custom_type_name]
|
314
|
-
else
|
315
|
-
attributes[:element_type]
|
316
|
-
end.to_sym
|
317
|
-
end
|
318
|
-
else
|
319
|
-
{}
|
320
|
-
end
|
321
|
-
|
322
|
-
Definitions::Field.build(
|
323
|
-
data[:name].to_sym,
|
324
|
-
type,
|
325
|
-
primary_key: primary_key,
|
326
|
-
null: nullable,
|
327
|
-
default: default,
|
328
|
-
**options
|
329
|
-
)
|
330
|
-
end
|
331
|
-
|
332
|
-
def build_foreign_key(data, connection)
|
333
|
-
keys = if data[:key] == [primary_key_for(data[:table], connection)]
|
334
|
-
[] # this foreign key references a primary key
|
335
|
-
else
|
336
|
-
data[:key]
|
4
|
+
def reader_for(connection)
|
5
|
+
case connection.adapter_scheme
|
6
|
+
when :postgres
|
7
|
+
unless defined?(Reader::Postgres)
|
8
|
+
raise 'You need the \'db_schema-reader-postgres\' gem in order to work with PostgreSQL database structure.'
|
337
9
|
end
|
338
10
|
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
table: data[:table],
|
343
|
-
keys: keys,
|
344
|
-
on_delete: data[:on_delete],
|
345
|
-
on_update: data[:on_update],
|
346
|
-
deferrable: data[:deferrable]
|
347
|
-
)
|
348
|
-
end
|
349
|
-
|
350
|
-
def primary_key_for(table_name, connection)
|
351
|
-
if pkey = connection.primary_key(table_name)
|
352
|
-
pkey.to_sym
|
353
|
-
end
|
11
|
+
Reader::Postgres.new(connection)
|
12
|
+
else
|
13
|
+
raise NotImplementedError, "DbSchema::Reader does not support #{connection.adapter_scheme}."
|
354
14
|
end
|
355
15
|
end
|
356
16
|
end
|
357
|
-
|
358
|
-
registry[:postgres] = Postgres
|
359
17
|
end
|
360
18
|
end
|