pg_graph 0.4.2 → 0.5.1

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: 829bab0e543f48a02760b6a6888967bce94f2d5a4456fc6af81f43a084275532
4
- data.tar.gz: 0ca91b04090f570ef3bac358791e37f911e030c3dc334edb941a739896099057
3
+ metadata.gz: 3605f3dc16a65459725b3890e9dc85d4c7f4bf3fbdbf216526a12a1c843ef6f7
4
+ data.tar.gz: 34a6d5f23cf5914d43f53835f817aedb79f9699104c807d20d30fb9507633162
5
5
  SHA512:
6
- metadata.gz: 5fc04dbdebdf415b9c6e51e5af2a398689c517c7becae479a4f8eee9f5fcafa5bcd78d52e370fbfc8b893d86fa09e2cc14b41b8f161c55f67fed1f0caa749d84
7
- data.tar.gz: dec4aad67d9eba1236688baca32f013889748083ecec306b081dafd9c119c20fc05cdac422e0aa13e40da7417335681d791173c5d24113b0d5f21ab178398435
6
+ metadata.gz: e5e870b7ecd6ec71a8c0b8e5196511963402a372374efa003c522b847ec3b92ba50904c36046451930a79f6265455f0ba33f2f65547bd6b39a79ab88dc7ba30c
7
+ data.tar.gz: ec4d637a227f5a94beda42b2075240e9ecc1d70af3eaf1fa3c9c9c7c4d5990f269b70751985aa17482f3210c3ffbb635ed92638f8d5b5d69906c7e57fcc9526e
data/TODO CHANGED
@@ -1,4 +1,5 @@
1
1
 
2
+ o Fix that tables are not deleted in dependency order
2
3
  o Propagate super table relations to sub-tables
3
4
  o Provide a way to exclude certain schemas from the model (eg. prick/postspec/etc.)
4
5
  o Move SimpleType to PgCatalog schema
