pg_graph 0.1.3 → 0.1.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 +4 -4
- data/exe/pg_graph +39 -6
- data/lib/pg_graph/reflector.rb +71 -5
- data/lib/pg_graph/version.rb +1 -1
- data/lib/pg_graph.rb +12 -9
- data/lib/type/type.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ea523768bdb76ecb1e4d8a8cee3d1b4afbad3e5735964acf63f78d5152050cf5
|
4
|
+
data.tar.gz: a29f1abbbdb5b674090a503c9db9ab0357140035b2c5af62a07352d38d5f3009
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: ad4d4f581462c3b982d7e7504a6277e7585e1d422974a6058ca9ba54c4e30ed48ba5ba38e88504d449caa8690c7664a46366187e2ceab7e19a2f8f26abb944ac
|
7
|
+
data.tar.gz: fff6a163e030d2dfd1187c07e6e69d0da9dbef18b4c0ef2fda393dfe7f9725e61c21f47febed69199b553b17f0285f16c30951e623e0143f0dd37d302228fd8b
|
data/exe/pg_graph
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
#!/usr/bin/env ruby
|
2
2
|
|
3
|
+
#$LOAD_PATH.unshift "/home/clr/prj/shellopts/lib"
|
4
|
+
|
3
5
|
require 'shellopts'
|
4
6
|
require 'pg_graph.rb'
|
5
7
|
require "pg_graph/timer.rb"
|
@@ -32,9 +34,23 @@ SPEC = %(
|
|
32
34
|
Make pg_graph loads its meta data from a marshalled PgMeta object instead
|
33
35
|
of quering the database
|
34
36
|
|
37
|
+
+i,ignore=SCHEMA
|
38
|
+
Exclude objects in the given schema. This option can be repeated
|
39
|
+
|
35
40
|
-r,reflections=EFILE
|
36
41
|
Load reflections from FILE
|
37
42
|
|
43
|
+
-t,reflections-table=TABLE_UID?
|
44
|
+
Read/write reflections in the given table. The table argument can be both a
|
45
|
+
full UID (eg. "my_schema.my_reflections") or just a table name in the public
|
46
|
+
schema. Default is "public.reflections". The table and schema is created
|
47
|
+
if not present.
|
48
|
+
|
49
|
+
If this option is used together with the --reflections option, the
|
50
|
+
reflections are read from th e given file and written back to the database.
|
51
|
+
If both options are missing, pg_graph will look for the default table and
|
52
|
+
load it if present
|
53
|
+
|
38
54
|
-f,format=FORMAT:sql,exec,psql,yaml
|
39
55
|
Input/output format. Can be one of 'sql', 'exec', 'psql', or 'yaml' (default)
|
40
56
|
|
@@ -50,7 +66,7 @@ SPEC = %(
|
|
50
66
|
-k,kind=KIND:meta,type,data
|
51
67
|
Output kind. Can be one of 'meta', 'type' (the default), or 'data'
|
52
68
|
|
53
|
-
|
69
|
+
--time
|
54
70
|
Emit timings for process
|
55
71
|
|
56
72
|
load! -- DATABASE [FILE]
|
@@ -70,21 +86,38 @@ SPEC = %(
|
|
70
86
|
#
|
71
87
|
def load_type(timer, opts, database)
|
72
88
|
tg = timer.group("initialization")
|
73
|
-
|
89
|
+
conn = tg.time("connect") { PgConn.new(database) if !opts.meta? && !opts.marshal? }
|
74
90
|
meta = tg.time("meta") {
|
75
91
|
if opts.meta?
|
76
92
|
PgMeta.load_file(opts.meta)
|
77
93
|
elsif opts.marshal?
|
78
94
|
PgMeta.load_marshal(opts.marshal)
|
79
95
|
else
|
80
|
-
PgMeta.new(
|
96
|
+
PgMeta.new(conn)
|
81
97
|
end
|
82
98
|
}
|
83
99
|
reflector = tg.time("reflector") {
|
84
|
-
|
100
|
+
table, schema = opts.reflections_table&.split(".")&.reverse
|
101
|
+
schema ||= PgGraph::Reflector::REFLECTIONS_SCHEMA
|
102
|
+
table ||= PgGraph::Reflector::REFLECTIONS_TABLE
|
103
|
+
|
104
|
+
if opts.reflections?
|
105
|
+
r = PgGraph::Reflector.load_file(opts.reflections)
|
106
|
+
r.save_table(conn, schema, table) if opts.reflections_table?
|
107
|
+
r
|
108
|
+
else
|
109
|
+
if opts.reflections_table?
|
110
|
+
PgGraph::Reflector.load_table(conn, schema, table)
|
111
|
+
elsif conn.schema.exist_table?(schema, table)
|
112
|
+
PgGraph::Reflector.load_table(conn, schema, table)
|
113
|
+
else
|
114
|
+
nil
|
115
|
+
end
|
116
|
+
end
|
85
117
|
}
|
86
|
-
|
87
|
-
|
118
|
+
|
119
|
+
type = timer.time("type") { PgGraph::Type.new(meta, reflector, ignore: opts.ignore) }
|
120
|
+
[conn, type]
|
88
121
|
end
|
89
122
|
|
90
123
|
opts, args = ShellOpts::ShellOpts.process(SPEC, ARGV)
|
data/lib/pg_graph/reflector.rb
CHANGED
@@ -26,12 +26,16 @@ module PgGraph
|
|
26
26
|
# matches
|
27
27
|
attr_reader :components
|
28
28
|
|
29
|
+
# True if this is a default reflection
|
30
|
+
attr_reader :default_reflection
|
31
|
+
|
29
32
|
# +this+ and +that+ are template strings, nil, or false
|
30
|
-
def initialize(match, this, that, pluralize = false)
|
33
|
+
def initialize(match, this, that, pluralize = false, default_reflection = false)
|
31
34
|
constrain match, Regexp, String
|
32
35
|
constrain this, String, NilClass
|
33
36
|
constrain that, String, FalseClass, NilClass
|
34
37
|
constrain pluralize, TrueClass, FalseClass, NilClass
|
38
|
+
constrain default_reflection, TrueClass, FalseClass, NilClass
|
35
39
|
@match = match.is_a?(Regexp) ? match.source : match
|
36
40
|
if @match =~ /^\/(.*)\/$/
|
37
41
|
re = $1
|
@@ -45,10 +49,11 @@ module PgGraph
|
|
45
49
|
@this = this
|
46
50
|
@that = that
|
47
51
|
@pluralize = pluralize || pluralize.nil?
|
52
|
+
@default_reflection = default_reflection || false
|
48
53
|
end
|
49
54
|
|
50
55
|
def to_yaml
|
51
|
-
{ match: match, this: this, that: that, pluralize: pluralize }
|
56
|
+
{ match: match, this: this, that: that, pluralize: pluralize, default_reflection: default_reflection }
|
52
57
|
end
|
53
58
|
|
54
59
|
def ==(other)
|
@@ -66,11 +71,13 @@ module PgGraph
|
|
66
71
|
}
|
67
72
|
end
|
68
73
|
|
69
|
-
|
70
|
-
METHODS = %w(match this that pluralize).map(&:to_sym)
|
74
|
+
METHODS = %w(match this that pluralize default_reflection).map(&:to_sym)
|
71
75
|
end
|
72
76
|
|
73
77
|
class Reflector
|
78
|
+
REFLECTIONS_SCHEMA = "public"
|
79
|
+
REFLECTIONS_TABLE = "reflections"
|
80
|
+
|
74
81
|
# Reflections ordered from most-specific to least-specific and newest to oldest
|
75
82
|
def reflections()
|
76
83
|
# assumes @reflection keys are created in descending order
|
@@ -140,6 +147,40 @@ module PgGraph
|
|
140
147
|
load_yaml YAML.load(IO.read(file)), default_reflections: default_reflections
|
141
148
|
end
|
142
149
|
|
150
|
+
def self.load_table(conn, schema = nil, table = nil, default_reflections: Reflector.default_reflections)
|
151
|
+
schema ||= REFLECTIONS_SCHEMA
|
152
|
+
table ||= REFLECTIONS_TABLE
|
153
|
+
if conn.schema.exist?(schema) && conn.schema.exist_table?(schema, table)
|
154
|
+
yaml = conn.structs(%(
|
155
|
+
select match, this, that, pluralize, false as "default_reflection"
|
156
|
+
from #{schema}.#{table}
|
157
|
+
order by ordinal
|
158
|
+
)).map(&:to_h)
|
159
|
+
else
|
160
|
+
yaml = {}
|
161
|
+
end
|
162
|
+
load_yaml yaml, default_reflections: default_reflections
|
163
|
+
end
|
164
|
+
|
165
|
+
def save_table(conn, schema = nil, table = nil)
|
166
|
+
schema ||= REFLECTIONS_SCHEMA
|
167
|
+
table ||= REFLECTIONS_TABLE
|
168
|
+
self.class.ensure_table(conn, schema, table)
|
169
|
+
values = reflections.select { |r| !r.default_reflection }.map.with_index { |reflection, i|
|
170
|
+
values = "(" + Reflection::METHODS.map { |m|
|
171
|
+
v = reflection.send(m)
|
172
|
+
v.nil? ? "null" : "'#{v}'"
|
173
|
+
}.join(", ") + ", #{i})"
|
174
|
+
}.join(",\n")
|
175
|
+
|
176
|
+
conn.exec %(
|
177
|
+
insert into #{schema}.#{table}
|
178
|
+
(match, this, that, pluralize, default_reflection, ordinal)
|
179
|
+
values
|
180
|
+
#{values}
|
181
|
+
)
|
182
|
+
end
|
183
|
+
|
143
184
|
def self.default_reflections
|
144
185
|
@default_reflections ||= begin
|
145
186
|
initializers = [
|
@@ -153,7 +194,9 @@ module PgGraph
|
|
153
194
|
{"match"=>"/(\\w+)_id/", "this"=>"$1", "that"=>"$$"},
|
154
195
|
{"match"=>"/(\\w+)/", "this"=>"$1", "that"=>"$$"}, # Kind fields w/o explicit 'kind'
|
155
196
|
]
|
156
|
-
initializers.map { |initializer|
|
197
|
+
initializers.map { |initializer|
|
198
|
+
Reflection.load_yaml initializer.merge(default_reflection: true)
|
199
|
+
}
|
157
200
|
end
|
158
201
|
end
|
159
202
|
|
@@ -179,6 +222,29 @@ module PgGraph
|
|
179
222
|
end
|
180
223
|
}
|
181
224
|
end
|
225
|
+
|
226
|
+
def self.create_table(conn, schema, table)
|
227
|
+
conn.exec %(
|
228
|
+
create table #{schema}.#{table} (
|
229
|
+
id integer generated by default as identity primary key,
|
230
|
+
match varchar not null,
|
231
|
+
this varchar,
|
232
|
+
that varchar not null,
|
233
|
+
pluralize boolean not null,
|
234
|
+
default_reflection boolean not null,
|
235
|
+
ordinal integer not null -- zero-based
|
236
|
+
)
|
237
|
+
)
|
238
|
+
end
|
239
|
+
|
240
|
+
def self.ensure_table(conn, schema, table)
|
241
|
+
conn.schema.create(schema) if !conn.schema.exist?(schema)
|
242
|
+
if conn.schema.exist_table?(schema, table)
|
243
|
+
conn.exec "truncate #{schema}.#{table}"
|
244
|
+
else
|
245
|
+
create_table(conn, schema, table)
|
246
|
+
end
|
247
|
+
end
|
182
248
|
end
|
183
249
|
end
|
184
250
|
|
data/lib/pg_graph/version.rb
CHANGED
data/lib/pg_graph.rb
CHANGED
@@ -39,26 +39,29 @@ module PgGraph
|
|
39
39
|
# new(meta, reflect = nil)
|
40
40
|
# new(pg_conn, reflect = nil)
|
41
41
|
#
|
42
|
-
# The +
|
43
|
-
# name or nil.
|
44
|
-
#
|
42
|
+
# The +reflections+ argument can be a Reflector object, an yaml array, a
|
43
|
+
# file name, a PgConn object, or nil. If +reflections+ is a PgConn object,
|
44
|
+
# the +schema+ argument should be set to the schema containing the
|
45
|
+
# 'reflections' table. The +ignore+ option is a list of schema names to
|
46
|
+
# exclude from the type system
|
45
47
|
#
|
46
48
|
# Note that together with ::=== and Database#is_a? this makes
|
47
49
|
# Type::Database pretend it is an instance of the Type module
|
48
50
|
#
|
49
|
-
def self.new(arg,
|
51
|
+
def self.new(arg, reflections = nil, schema = nil, ignore: [])
|
50
52
|
constrain arg, PgMeta, PgConn
|
51
|
-
constrain
|
53
|
+
constrain reflections, Reflector, Array, String, PgConn, NilClass
|
52
54
|
meta =
|
53
55
|
case arg
|
54
56
|
when PgMeta; arg
|
55
57
|
when PgConn; PgMeta.new(arg)
|
56
58
|
end
|
57
59
|
reflector =
|
58
|
-
case
|
59
|
-
when Reflector;
|
60
|
-
when Array; Reflector.load_yaml(
|
61
|
-
when String; Reflector.load_file(
|
60
|
+
case reflections
|
61
|
+
when Reflector; reflections
|
62
|
+
when Array; Reflector.load_yaml(reflections)
|
63
|
+
when String; Reflector.load_file(reflections)
|
64
|
+
when PgConn; Reflector.load_table(reflections, schema)
|
62
65
|
when NilClass; Reflector.new
|
63
66
|
end
|
64
67
|
Database.new(meta.name, reflector).read(meta, ignore: ignore)
|
data/lib/type/type.rb
CHANGED
@@ -173,7 +173,7 @@ module PgGraph::Type
|
|
173
173
|
def initialize(
|
174
174
|
schema, name,
|
175
175
|
mm_table: false, nm_table: false, depending_materialized_views: [])
|
176
|
-
PgGraph.inflector.plural?(name) or raise Error, "Table names should be plural: #{name
|
176
|
+
PgGraph.inflector.plural?(name) or raise Error, "Table names should be plural: #{schema.name}.#{name}"
|
177
177
|
super(schema, name)
|
178
178
|
@path = "#{schema.name}.#{name}"
|
179
179
|
@mm_table = mm_table || nm_table
|
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.1.
|
4
|
+
version: 0.1.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Claus Rasmussen
|
8
8
|
autorequire:
|
9
9
|
bindir: exe
|
10
10
|
cert_chain: []
|
11
|
-
date: 2022-04-
|
11
|
+
date: 2022-04-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: boolean
|