db_schema-reader-postgres 0.1.1 → 0.2.rc1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 9f12b3dcea5dc1a301418825e2b8da015e078c520195e42517da991830d3bc22
4
- data.tar.gz: 52778450688b800dccf4934525fc567f0d99a9b426095298f198728cb827a9e6
3
+ metadata.gz: 8b2b3ebe11fc219d52a9576207a384fa6dd8f9b6178a5a65efaadbb215c3dcd9
4
+ data.tar.gz: 0fbc9926bcf4429875278c1d9b9157cf91618f6dad67c245c109fd85dbfc04e8
5
5
  SHA512:
6
- metadata.gz: 7c222884746207d2c46ab112ed40b7d78b4de10feef39dbeee650fa0b40c58bd00307c121ce1fa550391379aa61e80a4d78275e7c2782394f4e91153be986997
7
- data.tar.gz: 7ec7a253c3ca0c576b6935df764a24456994b8a26a045d5614445164399dff84568c424d11955ab4560542eef9ec8d340c215ee82145c7b585b27c38b5cf003a
6
+ metadata.gz: 3f55b980f9ceb11448e1699da20f071dcc75cbd79c3dfee4869081f2fb1450b04d0027be2df92310082a5c54144c5ce8df27efa21cc1d9d19365a0127280512e
7
+ data.tar.gz: 809c304408c6f03014db7ad5169f36f6616d3765d6e31a96f6ee6e566d3e3c963788a6df796eac373e59851cc42c0b69ae21a335ceb2f2a7399adde32d1ac1db
data/.travis.yml CHANGED
@@ -1,10 +1,10 @@
1
1
  sudo: false
2
2
  language: ruby
3
3
  rvm:
4
- - 2.2.8
5
- - 2.3.5
6
- - 2.4.2
7
- before_install: gem install bundler -v 1.16.0
4
+ - 2.3.8
5
+ - 2.4.5
6
+ - 2.5.3
7
+ - 2.6.0
8
8
  services:
9
9
  - postgresql
10
10
  addons:
data/Gemfile CHANGED
@@ -1,3 +1,5 @@
1
1
  source 'https://rubygems.org'
2
2
 
3
+ gem 'db_schema-definitions', github: 'db-schema/definitions', branch: 'primary_keys'
4
+
3
5
  gemspec
@@ -20,7 +20,7 @@ Gem::Specification.new do |spec|
20
20
 
21
21
  spec.add_runtime_dependency 'sequel'
22
22
  spec.add_runtime_dependency 'pg'
23
- spec.add_runtime_dependency 'db_schema-definitions', '~> 0.1.0'
23
+ spec.add_runtime_dependency 'db_schema-definitions', '= 0.2.rc1'
24
24
 
25
25
  spec.add_development_dependency 'bundler', '~> 1.16'
26
26
  spec.add_development_dependency 'rake', '~> 10.0'
@@ -5,6 +5,84 @@ require_relative 'postgres/version'
5
5
  module DbSchema
6
6
  module Reader
7
7
  class Postgres