data/exe/pg_graph CHANGED
@@ -16,7 +16,7 @@ SPEC = %(
16
16
  ('psql') or by the Postgres library exec() call ('exec', 'sql'). It can also
17
17
  read and write Yaml data ('yaml') that is useful for exchanging data with
18
18
  other programs
19
-
19
+
20
20
  Note that when you're loading or dumping data in one of the SQL formats,
21
21
  you're almost always better off using postgres' own tools
22
22
  (pg_dump/pg_restore/pg_sql), except in the special case when the data
@@ -44,8 +44,8 @@ SPEC = %(
44
44
  Read/write reflections in the given table. The table argument can be both a
45
45
  full UID (eg. "my_schema.my_reflections") or just a table name in the public
46
46
  schema. Default is "public.reflections". The table and schema is created
47
- if not present.
48
-
47
+ if not present.
48
+
49
49
  If this option is used together with the --reflections option, the
50
50
  reflections are read from th e given file and written back to the database.
51
51
  If both options are missing, pg_graph will look for the default table and
@@ -74,7 +74,7 @@ SPEC = %(
74
74
  extension but can also be set explicitly using the --format option. Reads
75
75
  from standard input if FILE is missing
76
76
 
77
- dump! -- DATABASE
77
+ dump! -- DATABASE
78
78
  Dumps data on standard output. Default is to dump the type system in yaml
79
79
  format but this can be explicitly set using the --kind and --format options
80
80
 
@@ -96,7 +96,7 @@ def load_type(timer, opts, database)
96
96
  PgMeta.new(conn)
97
97
  end
98
98
  }
99
- reflector = tg.time("reflector") {
99
+ reflector = tg.time("reflector") {
100
100
  table, schema = opts.reflections_table&.split(".")&.reverse
101
101
  schema ||= PgGraph::Reflector::REFLECTIONS_SCHEMA
102
102
  table ||= PgGraph::Reflector::REFLECTIONS_TABLE
@@ -115,7 +115,7 @@ def load_type(timer, opts, database)
115
115
  end
116
116
  end
117
117
  }
118
-
118
+
119
119
  type = timer.time("type") { PgGraph::Type.new(meta, reflector, ignore: opts.ignore) }
120
120
  [conn, type]
121
121
  end
@@ -133,7 +133,7 @@ case opts.subcommand || :dump!
133
133
  if opts.format?
134
134
  format = opts.format
135
135
  else
136
- format =
136
+ format =
137
137
  case File.extname(file)
138
138
  when ".sql"; "sql"
139
139
  when ".yaml", ".yml"; "yaml"
@@ -143,7 +143,7 @@ case opts.subcommand || :dump!
143
143
  end
144
144
 
145
145
  case format
146
- when "sql", "exec";
146
+ when "sql", "exec";
147
147
  connection = timer.time("connect") { PgConn.new(database) }
148
148
  timer.time("load file") {
149
149
  connection.exec(IO.read(file))
@@ -37,8 +37,8 @@ module PgGraph::Data
37
37
  # value of a field even if the field is an association
38
38
  def object() self end
39
39
 
40
- def inspect(payload = inspect_inner)
41
- "#<#{self.class}:#{uid}#{payload ? " #{payload}" : ""}>"
40
+ def inspect(payload = inspect_inner)
41
+ "#<#{self.class}:#{uid}#{payload ? " #{payload}" : ""}>"
42
42
  end
43
43
 
44
44
  def to_h() raise NotThis end
@@ -93,7 +93,7 @@ module PgGraph::Data
93
93
  end
94
94
 
95
95
  def dup() Database.new(type, to_h) end
96
-
96
+
97
97
  # Make Database pretend it is a PgGraph::Data object
98
98
  def is_a?(klass) klass == PgGraph::Type or super end
99
99
 
@@ -115,7 +115,7 @@ module PgGraph::Data
115
115
  id.nil? ? object : object[id]
116
116
  end
117
117
 
118
- def ==(other) to_h == other.to_h end
118
+ def ==(other) to_h == other.to_h end
119
119
 
120
120
  alias_method :to_h, :data
121
121
 
@@ -124,17 +124,17 @@ module PgGraph::Data
124
124
  def to_yaml() @impl.map { |k,v| [k, v.to_yaml] }.to_h end
125
125
 
126
126
  # Note that #to_sql in derived classes should be deleted FIXME
127
- def to_sql(format: :sql, ids: {}, delete: :all, files: [])
128
- render = SqlRender.new(self, format, ids: ids, delete: delete, files: files)
127
+ def to_sql(format: :sql, ids: {}, delete: :all, truncate: :none, files: [])
128
+ render = SqlRender.new(self, format, ids: ids, delete: delete, truncate: truncate, files: files)
129
129
  render.to_s
130
130
  end
131
131
 
132
- def to_exec_sql(ids: {}, delete: :all)
133
- to_sql(format: :exec, ids: ids, delete: delete)
132
+ def to_exec_sql(ids: {}, delete: :all)
133
+ to_sql(format: :exec, ids: ids, delete: delete)
134
134
  end
135
135
 
136
- def to_psql_sql(files = [], ids: {}, delete: :all)
137
- to_sql(format: :psql, ids: ids, delete: delete, files: files)
136
+ def to_psql_sql(files = [], ids: {}, delete: :all)
137
+ to_sql(format: :psql, ids: ids, delete: delete, files: files)
138
138
  end
139
139
 
140
140
  # :call-seq:
@@ -208,8 +208,8 @@ module PgGraph::Data
208
208
  def data() @impl.map { |k,v| [k, v.data] }.to_h end
209
209
 
210
210
  alias_method :to_h, :data
211
- # def to_sql()
212
- # tables.select { |table| !table.empty? }.map(&:to_sql).join("\n")
211
+ # def to_sql()
212
+ # tables.select { |table| !table.empty? }.map(&:to_sql).join("\n")
213
213
  # end
214
214
  def to_yaml() @impl.map { |k,v| [k, v.to_yaml] }.to_h end
215
215
  end
@@ -245,29 +245,29 @@ module PgGraph::Data
245
245
  type.fields.each { |column|
246
246
  next if column.is_a?(PgGraph::Type::SimpleColumn)
247
247
  that_table = db[column.type.schema.name][column.type.table.name]
248
- association =
248
+ association =
249
249
  case column
250
250
  when PgGraph::Type::KindRecordColumn
251
251
  KindAssociation.new(1,
252
- self, that_table,
253
- column.this_link_column.to_sym,
252
+ self, that_table,
253
+ column.this_link_column.to_sym,
254
254
  column.that_link_column.to_sym)
255
255
  when PgGraph::Type::RecordColumn
256
- Association.new(1,
257
- self, that_table,
258
- column.this_link_column.to_sym,
256
+ Association.new(1,
257
+ self, that_table,
258
+ column.this_link_column.to_sym,
259
259
  column.that_link_column.to_sym)
260
260
  when PgGraph::Type::NmTableColumn, PgGraph::Type::MmTableColumn
261
261
  dimension = column.is_a?(PgGraph::Type::NmTableColumn) ? 2 : 3
262
262
  nm_table = db[column.mm_table.schema.name][column.mm_table.name]
263
- LinkAssociation.new(dimension,
263
+ LinkAssociation.new(dimension,
264
264
  self, that_table, nm_table,
265
- column.this_link_column.to_sym, column.this_mm_column.to_sym,
265
+ column.this_link_column.to_sym, column.this_mm_column.to_sym,
266
266
  column.that_mm_column.to_sym, column.that_link_column.to_sym)
267
267
  when PgGraph::Type::TableColumn
268
- Association.new(2,
269
- self, that_table,
270
- column.this_link_column.to_sym,
268
+ Association.new(2,
269
+ self, that_table,
270
+ column.this_link_column.to_sym,
271
271
  column.that_link_column.to_sym)
272
272
  else
273
273
  raise NotHere
@@ -284,7 +284,7 @@ module PgGraph::Data
284
284
 
285
285
  # Return record with the given ID
286
286
  def [](id) @impl[id] end
287
-
287
+
288
288
  # True if the table contains a record with the given ID
289
289
  def id?(id) @impl.key?(id) end
290
290
 
@@ -348,7 +348,7 @@ module PgGraph::Data
348
348
  uid =~ /^(.*?)\[(\d+)\]$/
349
349
  [$1, $2.to_i]
350
350
  end
351
-
351
+
352
352
  # Redefine GUID to include ID of record
353
353
  def guid() "#{table.guid}[#{id}]" end
354
354
 
@@ -371,7 +371,7 @@ module PgGraph::Data
371
371
  constrain columns, lambda { |h| h.key?(:id) }, "No :id field"
372
372
  @table = table # has to go before super
373
373
  super(table.type.record_type, dimension: 1)
374
- @impl = columns.map { |k,v| [k, Column.new(self, k, v)] }.to_h
374
+ @impl = columns.map { |k,v| [k, Column.new(self, k, v)] }.to_h
375
375
  for name, association in table.associations
376
376
  if association.is_a?(KindAssociation) #&& @impl.key?(name)
377
377
  next if !@impl.key?(name)
@@ -407,9 +407,9 @@ module PgGraph::Data
407
407
  def columns() @impl.values.select { |field| field.is_a?(Column) } end
408
408
 
409
409
  # List of columns excluding generated columns
410
- def value_columns()
410
+ def value_columns()
411
411
  columns.select { |column| !column.type.generated? }.uniq
412
- end
412
+ end
413
413
 
414
414
  # List of association objects in the record
415
415
  def associations() @impl.values.select { |field| field.is_a?(AssociationField) } end
@@ -422,7 +422,7 @@ module PgGraph::Data
422
422
  # def data() @impl.select { |k,v| v.is_a?(Column) }.map { |k,v| [k, v.data] }.to_h end
423
423
 
424
424
  def data()
425
- @impl.select { |k,v| v.is_a?(Column) || v.is_a?(KindRecordField) }.map { |k,v| [k, v.data] }.to_h
425
+ @impl.select { |k,v| v.is_a?(Column) || v.is_a?(KindRecordField) }.map { |k,v| [k, v.data] }.to_h
426
426
  end
427
427
 
428
428
  alias_method :to_h, :data
@@ -516,7 +516,7 @@ module PgGraph::Data
516
516
  # Return the value of the association. This is either a Record, TableValue,
517
517
  # or MmTableValue depending on the dimension of the association
518
518
  def object()
519
- @object ||= Dimension.value_class(dimension).new(table, association.get_records(record))
519
+ @object ||= Dimension.value_class(dimension).new(table, association.get_records(record))
520
520
  end
521
521
  end
522
522
 
@@ -530,7 +530,7 @@ module PgGraph::Data
530
530
  super(record, name, association)
531
531
  @column = column
532
532
  end
533
-
533
+
534
534
  def value_type() @column.value_type end
535
535
  def value() @column.value end
536
536
  def data() @column.data end
@@ -16,7 +16,13 @@ module PgGraph::Data
16
16
  # recursive - delete data for table in the fox file including recursively depending tables
17
17
  # all - delete data from the whole database
18
18
  attr_reader :delete
19
-
19
+
20
+ # Which data to truncate:
21
+ # none - don't delete any data
22
+ # touched - delete data for tables in the fox file
23
+ # all - delete data from the whole database
24
+ attr_reader :truncate
25
+
20
26
  # +ids+ is a map from table UID to ID. Records with larger IDs will
21
27
  # be emitted as insert statements, records with IDs less or equal to the
22
28
  # given ID is emitted as update statements
@@ -25,10 +31,15 @@ module PgGraph::Data
25
31
  # :recursive, :all Only records with an ID greater than the corresponding
26
32
  # ID from +ids+ will be deleted
27
33
  #
34
+ # +truncate+ acts as +delete+ that has the major drawback that it doesn't
35
+ # delete records in dependency order (FIXME This is an error). You can use
36
+ # the SQL truncate statement instead of delete using this option but note
37
+ # that +ids+ should be empty for this to work
38
+ #
28
39
  # +files+ is a list of source file names to be included in the psql SQL
29
40
  # header as documentation. It can be set explicitly when #to_a or #to_h is
30
41
  # called (FIXME: is this used?)
31
- def initialize(database, format, ids: {}, delete: :all, files: [])
42
+ def initialize(database, format, ids: {}, delete: :all, truncate: :none, files: [])
32
43
  # puts "SqlRender#initialize"
33
44
  # puts " format: #{format.inspect}"
34
45
  # puts " ids: #{ids.inspect}"
@@ -36,10 +47,13 @@ module PgGraph::Data
36
47
  # puts " files: #{files.inspect}"
37
48
  constrain database, Database
38
49
  constrain ids, { String => Integer }
50
+ constrain ids.empty? || truncate == :none, true
51
+ constrain delete == :none || truncate == :none, true
39
52
  @database = database
40
53
  self.format = format
41
54
  (@ids = ids.dup).default = 0
42
55
  @delete = delete
56
+ @truncate = truncate
43
57
  @files = files
44
58
 
45
59
  @tables = database.schemas.map(&:tables).flatten.sort
@@ -71,7 +85,7 @@ module PgGraph::Data
71
85
  case format
72
86
  when :sql; to_a.join("\n")
73
87
  when :exec; to_a.join("\n")
74
- when :psql; to_psql(files).map { |group| group.join("\n") }.join("\n\n")
88
+ when :psql; to_psql(files).map { |group| group.join("\n") }.join("\n\n")
75
89
  end
76
90
  end
77
91
 
@@ -79,6 +93,7 @@ module PgGraph::Data
79
93
  @to_h ||= {
80
94
  disable: render_triggers(:disable),
81
95
  delete: render_deletes(delete),
96
+ truncate: render_truncates(truncate),
82
97
  update: render_updates,
83
98
  insert: render_inserts,
84
99
  restart: render_restart_sequences,
@@ -90,7 +105,11 @@ module PgGraph::Data
90
105
  protected
91
106
  # Returns a single-element array of array of SQL statements
92
107
  def to_sql
93
- [to_h[:delete] + to_h[:update] + to_h[:insert]]
108
+ if delete != :none
109
+ [to_h[:delete] + to_h[:update] + to_h[:insert]]
110
+ else
111
+ [to_h[:truncate] + to_h[:update] + to_h[:insert]]
112
+ end
94
113
  end
95
114
 
96
115
  # Returns an array of non-empty arrays of SQL statements
@@ -115,7 +134,7 @@ module PgGraph::Data
115
134
  ]
116
135
  end
117
136
 
118
- def render_begin()
137
+ def render_begin()
119
138
  [ "begin;" ]
120
139
  end
121
140
 
@@ -135,7 +154,7 @@ module PgGraph::Data
135
154
  end
136
155
 
137
156
  def render_deletes(kind)
138
- table_uids =
157
+ table_uids =
139
158
  case kind
140
159
  when :none; []
141
160
  when :touched; @tables.reject(&:empty?).map(&:uid)
@@ -146,6 +165,8 @@ module PgGraph::Data
146
165
  else
147
166
  raise ArgumentError
148
167
  end
168
+
169
+ # FIXME: Not in dependency order
149
170
  table_uids.map { |uid|
150
171
  if !@ids.key?(uid)
151
172
  "delete from #{uid};"
@@ -155,14 +176,38 @@ module PgGraph::Data
155
176
  }
156
177
  end
157
178
 
179
+ def render_truncates(kind)
180
+ table_uids =
181
+ case kind
182
+ when :none; []
183
+ when :touched; @tables.reject(&:empty?).map(&:uid)
184
+ when :all; @tables.map(&:uid)
185
+ else
186
+ raise ArgumentError
187
+ end
188
+ table_uids.map { |uid| "truncate #{uid} cascade;" }
189
+ end
190
+
158
191
  def render_updates
159
192
  @update_records.map { |record|
160
- "update #{record.table.uid} set " \
161
- + record.value_columns
162
- .select { |column| !column.type.primary_key? }
163
- .map { |column| "#{column.name} = #{render_value(column)}" }
164
- .join(", ") + " " \
165
- + "where id = #{record.id};"
193
+ # Temporary fix for the case where a kind field is updated. Kind fields
194
+ # are not considered value_columns (!) so kind fields are skipped in
195
+ # the original code below. FIXME FIXME FIXME
196
+ "update #{record.table.uid} set " +
197
+ record.to_h.keys
198
+ .map { |key| record[key] }
199
+ .reject { |column| column.type.primary_key? }
200
+ .map { |column|
201
+ "#{column.name} = #{render_value(column)}"
202
+ }.join(", ") + " " \
203
+ + "where id = #{record.id};"
204
+
205
+ # "update #{record.table.uid} set " \
206
+ # + record.value_columns
207
+ # .select { |column| !column.type.primary_key? }
208
+ # .map { |column| "#{column.name} = #{render_value(column)}" }
209
+ # .join(", ") + " " \
210
+ # + "where id = #{record.id};"
166
211
  }
167
212
  end
168
213
 
@@ -229,7 +274,7 @@ module PgGraph::Data
229
274
  end
230
275
  end
231
276
 
232
- def render_commit()
277
+ def render_commit()
233
278
  [ "commit;" ]
234
279
  end
235
280
  end
@@ -9,7 +9,7 @@ module PgGraph::Data
9
9
 
10
10
  # Fake class: RecordValue.new(table, records) simply returns the Record object
11
11
  class RecordValue < Value
12
- def self.new(table, records)
12
+ def self.new(table, records)
13
13
  constrain table, Table
14
14
  constrain records, [Record]
15
15
  records.first
@@ -50,7 +50,7 @@ module PgGraph::Data
50
50
  @impl = {}
51
51
  records.each { |record| (@impl[record.id] ||= []) << record }
52
52
  end
53
-
53
+
54
54
  # Number of records including duplicates
55
55
  def size() records.size end
56
56
 
@@ -10,7 +10,7 @@ module PgGraph
10
10
  # Template for 'this' field name. Can be nil
11
11
  attr_reader :this
12
12
 
13
- # Template for 'that' field name or false if the field shouldn't be
13
+ # Template for 'that' field name or false if the field should not be
14
14
  # included in the model. Can be nil
15
15
  attr_reader :that
16
16
 
@@ -30,7 +30,7 @@ module PgGraph
30
30
  attr_reader :pluralize
31
31
 
32
32
  # RE corresponding to #match. #re always match a full UID
33
- attr_reader :re
33
+ attr_reader :re
34
34
 
35
35
  # Number of name components (database, schema, table, column). It can be
36
36
  # between one and four. By ordering reflections from highest to lowest
@@ -67,9 +67,9 @@ module PgGraph
67
67
  end
68
68
 
69
69
  def to_yaml
70
- {
71
- match: match, this: this, that: that, multi: multi, pluralize: pluralize,
72
- default_reflection: default_reflection
70
+ {
71
+ match: match, this: this, that: that, multi: multi, pluralize: pluralize,
72
+ default_reflection: default_reflection
73
73
  }
74
74
  end
75
75
 
@@ -82,8 +82,8 @@ module PgGraph
82
82
  # +hash+ has the keys :match, :this, :that, and :pluralize. The keys can
83
83
  # also be strings
84
84
  def self.load_yaml(hash)
85
- Reflection.new *METHODS.map { |key|
86
- value = hash[key].nil? ? hash[key.to_s] : hash[key]
85
+ Reflection.new *METHODS.map { |key|
86
+ value = hash[key].nil? ? hash[key.to_s] : hash[key]
87
87
  value == "nil" ? nil : value
88
88
  }
89
89
  end
@@ -117,7 +117,7 @@ module PgGraph
117
117
  def dup() Reflector.new(reflections.dup) end
118
118
 
119
119
  # Return true if the Reflector has no reflections
120
- def empty?()
120
+ def empty?()
121
121
  @reflection_list ? reflections.empty? : !@reflections.values.all?(:empty?)
122
122
  end
123
123
 
@@ -126,8 +126,8 @@ module PgGraph
126
126
  def add(*reflections)
127
127
  @reflection_list = nil
128
128
  # reverse makes it possible to use #insert but keep order:
129
- Array(reflections).flatten.reverse.each { |reflection|
130
- @reflections[reflection.components].insert(0, reflection)
129
+ Array(reflections).flatten.reverse.each { |reflection|
130
+ @reflections[reflection.components].insert(0, reflection)
131
131
  }
132
132
  end
133
133
 
@@ -193,14 +193,14 @@ module PgGraph
193
193
  table ||= REFLECTIONS_TABLE
194
194
  self.class.ensure_table(conn, schema, table)
195
195
  values = reflections.select { |r| !r.default_reflection }.map.with_index { |reflection, i|
196
- values = "(" + Reflection::METHODS.map { |m|
196
+ values = "(" + Reflection::METHODS.map { |m|
197
197
  v = reflection.send(m)
198
198
  v.nil? ? "null" : "'#{v}'"
199
199
  }.join(", ") + ", #{i})"
200
200
  }.join(",\n")
201
201
 
202
202
  conn.exec %(
203
- insert into #{schema}.#{table}
203
+ insert into #{schema}.#{table}
204
204
  (match, this, that, multi, pluralize, default_reflection, ordinal)
205
205
  values
206
206
  #{values}
@@ -215,14 +215,14 @@ module PgGraph
215
215
  {"match"=>"/parent_(\\w+)_id/", "that"=>"child_$1"},
216
216
  {"match"=>"/child_(\\w+)_id/", "that"=>"parent_$1"},
217
217
  {"match"=>"kind", "this"=>"kind", "that"=>"$$"},
218
- {"match"=>"/(\\w+)_kind/", "this"=>"$1", "that"=>"$$"},
218
+ {"match"=>"/(\\w+)_kind/", "this"=>"$1", "that"=>"$$"},
219
219
  {"match"=>"/(\\w+)_by_id/", "this"=>"$1_by", "that"=>"$1_$$", pluralize: true},
220
220
  {"match"=>"/(\\w+)_id/", "this"=>"$1", "that"=>"$$", multi: false},
221
221
  {"match"=>"/(\\w+)_id/", "this"=>"$1", "that"=>"$1_of", multi: true, pluralize: false},
222
222
  {"match"=>"/(\\w+)/", "this"=>"$1", "that"=>"$$"}, # Kind fields w/o explicit 'kind'
223
223
  ]
224
- initializers.map { |initializer|
225
- Reflection.load_yaml initializer.merge(default_reflection: true)
224
+ initializers.map { |initializer|
225
+ Reflection.load_yaml initializer.merge(default_reflection: true)
226
226
  }
227
227
  end
228
228
  end
@@ -7,7 +7,7 @@ module PgGraph::Type
7
7
  # Array of [record, meta_column] tuples
8
8
  field_columns = []
9
9
  link_columns = []
10
- kind_columns = [] # The link side
10
+ kind_columns = [] # The link side
11
11
  id_link_columns = [] # sub tables
12
12
 
13
13
  # Temporary arrays of meta tables
@@ -21,7 +21,7 @@ module PgGraph::Type
21
21
  meta_schema.tables.values.select { |t| t.table? }.each { |meta_table| # FIXME Ignore views for now
22
22
  (meta_table.mm_table? ? mm_tables : tables) << meta_table
23
23
  table = Table.new(
24
- schema, meta_table.name,
24
+ schema, meta_table.name,
25
25
  mm_table: meta_table.mm_table?,
26
26
  depending_materialized_views: meta_table.depending_views.select(&:materialized?))
27
27
  record_type = RecordType.new(table)
@@ -32,7 +32,7 @@ module PgGraph::Type
32
32
  # Create basic types needed by columns
33
33
  type_name = meta_column.type
34
34
  if !schema.key?(type_name) && !catalog.key?(type_name)
35
- if meta_column.array?
35
+ if meta_column.array?
36
36
  element_name = meta_column.element_type
37
37
  dimensions = meta_column.dimensions
38
38
  if !schema.key?(element_name) && !catalog.key?(element_name)
@@ -51,7 +51,7 @@ module PgGraph::Type
51
51
  if meta_column.name == "id"
52
52
  id_link_columns
53
53
  elsif meta_column.name =~ /^(?:.*_)?kind$/
54
- kind_columns
54
+ kind_columns
55
55
  else
56
56
  link_columns
57
57
  end
@@ -76,7 +76,7 @@ module PgGraph::Type
76
76
  next if meta_column.kind?
77
77
  type = record_type.schema[meta_column.type] || catalog[meta_column.type]
78
78
  SimpleColumn.new(
79
- record_type, meta_column.name, meta_column.name, type,
79
+ record_type, meta_column.name, meta_column.name, type,
80
80
  ordinal: meta_column.ordinal,
81
81
  **column_options(meta_column))
82
82
  }
@@ -104,7 +104,7 @@ module PgGraph::Type
104
104
  (reference_count[record_type] ||= {})[type] ||= 0
105
105
  reference_count[record_type][type] += 1 if reflector.multi?(this_link_column)
106
106
 
107
- field =
107
+ field =
108
108
  if meta_column.kind?
109
109
  name = reflector.this(meta_column.uid) || meta_column.name
110
110
  name = meta_column.name if record_type[name] # Check for duplicates
@@ -171,7 +171,7 @@ module PgGraph::Type
171
171
  # Create back-references
172
172
  if this_column.unique?
173
173
  RecordColumn.new(
174
- that_record_type, name, nil, this_record_type,
174
+ that_record_type, name, nil, this_record_type,
175
175
  this_column.that_link_column, this_column.this_link_column)
176
176
  else
177
177
  TableColumn.new(that_record_type, name, this_table.type,
@@ -237,7 +237,7 @@ module PgGraph::Type
237
237
  if table1.type.record_type.key?(column1_name)
238
238
  raise Error, "Duplicate column name in #{table1.identifier}: #{column1_name}"
239
239
  end
240
-
240
+
241
241
  if table2.type.record_type.key?(column2_name)
242
242
  raise Error, "Duplicate column name in #{table2.identifier}: #{column2_name}"
243
243
  end
@@ -1,7 +1,7 @@
1
1
 
2
2
  module PgGraph::Type
3
3
  class Error < StandardError; end
4
-
4
+
5
5
  class Node < HashTree::Set
6
6
  include Constrain
7
7
 
@@ -16,7 +16,7 @@ module PgGraph::Type
16
16
  # The full Ruby model identifier of the object within a database. It
17
17
  # corresponds to #uid
18
18
  def schema_identifier() identifier end
19
-
19
+
20
20
  # :call-seq: initialize(database, name, attach: true)
21
21
  def initialize(parent, name, **opts)
22
22
  constrain parent, Node, NilClass
@@ -24,8 +24,8 @@ module PgGraph::Type
24
24
  super
25
25
  end
26
26
 
27
- def inspect(payload = inspect_inner)
28
- "#<#{self.class}:#{name.inspect}#{payload ? " #{payload}" : ""}>"
27
+ def inspect(payload = inspect_inner)
28
+ "#<#{self.class}:#{name.inspect}#{payload ? " #{payload}" : ""}>"
29
29
  end
30
30
 
31
31
  def inspect_inner() nil end
@@ -33,9 +33,9 @@ module PgGraph::Type
33
33
  protected
34
34
  # Nodes with nil keys are not attached. This is used in PgCatalogSchema to
35
35
  # avoid being included in the list of schemas
36
- def do_attach(key, child)
36
+ def do_attach(key, child)
37
37
  !key?(key) or raise PgGraph::Error, "Duplicate fields in #{self.uid}: '#{key}'"
38
- super if child
38
+ super if child
39
39
  end
40
40
 
41
41
  # Forward list of methods to object. The arguments should be strings or symbols
@@ -48,7 +48,7 @@ module PgGraph::Type
48
48
 
49
49
  # Included by tables, records, and fields
50
50
  module TableObject
51
- # Circular definitions. Classes that include TableObject should redefine at least
51
+ # Circular definitions. Classes that include TableObject should redefine at least
52
52
  # one of the methods to break the loop
53
53
  def table() record_type.table end
54
54
  def table_type() table.type end
@@ -95,7 +95,7 @@ module PgGraph::Type
95
95
  @reflector = reflector || @reflector
96
96
  case arg
97
97
  # #read_meta is a member of Database but defined in read.rb
98
- when PgMeta; read_meta(arg, ignore: ignore)
98
+ when PgMeta; read_meta(arg, ignore: ignore)
99
99
  when PgConn; read_meta(PgMeta.new(arg), ignore: ignore)
100
100
  end
101
101
  end
@@ -282,12 +282,12 @@ module PgGraph::Type
282
282
  end
283
283
 
284
284
  # List of postgres columns. The columns are sorted by ordinal
285
- def columns()
285
+ def columns()
286
286
  @columns ||= begin
287
287
  cols = fields.map { |field|
288
288
  case field
289
289
  when SimpleColumn; field
290
- when KindRecordColumn;
290
+ when KindRecordColumn;
291
291
  if field.kind_column&.parent
292
292
  nil
293
293
  else
@@ -308,7 +308,7 @@ module PgGraph::Type
308
308
  cols = fields.map { |field|
309
309
  case field
310
310
  when SimpleColumn; field
311
- when KindRecordColumn;
311
+ when KindRecordColumn;
312
312
  if field.kind_column&.parent
313
313
  nil
314
314
  else
@@ -324,7 +324,7 @@ module PgGraph::Type
324
324
  end
325
325
 
326
326
  # TODO: Rename #columns to #postgres_columns and #abstract_columns to #columns
327
- def abstract_columns
327
+ def abstract_columns
328
328
  @abstract_columns ||= fields.map { |field|
329
329
  case field
330
330
  when SimpleColumn; field
@@ -334,19 +334,19 @@ module PgGraph::Type
334
334
  nil
335
335
  end
336
336
  }.compact.sort_by(&:ordinal)
337
-
337
+
338
338
  end
339
339
 
340
340
  # List of columns excluding generated fields
341
- def value_columns()
341
+ def value_columns()
342
342
  columns.select { |column| !column.generated? }
343
343
  end
344
344
 
345
345
  # True iff name if the name of a postgres column
346
346
  # def column?(name) self[name].is_a?(SimpleColumn) end
347
- def column?(name)
347
+ def column?(name)
348
348
  raise "See the rename TODO above"
349
- @columns_hash.key?(name)
349
+ @columns_hash.key?(name)
350
350
  end
351
351
 
352
352
  end
@@ -439,7 +439,7 @@ module PgGraph::Type
439
439
  def primary_key?() @postgres_column && @primary_key end
440
440
 
441
441
  # Return true/false or nil if postgres_column is an identity column.
442
- # Sub-keys are primary keys but not identity keys
442
+ # Sub-keys are primary keys but not identity keys
443
443
  def identity?() @postgres_column && @identity end
444
444
 
445
445
  # Return true/false or nil
@@ -462,8 +462,8 @@ module PgGraph::Type
462
462
 
463
463
  protected
464
464
  def initialize(
465
- record_type, name, postgres_column, type,
466
- primary_key: false, identity: false,
465
+ record_type, name, postgres_column, type,
466
+ primary_key: false, identity: false,
467
467
  reference: false, kind: false,
468
468
  nullable: true, unique: false, readonly: false, generated: false)
469
469
  constrain record_type, RecordType, NilClass
@@ -531,8 +531,8 @@ module PgGraph::Type
531
531
  forward_method :kind_column, :literal?
532
532
 
533
533
  def initialize(
534
- record_type, name, postgres_column, type,
535
- this_link_column, that_link_column,
534
+ record_type, name, postgres_column, type,
535
+ this_link_column, that_link_column,
536
536
  kind_column, **opts)
537
537
  constrain kind_column, SimpleColumn
538
538
  super(record_type, name, postgres_column, type, this_link_column, that_link_column, kind: true, **opts)
@@ -1,3 +1,3 @@
1
1
  module PgGraph
2
- VERSION = "0.4.2"
2
+ VERSION = "0.5.1"
3
3
  end
data/lib/pg_graph.rb CHANGED
@@ -53,12 +53,12 @@ module PgGraph
53
53
  def self.new(arg, reflections = nil, schema = nil, ignore: [])
54
54
  constrain arg, PgMeta, PgConn
55
55
  constrain reflections, Reflector, Array, String, PgConn, NilClass
56
- meta =
56
+ meta =
57
57
  case arg
58
58
  when PgMeta; arg
59
59
  when PgConn; PgMeta.new(arg)
60
60
  end
61
- reflector =
61
+ reflector =
62
62
  case reflections
63
63
  when Reflector; reflections
64
64
  when Array; Reflector.load_yaml(reflections)
@@ -78,7 +78,7 @@ module PgGraph
78
78
  # instantiate(hash)
79
79
  # instantiate(yaml)
80
80
  # instantiate(pg_conn)
81
- #
81
+ #
82
82
  def instantiate(arg = nil)
83
83
  constrain arg, NilClass, Hash, PgConn
84
84
  Data.new(self, arg)
@@ -94,7 +94,7 @@ module PgGraph
94
94
  # new(type, hash = {})
95
95
  # new(type, yaml = {})
96
96
  # new(type, pg_conn = nil)
97
- #
97
+ #
98
98
  # Note that together with ::=== and Data::Database#is_a? this makes
99
99
  # Data::Database pretend it is an instance of the Data module
100
100
  def self.new(type, arg)
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg_graph
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.5.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Claus Rasmussen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-04-20 00:00:00.000000000 Z
11
+ date: 2024-07-24 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: boolean