8
+ COLUMNS_QUERY = <<-SQL.freeze
9
+ SELECT c.table_name,
10
+ c.column_name AS name,
11
+ c.ordinal_position AS pos,
12
+ c.column_default AS default,
13
+ c.is_nullable AS null,
14
+ c.data_type AS type,
15
+ c.is_identity,
16
+ c.udt_name AS custom_type_name,
17
+ c.character_maximum_length AS char_length,
18
+ c.numeric_precision AS num_precision,
19
+ c.numeric_scale AS num_scale,
20
+ c.datetime_precision AS dt_precision,
21
+ c.interval_type,
22
+ e.data_type AS element_type,
23
+ e.udt_name AS element_custom_type_name
24
+ FROM information_schema.columns AS c
25
+ LEFT JOIN information_schema.element_types AS e
26
+ ON e.object_catalog = c.table_catalog
27
+ AND e.object_schema = c.table_schema
28
+ AND e.object_name = c.table_name
29
+ AND e.object_type = 'TABLE'
30
+ AND e.collection_type_identifier = c.dtd_identifier
31
+ WHERE c.table_schema = 'public'
32
+ SQL
33
+
34
+ INDEXES_QUERY = <<-SQL.freeze
35
+ SELECT table_rel.relname AS table_name,
36
+ pg_class.relname AS name,
37
+ indkey AS column_positions,
38
+ indisprimary AS primary,
39
+ indisunique AS unique,
40
+ indoption AS index_options,
41
+ pg_get_expr(indpred, indrelid, true) AS condition,
42
+ amname AS index_type,
43
+ indexrelid AS index_oid
44
+ FROM pg_class, pg_index
45
+ LEFT JOIN pg_opclass
46
+ ON pg_opclass.oid = ANY(pg_index.indclass::int[])
47
+ LEFT JOIN pg_am
48
+ ON pg_am.oid = pg_opclass.opcmethod
49
+ JOIN pg_class AS table_rel
50
+ ON table_rel.oid = pg_index.indrelid
51
+ JOIN pg_namespace
52
+ ON pg_namespace.oid = table_rel.relnamespace
53
+ WHERE pg_class.oid = pg_index.indexrelid
54
+ AND pg_namespace.nspname = 'public'
55
+ GROUP BY table_name, name, column_positions, indisprimary, indisunique, index_options, condition, index_type, index_oid
56
+ SQL
57
+
58
+ EXPRESSION_INDEXES_QUERY = <<-SQL.freeze
59
+ WITH index_ids AS (SELECT unnest(?) AS index_id),
60
+ elements AS (SELECT unnest(?) AS element)
61
+ SELECT index_id,
62
+ array_agg(pg_get_indexdef(index_id, element, 't')) AS definitions
63
+ FROM index_ids, elements
64
+ GROUP BY index_id;
65
+ SQL
66
+
67
+ CONSTRAINTS_QUERY = <<-SQL.freeze
68
+ SELECT owner_table.relname AS table_name,
69
+ constr.conname AS name,
70
+ pg_get_expr(conbin, conrelid, true) AS condition,
71
+ referenced_table.relname AS referenced,
72
+ conkey,
73
+ confkey,
74
+ confupdtype AS on_update,
75
+ confdeltype AS on_delete,
76
+ condeferrable AS deferrable,
77
+ constr.contype AS type
78
+ FROM pg_constraint AS constr
79
+ JOIN pg_class AS owner_table
80
+ ON owner_table.oid = constr.conrelid
81
+ LEFT JOIN pg_class AS referenced_table
82
+ ON referenced_table.oid = constr.confrelid
83
+ WHERE contype IN ('c', 'f');
84
+ SQL
85
+
8
86
  ENUMS_QUERY = <<-SQL.freeze
9
87
  SELECT t.typname AS name,
10
88
  array_agg(e.enumlabel ORDER BY e.enumsortorder) AS values
@@ -35,13 +113,17 @@ SELECT extname
35
113
  end
36
114
 
37
115
  def read_tables
38
- connection.tables.map do |table_name|
39
- read_table(table_name)
40
- end
41
- end
116
+ checks_data, foreign_keys_data = constraints_data
42
117
 
43
- def read_table(table_name)
44
- Table.new(connection, table_name).read
118
+ columns_data.keys.map do |table_name|
119
+ Table.new(
120
+ table_name.to_sym,
121
+ columns_data[table_name],
122
+ indexes_data[table_name],
123
+ checks_data[table_name],
124
+ foreign_keys_data[table_name]
125
+ ).definition
126
+ end
45
127
  end
46
128
 
47
129
  def read_enums
@@ -55,6 +137,120 @@ SELECT extname
55
137
  Definitions::Extension.new(extension_data[:extname].to_sym)
56
138
  end
57
139
  end
140
+
141
+ private
142
+ def columns_data
143
+ @columns_data ||= connection[COLUMNS_QUERY].to_a.group_by do |column|
144
+ column[:table_name]
145
+ end
146
+ end
147
+
148
+ def indexes_data
149
+ @indexes_data ||= begin
150
+ raw_data = connection[INDEXES_QUERY].map do |index_data|
151
+ index_data.merge(
152
+ column_positions: index_data[:column_positions].split(' ').map(&:to_i),
153
+ index_options: index_data[:index_options].split(' ').map(&:to_i)
154
+ )
155
+ end
156
+
157
+ expressions_data = index_expressions_data(raw_data)
158
+
159
+ raw_data.map do |index_data|
160
+ columns = index_data[:column_positions].map do |position|
161
+ if position.zero?
162
+ expressions_data.fetch(index_data[:index_oid]).shift
163
+ else
164
+ get_field_name(index_data[:table_name], position)
165
+ end
166
+ end
167
+
168
+ index_data.delete(:index_oid)
169
+ index_data.delete(:column_positions)
170
+ index_data.merge(columns: columns)
171
+ end.group_by { |index| index[:table_name] }.tap { |h| h.default = [] }
172
+ end
173
+ end
174
+
175
+ def index_expressions_data(indexes_data)
176
+ all_positions, max_position = {}, 0
177
+
178
+ indexes_data.each do |index_data|
179
+ positions = index_data[:column_positions]
180
+ expression_positions = positions.each_index.select do |i|
181
+ positions[i].zero?
182
+ end
183
+
184
+ if expression_positions.any?
185
+ all_positions[index_data[:index_oid]] = expression_positions
186
+ max_position = [max_position, expression_positions.max].max
187
+ end
188
+ end
189
+
190
+ if all_positions.any?
191
+ connection[
192
+ EXPRESSION_INDEXES_QUERY,
193
+ Sequel.pg_array(all_positions.keys),
194
+ Sequel.pg_array((1..max_position.succ).to_a)
195
+ ].each_with_object({}) do |index_data, indexes_data|
196
+ index_id = index_data[:index_id]
197
+ expressions = all_positions[index_id].map { |pos| index_data[:definitions][pos] }
198
+
199
+ indexes_data[index_id] = expressions
200
+ end
201
+ else
202
+ {}
203
+ end
204
+ end
205
+
206
+ def constraints_data
207
+ checks = Hash.new { |h, k| h[k] = [] }
208
+ foreign_keys = Hash.new { |h, k| h[k] = [] }
209
+
210
+ connection[CONSTRAINTS_QUERY].each do |constraint|
211
+ case constraint[:type]
212
+ when 'c'
213
+ checks[constraint[:table_name]] << {
214
+ name: constraint[:name],
215
+ condition: constraint[:condition]
216
+ }
217
+ when 'f'
218
+ fields = constraint[:conkey].map do |position|
219
+ get_field_name(constraint[:table_name], position)
220
+ end
221
+
222
+ keys = constraint[:confkey].map do |position|
223
+ get_field_name(constraint[:referenced], position)
224
+ end
225
+
226
+ pkey_columns = indexes_data.fetch(constraint[:referenced]).find do |index|
227
+ index[:primary]
228
+ end.fetch(:columns)
229
+
230
+ keys = [] if keys == pkey_columns # this foreign key references a primary key
231
+
232
+ foreign_keys[constraint[:table_name]] << {
233
+ name: constraint[:name],
234
+ referenced: constraint[:referenced],
235
+ fields: fields,
236
+ keys: keys,
237
+ on_update: constraint[:on_update],
238
+ on_delete: constraint[:on_delete],
239
+ deferrable: constraint[:deferrable]
240
+ }
241
+ else
242
+ raise "Unknown constraint type #{constraint[:type].inspect}"
243
+ end
244
+ end
245
+
246
+ [checks, foreign_keys]
247
+ end
248
+
249
+ def get_field_name(table, position)
250
+ columns_data.fetch(table).find do |column|
251
+ column[:pos] == position
252
+ end.fetch(:name).to_sym
253
+ end
58
254
  end
59
255
  end
60
256
  end
@@ -2,6 +2,12 @@ module DbSchema
2
2
  module Reader
3
3
  class Postgres
4
4
  class Table
5
+ SERIAL_TYPES = {
6
+ smallint: :smallserial,
7
+ integer: :serial,
8
+ bigint: :bigserial
9
+ }.freeze
10
+
5
11
  DEFAULT_VALUE = /\A(
6
12
  ('(?<date>\d{4}-\d{2}-\d{2})'::date)
7
13
  |
@@ -16,102 +22,25 @@ module DbSchema
16
22
  (?<boolean>true|false)
17
23
  )/x
18
24
 
19
- COLUMN_NAMES_QUERY = <<-SQL.freeze
20
- SELECT c.column_name AS name,
21
- c.ordinal_position AS pos,
22
- c.column_default AS default,
23
- c.is_nullable AS null,
24
- c.data_type AS type,
25
- c.udt_name AS custom_type_name,
26
- c.character_maximum_length AS char_length,
27
- c.numeric_precision AS num_precision,
28
- c.numeric_scale AS num_scale,
29
- c.datetime_precision AS dt_precision,
30
- c.interval_type,
31
- e.data_type AS element_type,
32
- e.udt_name AS element_custom_type_name
33
- FROM information_schema.columns AS c
34
- LEFT JOIN information_schema.element_types AS e
35
- ON e.object_catalog = c.table_catalog
36
- AND e.object_schema = c.table_schema
37
- AND e.object_name = c.table_name
38
- AND e.object_type = 'TABLE'
39
- AND e.collection_type_identifier = c.dtd_identifier
40
- WHERE c.table_schema = 'public'
41
- AND c.table_name = ?
42
- SQL
43
-
44
- CONSTRAINTS_QUERY = <<-SQL.freeze
45
- SELECT conname AS name,
46
- pg_get_expr(conbin, conrelid, true) AS condition
47
- FROM pg_constraint, pg_class
48
- WHERE conrelid = pg_class.oid
49
- AND relname = ?
50
- AND contype = 'c'
51
- SQL
52
-
53
- INDEXES_QUERY = <<-SQL.freeze
54
- SELECT relname AS name,
55
- indkey AS column_positions,
56
- indisunique AS unique,
57
- indoption AS index_options,
58
- pg_get_expr(indpred, indrelid, true) AS condition,
59
- amname AS index_type,
60
- indexrelid AS index_oid
61
- FROM pg_class, pg_index
62
- LEFT JOIN pg_opclass
63
- ON pg_opclass.oid = ANY(pg_index.indclass::int[])
64
- LEFT JOIN pg_am
65
- ON pg_am.oid = pg_opclass.opcmethod
66
- WHERE pg_class.oid = pg_index.indexrelid
67
- AND pg_class.oid IN (
68
- SELECT indexrelid
69
- FROM pg_index, pg_class
70
- WHERE pg_class.relname = ?
71
- AND pg_class.oid = pg_index.indrelid
72
- AND indisprimary != 't'
73
- )
74
- GROUP BY name, column_positions, indisunique, index_options, condition, index_type, index_oid
75
- SQL
76
-
77
- EXPRESSION_INDEXES_QUERY = <<-SQL.freeze
78
- WITH index_ids AS (SELECT unnest(?) AS index_id),
79
- elements AS (SELECT unnest(?) AS element)
80
- SELECT index_id,
81
- array_agg(pg_get_indexdef(index_id, element, 't')) AS definitions
82
- FROM index_ids, elements
83
- GROUP BY index_id;
84
- SQL
85
-
86
- attr_reader :connection, :table_name
87
-
88
- def initialize(connection, table_name)
89
- @connection = connection
90
- @table_name = table_name
25
+ FKEY_ACTIONS = {
26
+ a: :no_action,
27
+ r: :restrict,
28
+ c: :cascade,
29
+ n: :set_null,
30
+ d: :set_default
31
+ }.freeze
32
+
33
+ attr_reader :table_name, :fields_data, :indexes_data, :checks_data, :fkeys_data
34
+
35
+ def initialize(table_name, fields_data, indexes_data, checks_data, fkeys_data)
36
+ @table_name = table_name
37
+ @fields_data = fields_data
38
+ @indexes_data = indexes_data
39
+ @checks_data = checks_data
40
+ @fkeys_data = fkeys_data
91
41
  end
92
42
 
93
- def read
94
- primary_key_name = connection.primary_key(table_name)
95
-
96
- fields = columns_data.map do |column_data|
97
- build_field(column_data, primary_key: column_data[:name] == primary_key_name)
98
- end
99
-
100
- indexes = indexes_data.map do |index_data|
101
- Definitions::Index.new(index_data)
102
- end.sort_by(&:name)
103
-
104
- foreign_keys = connection.foreign_key_list(table_name).map do |foreign_key_data|
105
- build_foreign_key(foreign_key_data)
106
- end
107
-
108
- checks = connection[CONSTRAINTS_QUERY, table_name.to_s].map do |check_data|
109
- Definitions::CheckConstraint.new(
110
- name: check_data[:name].to_sym,
111
- condition: check_data[:condition]
112
- )
113
- end
114
-
43
+ def definition
115
44
  Definitions::Table.new(
116
45
  table_name,
117
46
  fields: fields,
@@ -121,107 +50,71 @@ GROUP BY index_id;
121
50
  )
122
51
  end
123
52
 
124
- private
125
- def columns_data
126
- @columns_data ||= connection[COLUMN_NAMES_QUERY, table_name.to_s]
127
- end
128
-
129
- def indexes_data
130
- column_names = columns_data.reduce({}) do |names, column|
131
- names.merge(column[:pos] => column[:name].to_sym)
132
- end
133
-
134
- indexes_data = connection[INDEXES_QUERY, table_name.to_s].to_a
135
- expressions_data = index_expressions_data(indexes_data)
136
-
137
- indexes_data.map do |index|
138
- positions = index[:column_positions].split(' ').map(&:to_i)
139
- options = index[:index_options].split(' ').map(&:to_i)
140
-
141
- columns = positions.zip(options).map do |column_position, column_order_options|
142
- options = case column_order_options
143
- when 0
144
- {}
145
- when 3
146
- { order: :desc }
147
- when 2
148
- { nulls: :first }
149
- when 1
150
- { order: :desc, nulls: :last }
151
- end
152
-
153
- if column_position.zero?
154
- expression = expressions_data.fetch(index[:index_oid]).shift
155
- DbSchema::Definitions::Index::Expression.new(expression, **options)
156
- else
157
- DbSchema::Definitions::Index::TableField.new(column_names.fetch(column_position), **options)
158
- end
159
- end
160
-
161
- {
162
- name: index[:name].to_sym,
163
- columns: columns,
164
- unique: index[:unique],
165
- type: index[:index_type].to_sym,
166
- condition: index[:condition]
167
- }
53
+ def fields
54
+ fields_data.map do |field_data|
55
+ build_field(field_data)
168
56
  end
169
57
  end
170
58
 
171
- def index_expressions_data(indexes_data)
172
- all_positions, max_position = {}, 0
173
-
174
- indexes_data.each do |index_data|
175
- positions = index_data[:column_positions].split(' ').map(&:to_i)
176
- expression_positions = positions.each_index.select { |i| positions[i].zero? }
59
+ def indexes
60
+ indexes_data.map do |index_data|
61
+ build_index(index_data)
62
+ end.sort_by(&:name)
63
+ end
177
64
 
178
- if expression_positions.any?
179
- all_positions[index_data[:index_oid]] = expression_positions
180
- max_position = [max_position, expression_positions.max].max
181
- end
65
+ def checks
66
+ checks_data.map do |check_data|
67
+ Definitions::CheckConstraint.new(
68
+ name: check_data[:name].to_sym,
69
+ condition: check_data[:condition]
70
+ )
182
71
  end
72
+ end
183
73
 
184
- if all_positions.any?
185
- connection[
186
- EXPRESSION_INDEXES_QUERY,
187
- Sequel.pg_array(all_positions.keys),
188
- Sequel.pg_array((1..max_position.succ).to_a)
189
- ].each_with_object({}) do |index_data, indexes_data|
190
- index_id = index_data[:index_id]
191
- expressions = all_positions[index_id].map { |pos| index_data[:definitions][pos] }
192
-
193
- indexes_data[index_id] = expressions
194
- end
195
- else
196
- {}
74
+ def foreign_keys
75
+ fkeys_data.map do |foreign_key_data|
76
+ build_foreign_key(foreign_key_data)
197
77
  end
198
78
  end
199
79
 
200
- def build_field(data, primary_key: false)
80
+ private
81
+ def build_field(data)
201
82
  type = data[:type].to_sym.downcase
202
83
  if type == :'user-defined'
203
84
  type = data[:custom_type_name].to_sym
204
85
  end
205
86
 
87
+ serial_type = SERIAL_TYPES[type]
88
+
206
89
  nullable = (data[:null] != 'NO')
207
90
 
208
- unless primary_key || data[:default].nil?
209
- default = if match = DEFAULT_VALUE.match(data[:default])
210
- if match[:date]
211
- Date.parse(match[:date])
212
- elsif match[:time]
213
- Time.parse(match[:time])
214
- elsif match[:string]
215
- match[:string]
216
- elsif match[:integer]
217
- match[:integer].to_i
218
- elsif match[:float]
219
- match[:float].to_f
220
- elsif match[:boolean]
221
- match[:boolean] == 'true'
222
- end
91
+ if data[:is_identity] == 'YES'
92
+ type = serial_type
93
+ default = nil
94
+ elsif !data[:default].nil?
95
+ serial_field_default = "nextval('#{table_name}_#{data[:name]}_seq'::regclass)"
96
+
97
+ if !serial_type.nil? && !nullable && data[:default] == serial_field_default
98
+ type = serial_type
99
+ default = nil
223
100
  else
224
- data[:default].to_sym
101
+ default = if match = DEFAULT_VALUE.match(data[:default])
102
+ if match[:date]
103
+ Date.parse(match[:date])
104
+ elsif match[:time]
105
+ Time.parse(match[:time])
106
+ elsif match[:string]
107
+ match[:string]
108
+ elsif match[:integer]
109
+ match[:integer].to_i
110
+ elsif match[:float]
111
+ match[:float].to_f
112
+ elsif match[:boolean]
113
+ match[:boolean] == 'true'
114
+ end
115
+ else
116
+ data[:default].to_sym
117
+ end
225
118
  end
226
119
  end
227
120
 
@@ -263,35 +156,52 @@ GROUP BY index_id;
263
156
  Definitions::Field.build(
264
157
  data[:name].to_sym,
265
158
  type,
266
- primary_key: primary_key,
267
- null: nullable,
268
- default: default,
159
+ null: nullable,
160
+ default: default,
269
161
  **options
270
162
  )
271
163
  end
272
164
 
273
- def build_foreign_key(data)
274
- keys = if data[:key] == [primary_key_for(data[:table])]
275
- [] # this foreign key references a primary key
276
- else
277
- data[:key]
165
+ def build_index(data)
166
+ columns = data[:columns].zip(data[:index_options]).map do |column, order_options|
167
+ options = case order_options
168
+ when 0
169
+ {}
170
+ when 3
171
+ { order: :desc }
172
+ when 2
173
+ { nulls: :first }
174
+ when 1
175
+ { order: :desc, nulls: :last }
176
+ end
177
+
178
+ if column.is_a?(String)
179
+ DbSchema::Definitions::Index::Expression.new(column, **options)
180
+ else
181
+ DbSchema::Definitions::Index::TableField.new(column, **options)
182
+ end
278
183
  end
279
184
 
280
- Definitions::ForeignKey.new(
281
- name: data[:name],
282
- fields: data[:columns],
283
- table: data[:table],
284
- keys: keys,
285
- on_delete: data[:on_delete],
286
- on_update: data[:on_update],
287
- deferrable: data[:deferrable]
185
+ Definitions::Index.new(
186
+ name: data[:name].to_sym,
187
+ columns: columns,
188
+ unique: data[:unique],
189
+ primary: data[:primary],
190
+ type: data[:index_type].to_sym,
191
+ condition: data[:condition]
288
192
  )
289
193
  end
290
194
 
291
- def primary_key_for(table_name)
292
- if pkey = connection.primary_key(table_name)
293
- pkey.to_sym
294
- end
195
+ def build_foreign_key(data)
196
+ Definitions::ForeignKey.new(
197
+ name: data[:name].to_sym,
198
+ fields: data[:fields],
199
+ table: data[:referenced].to_sym,
200
+ keys: data[:keys],
201
+ on_update: FKEY_ACTIONS.fetch(data[:on_update].to_sym),
202
+ on_delete: FKEY_ACTIONS.fetch(data[:on_delete].to_sym),
203
+ deferrable: data[:deferrable]
204
+ )
295
205
  end
296
206
 
297
207
  # TODO: replace following methods with Transproc
@@ -1,7 +1,7 @@
1
1
  module DbSchema
2
2
  module Reader
3
3
  class Postgres
4
- VERSION = '0.1.1'
4
+ VERSION = '0.2.rc1'
5
5
  end
6
6
  end
7
7
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: db_schema-reader-postgres
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.rc1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Vsevolod Romashov
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-10-31 00:00:00.000000000 Z
11
+ date: 2019-02-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sequel
@@ -42,16 +42,16 @@ dependencies:
42
42
  name: db_schema-definitions
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - "~>"
45
+ - - '='
46
46
  - !ruby/object:Gem::Version
47
- version: 0.1.0
47
+ version: 0.2.rc1
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - "~>"
52
+ - - '='
53
53
  - !ruby/object:Gem::Version
54
- version: 0.1.0
54
+ version: 0.2.rc1
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: bundler
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -202,12 +202,11 @@ required_ruby_version: !ruby/object:Gem::Requirement
202
202
  version: '0'
203
203
  required_rubygems_version: !ruby/object:Gem::Requirement
204
204
  requirements:
205
- - - ">="
205
+ - - ">"
206
206
  - !ruby/object:Gem::Version
207
- version: '0'
207
+ version: 1.3.1
208
208
  requirements: []
209
- rubyforge_project:
210
- rubygems_version: 2.7.6
209
+ rubygems_version: 3.0.1
211
210
  signing_key:
212
211
  specification_version: 4
213
212
  summary: Database schema reader for PostgreSQL