pg_objects 1.2.0 → 1.2.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 7020b30da04ae39e82f938692675d38dd4b65c8d0e354be2fc5198c726e41608
4
- data.tar.gz: d436471478f54272dc91ee41f0a0d72571f54fb1eb4d886c7b3d881b5aea6bd5
3
+ metadata.gz: 91c7eb71d09850bc60f89da023336a3b23da1032b708edd25d6d7c4c36cda48a
4
+ data.tar.gz: 68b0c1d67c6f8954b385bb92d9e56b4e9f26d493aeaa7ce436f853415d5df016
5
5
  SHA512:
6
- metadata.gz: 70c31c6788728cf943e6973ee4aaa9fe34238613bf1d07f6fa7b7de020fcb96de0deccdb79d0c79c1cf20c399039171a16c8a2f7125d44934da5106af10f66e3
7
- data.tar.gz: b4f122ce4aaead24702761ac44d8330f63e3daaac85448aef6dc8c14295ec3f6658731934db48c39eebbcef4e27d1bffde0edb137876820df38558fe5e10c3ce
6
+ metadata.gz: 58455882d344d4dff87af1855313bb2cf534408a43d8ead7c98d5eaf726cdd5d7c53576d066d018ea51932281bd7d4c38f716b21fb3a276cc859d074fc83ffd4
7
+ data.tar.gz: 74199983303ce4ef51a41c2131c5f70e384e1ebeeb730681ed8458fe8fa24da481e6240ca6efad0a18350ae9428aae06d4f884f314e0dd27cecea03116292ad1
data/Gemfile CHANGED
@@ -5,6 +5,7 @@ gemspec
5
5
  group :development, :test do
6
6
  gem 'bundler', require: false
7
7
  gem 'bundler-audit', require: false
8
+ gem 'faker', require: false
8
9
  gem 'pry-byebug'
9
10
  gem 'rake', require: false
10
11
  gem 'rspec', require: false
data/Gemfile.lock CHANGED
@@ -1,8 +1,13 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- pg_objects (1.2.0)
4
+ pg_objects (1.2.1)
5
5
  activerecord (>= 6.1.7.0, < 8)
6
+ dry-auto_inject (~> 1)
7
+ dry-configurable (~> 1)
8
+ dry-container (= 0.11.0)
9
+ dry-monads (~> 1.6)
10
+ memery (~> 1.5.0)
6
11
  pg_query (~> 5)
7
12
  railties (>= 4, < 8)
8
13
  rake-hooks (~> 1)
@@ -10,9 +15,9 @@ PATH
10
15
  GEM
11
16
  remote: https://rubygems.org/
12
17
  specs:
13
- actionpack (7.1.3.2)
14
- actionview (= 7.1.3.2)
15
- activesupport (= 7.1.3.2)
18
+ actionpack (7.1.3.4)
19
+ actionview (= 7.1.3.4)
20
+ activesupport (= 7.1.3.4)
16
21
  nokogiri (>= 1.8.5)
17
22
  racc
18
23
  rack (>= 2.2.4)
@@ -20,19 +25,19 @@ GEM
20
25
  rack-test (>= 0.6.3)
21
26
  rails-dom-testing (~> 2.2)
22
27
  rails-html-sanitizer (~> 1.6)
23
- actionview (7.1.3.2)
24
- activesupport (= 7.1.3.2)
28
+ actionview (7.1.3.4)
29
+ activesupport (= 7.1.3.4)
25
30
  builder (~> 3.1)
26
31
  erubi (~> 1.11)
27
32
  rails-dom-testing (~> 2.2)
28
33
  rails-html-sanitizer (~> 1.6)
29
- activemodel (7.1.3.2)
30
- activesupport (= 7.1.3.2)
31
- activerecord (7.1.3.2)
32
- activemodel (= 7.1.3.2)
33
- activesupport (= 7.1.3.2)
34
+ activemodel (7.1.3.4)
35
+ activesupport (= 7.1.3.4)
36
+ activerecord (7.1.3.4)
37
+ activemodel (= 7.1.3.4)
38
+ activesupport (= 7.1.3.4)
34
39
  timeout (>= 0.4.0)
35
- activesupport (7.1.3.2)
40
+ activesupport (7.1.3.4)
36
41
  base64
37
42
  bigdecimal
38
43
  concurrent-ruby (~> 1.0, >= 1.0.2)
@@ -44,57 +49,75 @@ GEM
44
49
  tzinfo (~> 2.0)
45
50
  ast (2.4.2)
46
51
  base64 (0.2.0)
47
- bigdecimal (3.1.6)
48
- binding_of_caller (1.0.0)
49
- debug_inspector (>= 0.0.1)
52
+ bigdecimal (3.1.8)
53
+ binding_of_caller (1.0.1)
54
+ debug_inspector (>= 1.2.0)
50
55
  builder (3.2.4)
51
56
  bundler-audit (0.9.1)
52
57
  bundler (>= 1.2.0, < 3)
53
58
  thor (~> 1.0)
54
59
  byebug (11.1.3)
55
60
  coderay (1.1.3)
56
- concurrent-ruby (1.2.3)
61
+ concurrent-ruby (1.3.1)
57
62
  connection_pool (2.4.1)
58
63
  crass (1.0.6)
59
64
  debug_inspector (1.2.0)
60
65
  diff-lcs (1.5.1)
61
- drb (2.2.0)
62
- ruby2_keywords
66
+ drb (2.2.1)
67
+ dry-auto_inject (1.0.1)
68
+ dry-core (~> 1.0)
69
+ zeitwerk (~> 2.6)
70
+ dry-configurable (1.1.0)
71
+ dry-core (~> 1.0, < 2)
72
+ zeitwerk (~> 2.6)
73
+ dry-container (0.11.0)
74
+ concurrent-ruby (~> 1.0)
75
+ dry-core (1.0.1)
76
+ concurrent-ruby (~> 1.0)
77
+ zeitwerk (~> 2.6)
78
+ dry-monads (1.6.0)
79
+ concurrent-ruby (~> 1.0)
80
+ dry-core (~> 1.0, < 2)
81
+ zeitwerk (~> 2.6)
63
82
  erubi (1.12.0)
83
+ faker (3.4.1)
84
+ i18n (>= 1.8.11, < 2)
64
85
  google-protobuf (3.25.3)
65
86
  google-protobuf (3.25.3-aarch64-linux)
66
87
  google-protobuf (3.25.3-arm64-darwin)
67
88
  google-protobuf (3.25.3-x86-linux)
68
89
  google-protobuf (3.25.3-x86_64-darwin)
69
90
  google-protobuf (3.25.3-x86_64-linux)
70
- i18n (1.14.1)
91
+ i18n (1.14.5)
71
92
  concurrent-ruby (~> 1.0)
72
93
  io-console (0.7.2)
73
- irb (1.11.2)
74
- rdoc
94
+ irb (1.13.1)
95
+ rdoc (>= 4.0.0)
75
96
  reline (>= 0.4.2)
76
- json (2.7.1)
97
+ json (2.7.2)
77
98
  language_server-protocol (3.17.0.3)
78
99
  loofah (2.22.0)
79
100
  crass (~> 1.0.2)
80
101
  nokogiri (>= 1.12.0)
102
+ memery (1.5.0)
103
+ ruby2_keywords (~> 0.0.2)
81
104
  method_source (1.0.0)
82
- minitest (5.22.2)
105
+ minitest (5.23.1)
83
106
  mutex_m (0.2.0)
84
- nokogiri (1.16.2-aarch64-linux)
107
+ nokogiri (1.16.5-aarch64-linux)
85
108
  racc (~> 1.4)
86
- nokogiri (1.16.2-arm-linux)
109
+ nokogiri (1.16.5-arm-linux)
87
110
  racc (~> 1.4)
88
- nokogiri (1.16.2-arm64-darwin)
111
+ nokogiri (1.16.5-arm64-darwin)
89
112
  racc (~> 1.4)
90
- nokogiri (1.16.2-x86-linux)
113
+ nokogiri (1.16.5-x86-linux)
91
114
  racc (~> 1.4)
92
- nokogiri (1.16.2-x86_64-darwin)
115
+ nokogiri (1.16.5-x86_64-darwin)
93
116
  racc (~> 1.4)
94
- nokogiri (1.16.2-x86_64-linux)
117
+ nokogiri (1.16.5-x86_64-linux)
95
118
  racc (~> 1.4)
96
119
  parallel (1.24.0)
97
- parser (3.3.0.5)
120
+ parser (3.3.2.0)
98
121
  ast (~> 2.4.1)
99
122
  racc
100
123
  pg_query (5.1.0)
@@ -111,8 +134,8 @@ GEM
111
134
  pry (>= 0.13, < 0.15)
112
135
  psych (5.1.2)
113
136
  stringio
114
- racc (1.7.3)
115
- rack (3.0.9.1)
137
+ racc (1.8.0)
138
+ rack (3.0.11)
116
139
  rack-session (2.0.0)
117
140
  rack (>= 3.0.0)
118
141
  rack-test (2.1.0)
@@ -127,24 +150,25 @@ GEM
127
150
  rails-html-sanitizer (1.6.0)
128
151
  loofah (~> 2.21)
129
152
  nokogiri (~> 1.14)
130
- railties (7.1.3.2)
131
- actionpack (= 7.1.3.2)
132
- activesupport (= 7.1.3.2)
153
+ railties (7.1.3.4)
154
+ actionpack (= 7.1.3.4)
155
+ activesupport (= 7.1.3.4)
133
156
  irb
134
157
  rackup (>= 1.0.0)
135
158
  rake (>= 12.2)
136
159
  thor (~> 1.0, >= 1.2.2)
137
160
  zeitwerk (~> 2.6)
138
161
  rainbow (3.1.1)
139
- rake (13.1.0)
162
+ rake (13.2.1)
140
163
  rake-hooks (1.2.3)
141
164
  rake
142
- rdoc (6.6.2)
165
+ rdoc (6.6.3.1)
143
166
  psych (>= 4.0.0)
144
- regexp_parser (2.9.0)
145
- reline (0.4.3)
167
+ regexp_parser (2.9.2)
168
+ reline (0.5.7)
146
169
  io-console (~> 0.5)
147
- rexml (3.2.6)
170
+ rexml (3.2.8)
171
+ strscan (>= 3.0.9)
148
172
  rspec (3.13.0)
149
173
  rspec-core (~> 3.13.0)
150
174
  rspec-expectations (~> 3.13.0)
@@ -157,7 +181,7 @@ GEM
157
181
  rspec-mocks (3.13.0)
158
182
  diff-lcs (>= 1.2.0, < 2.0)
159
183
  rspec-support (~> 3.13.0)
160
- rspec-parameterized (1.0.0)
184
+ rspec-parameterized (1.0.2)
161
185
  rspec-parameterized-core (< 2)
162
186
  rspec-parameterized-table_syntax (< 2)
163
187
  rspec-parameterized-core (1.0.0)
@@ -169,7 +193,7 @@ GEM
169
193
  binding_of_caller
170
194
  rspec-parameterized-core (< 2)
171
195
  rspec-support (3.13.1)
172
- rubocop (1.60.2)
196
+ rubocop (1.64.1)
173
197
  json (~> 2.3)
174
198
  language_server-protocol (>= 3.17.0)
175
199
  parallel (~> 1.10)
@@ -177,29 +201,33 @@ GEM
177
201
  rainbow (>= 2.2.2, < 4.0)
178
202
  regexp_parser (>= 1.8, < 3.0)
179
203
  rexml (>= 3.2.5, < 4.0)
180
- rubocop-ast (>= 1.30.0, < 2.0)
204
+ rubocop-ast (>= 1.31.1, < 2.0)
181
205
  ruby-progressbar (~> 1.7)
182
206
  unicode-display_width (>= 2.4.0, < 3.0)
183
- rubocop-ast (1.30.0)
184
- parser (>= 3.2.1.0)
207
+ rubocop-ast (1.31.3)
208
+ parser (>= 3.3.1.0)
185
209
  rubocop-capybara (2.20.0)
186
210
  rubocop (~> 1.41)
187
211
  rubocop-factory_bot (2.25.1)
188
212
  rubocop (~> 1.41)
189
- rubocop-rails (2.23.1)
213
+ rubocop-rails (2.25.0)
190
214
  activesupport (>= 4.2.0)
191
215
  rack (>= 1.1)
192
216
  rubocop (>= 1.33.0, < 2.0)
193
- rubocop-ast (>= 1.30.0, < 2.0)
217
+ rubocop-ast (>= 1.31.1, < 2.0)
194
218
  rubocop-rake (0.6.0)
195
219
  rubocop (~> 1.0)
196
- rubocop-rspec (2.26.1)
220
+ rubocop-rspec (2.30.0)
197
221
  rubocop (~> 1.40)
198
222
  rubocop-capybara (~> 2.17)
199
223
  rubocop-factory_bot (~> 2.22)
224
+ rubocop-rspec_rails (~> 2.28)
225
+ rubocop-rspec_rails (2.28.3)
226
+ rubocop (~> 1.40)
200
227
  ruby-progressbar (1.13.0)
201
228
  ruby2_keywords (0.0.5)
202
229
  stringio (3.1.0)
230
+ strscan (3.1.0)
203
231
  thor (1.3.1)
204
232
  timeout (0.4.1)
205
233
  tzinfo (2.0.6)
@@ -209,7 +237,7 @@ GEM
209
237
  diff-lcs (~> 1.3)
210
238
  parser (>= 3.3.0)
211
239
  webrick (1.8.1)
212
- zeitwerk (2.6.13)
240
+ zeitwerk (2.6.14)
213
241
 
214
242
  PLATFORMS
215
243
  aarch64-linux
@@ -222,6 +250,7 @@ PLATFORMS
222
250
  DEPENDENCIES
223
251
  bundler
224
252
  bundler-audit
253
+ faker
225
254
  pg_objects!
226
255
  pry-byebug
227
256
  rake
@@ -5,7 +5,7 @@ module PgObjects
5
5
  # PgObjects.configure do |config|
6
6
  # # use relative from RAILS_ROOT
7
7
  # config.before_path = 'db/alternate/before'
8
- # # or full (not recommended)
8
+ # # or full
9
9
  # config.after_path = '/var/tmp/alternate/after'
10
10
  # config.extensions = ['sql', 'txt']
11
11
  # # suppress output to console
@@ -13,22 +13,20 @@ module PgObjects
13
13
  # end
14
14
  class << self
15
15
  def configure
16
- yield config
16
+ yield Config.config
17
17
  end
18
18
 
19
19
  def config
20
- @config ||= Config.new
20
+ Config.config
21
21
  end
22
22
  end
23
23
 
24
24
  class Config
25
- attr_accessor :before_path, :after_path, :extensions, :silent
25
+ extend Dry::Configurable
26
26
 
27
- def initialize
28
- @before_path = 'db/objects/before'
29
- @after_path = 'db/objects/after'
30
- @extensions = ['sql']
31
- @silent = false
32
- end
27
+ setting :before_path, default: 'db/objects/before'
28
+ setting :after_path, default: 'db/objects/after'
29
+ setting :extensions, default: ['sql']
30
+ setting :silent, default: false
33
31
  end
34
32
  end
@@ -0,0 +1,30 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # Container for dependencies
5
+ #
6
+ class PgObjects::Container
7
+ extend ::Dry::Container::Mixin
8
+
9
+ register 'config' do
10
+ PgObjects::Config.config
11
+ end
12
+
13
+ register 'db_object_factory' do
14
+ PgObjects::DbObjectFactory.new
15
+ end
16
+
17
+ register 'parsed_object_factory' do
18
+ PgObjects::ParsedObjectFactory
19
+ end
20
+
21
+ register 'parser' do
22
+ PgObjects::Parser.new
23
+ end
24
+
25
+ register 'logger' do
26
+ PgObjects::Logger.new
27
+ end
28
+ end
29
+
30
+ Import = Dry::AutoInject(PgObjects::Container)
@@ -5,27 +5,38 @@
5
5
  # [full_name] full pathname of file
6
6
  # [object_name] name of function, trigger etc. if it was successfully parsed, otherwise - nil
7
7
  class PgObjects::DbObject
8
- attr_reader :sql_query, :name, :full_name, :object_name, :dependencies
9
- attr_accessor :status
8
+ include Memery
9
+
10
+ include Import['parser']
10
11
 
11
- def initialize(file_path)
12
- @full_name = file_path
13
- @name = File.basename(file_path, '.*')
12
+ attr_accessor :status
13
+ attr_reader :full_name, :object_name
14
14
 
15
- @status = :new
15
+ def initialize(path, status = :new)
16
+ @full_name = path
17
+ @status = status
16
18
  end
17
19
 
18
20
  def create
19
- @sql_query = File.read(full_name)
20
-
21
- parser = PgObjects::Parser.new(sql_query)
22
-
23
- directives = parser.fetch_directives
24
- @dependencies = directives[:depends_on]
21
+ parser.load(sql_query)
25
22
  @object_name = parser.fetch_object_name
26
-
27
23
  @status = :pending
28
24
 
29
25
  self
30
26
  end
27
+
28
+ memoize
29
+ def name
30
+ File.basename(full_name, '.*')
31
+ end
32
+
33
+ memoize
34
+ def dependencies
35
+ parser.fetch_directives[:depends_on]
36
+ end
37
+
38
+ memoize
39
+ def sql_query
40
+ File.read(full_name)
41
+ end
31
42
  end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ ##
4
+ # Factory for DbObject
5
+ #
6
+ class PgObjects::DbObjectFactory
7
+ include Import['parser']
8
+
9
+ def create_instance(path, status: :new)
10
+ db_object = PgObjects::DbObject.new(path, status)
11
+ db_object.create
12
+ end
13
+ end
@@ -2,19 +2,9 @@
2
2
  # Console output
3
3
  #
4
4
  class PgObjects::Logger
5
- attr_reader :silent
6
-
7
- def initialize
8
- @silent = false
9
- end
5
+ include Import['config']
10
6
 
11
7
  def write(str)
12
- puts "== #{str} ".ljust(80, '=') unless silent
13
- end
14
-
15
- def mute(value)
16
- @silent = value
17
-
18
- self
8
+ puts "== #{str} ".ljust(80, '=') unless config.silent
19
9
  end
20
10
  end
@@ -9,24 +9,18 @@
9
9
  #
10
10
  # Manager.new(config, logger).load_files(:after).create_objects
11
11
  class PgObjects::Manager
12
- attr_reader :objects, :config
13
-
14
- def initialize(config, logger)
15
- raise PgObjects::UnsupportedAdapterError if ActiveRecord::Base.connection.adapter_name != 'PostgreSQL'
16
-
17
- @objects = []
18
- @config = config
19
- @log = logger.mute(config.silent) # Logger.new(silent: config.silent)
20
- end
12
+ include Import['db_object_factory', 'config', 'logger']
21
13
 
22
14
  ##
23
15
  # event: +:before+ or +:after+
24
16
  #
25
17
  # used to reference configuration settings +before_path+ and +after_path+
26
18
  def load_files(event)
19
+ validate_workability
20
+
27
21
  dir = config.send "#{event}_path"
28
22
  Dir[File.join(dir, '**', "*.{#{config.extensions.join(',')}}")].each do |path|
29
- @objects << PgObjects::DbObject.new(path).create
23
+ objects << db_object_factory.create_instance(path)
30
24
  end
31
25
 
32
26
  self
@@ -36,8 +30,16 @@ class PgObjects::Manager
36
30
  objects.each { create_object(_1) }
37
31
  end
38
32
 
33
+ def objects
34
+ @objects ||= []
35
+ end
36
+
39
37
  private
40
38
 
39
+ def validate_workability
40
+ raise PgObjects::UnsupportedAdapterError if ActiveRecord::Base.connection.adapter_name != 'PostgreSQL'
41
+ end
42
+
41
43
  def create_object(obj)
42
44
  return if obj.status == :done
43
45
  raise PgObjects::CyclicDependencyError, obj.name if obj.status == :processing
@@ -46,8 +48,8 @@ class PgObjects::Manager
46
48
 
47
49
  create_dependencies(obj.dependencies)
48
50
 
49
- @log.write("creating #{obj.name}")
50
- ActiveRecord::Base.connection.execute obj.sql_query
51
+ logger.write("creating #{obj.name}")
52
+ ActiveRecord::Base.connection.execute(obj.sql_query)
51
53
 
52
54
  obj.status = :done
53
55
  end
@@ -57,7 +59,7 @@ class PgObjects::Manager
57
59
  end
58
60
 
59
61
  def find_object(dep_name)
60
- result = @objects.select { |obj| [obj.name, obj.full_name, obj.object_name].compact.include? dep_name }
62
+ result = objects.select { |obj| [obj.name, obj.full_name, obj.object_name].compact.include? dep_name }
61
63
 
62
64
  raise PgObjects::AmbiguousDependencyError, dep_name if result.size > 1
63
65
  raise PgObjects::DependencyNotExistError, dep_name if result.empty?
@@ -0,0 +1,8 @@
1
+ #
2
+ # AGGREGATE object representation
3
+ #
4
+ class PgObjects::ParsedObject::Aggregate < PgObjects::ParsedObject::Base
5
+ def name
6
+ stmt.define_stmt.defnames[0].string.sval
7
+ end
8
+ end
@@ -0,0 +1,16 @@
1
+ #
2
+ # Base class for parsed objects
3
+ #
4
+ class PgObjects::ParsedObject::Base
5
+ def initialize(stmt)
6
+ @stmt = stmt
7
+ end
8
+
9
+ def name
10
+ raise NotImplementedError
11
+ end
12
+
13
+ private
14
+
15
+ attr_reader :stmt
16
+ end
@@ -0,0 +1,8 @@
1
+ #
2
+ # CONVERSION object representation
3
+ #
4
+ class PgObjects::ParsedObject::Conversion < PgObjects::ParsedObject::Base
5
+ def name
6
+ stmt.create_conversion_stmt.conversion_name[0].string.sval
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ #
2
+ # EVENT TRIGGER object representation
3
+ #
4
+ class PgObjects::ParsedObject::EventTrigger < PgObjects::ParsedObject::Base
5
+ def name
6
+ stmt.create_event_trig_stmt.trigname
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ #
2
+ # FUNCTION object representation
3
+ #
4
+ class PgObjects::ParsedObject::Function < PgObjects::ParsedObject::Base
5
+ def name
6
+ stmt.create_function_stmt.funcname[0].string.sval
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ #
2
+ # MATERIALIZED VIEW object representation
3
+ #
4
+ class PgObjects::ParsedObject::MaterializedView < PgObjects::ParsedObject::Base
5
+ def name
6
+ stmt.create_table_as_stmt.into.rel.relname
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ #
2
+ # OPERATOR object representation
3
+ #
4
+ class PgObjects::ParsedObject::Operator < PgObjects::ParsedObject::Base
5
+ def name
6
+ stmt.define_stmt.defnames[0].string.sval
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ #
2
+ # OPERATOR CLASS object representation
3
+ #
4
+ class PgObjects::ParsedObject::OperatorClass < PgObjects::ParsedObject::Base
5
+ def name
6
+ stmt.create_op_class_stmt.opclassname[0].string.sval
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ #
2
+ # TABLE object representation
3
+ #
4
+ class PgObjects::ParsedObject::Table < PgObjects::ParsedObject::Base
5
+ def name
6
+ stmt.create_stmt.relation.relname
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ #
2
+ # TEXT SEARCH PARSER object representation
3
+ #
4
+ class PgObjects::ParsedObject::TextSearchParser < PgObjects::ParsedObject::Base
5
+ def name
6
+ stmt.define_stmt.defnames[0].string.sval
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ #
2
+ # TEXT SEARCH TEMPLATE object representation
3
+ #
4
+ class PgObjects::ParsedObject::TextSearchTemplate < PgObjects::ParsedObject::Base
5
+ def name
6
+ stmt.define_stmt.defnames[0].string.sval
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ #
2
+ # TRIGGER object representation
3
+ #
4
+ class PgObjects::ParsedObject::Trigger < PgObjects::ParsedObject::Base
5
+ def name
6
+ stmt.create_trig_stmt.trigname
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ #
2
+ # TYPE object representation
3
+ #
4
+ class PgObjects::ParsedObject::Type < PgObjects::ParsedObject::Base
5
+ def name
6
+ stmt.composite_type_stmt.typevar.relname
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ #
2
+ # VIEW object representation
3
+ #
4
+ class PgObjects::ParsedObject::View < PgObjects::ParsedObject::Base
5
+ def name
6
+ stmt.view_stmt.view.relname
7
+ end
8
+ end
@@ -0,0 +1,18 @@
1
+ module PgObjects::ParsedObject # rubocop: disable Style/Documentation
2
+ end
3
+
4
+ require 'pg_objects/parsed_object/base'
5
+ require 'pg_objects/parsed_object/aggregate'
6
+ require 'pg_objects/parsed_object/conversion'
7
+ require 'pg_objects/parsed_object/event_trigger'
8
+ require 'pg_objects/parsed_object/function'
9
+ require 'pg_objects/parsed_object/materialized_view'
10
+ require 'pg_objects/parsed_object/operator'
11
+ require 'pg_objects/parsed_object/operator_class'
12
+ require 'pg_objects/parsed_object/table'
13
+ require 'pg_objects/parsed_object/text_search_parser'
14
+ require 'pg_objects/parsed_object/text_search_template'
15
+ require 'pg_objects/parsed_object/trigger'
16
+ require 'pg_objects/parsed_object/type'
17
+ require 'pg_objects/parsed_object/view'
18
+ require 'pg_objects/parsed_object_factory'
@@ -0,0 +1,103 @@
1
+ #
2
+ # Returns an object of the respective class based on the provided parsed query
3
+ #
4
+ class PgObjects::ParsedObjectFactory
5
+ class << self
6
+ include Dry::Monads[:try, :result]
7
+
8
+ SUPPORTED_TYPES = %i[
9
+ aggregate
10
+ conversion
11
+ event_trigger
12
+ function
13
+ materialized_view
14
+ operator
15
+ operator_class
16
+ table
17
+ text_search_parser
18
+ text_search_template
19
+ trigger
20
+ type
21
+ view
22
+ ].freeze
23
+
24
+ def create_object(input_data)
25
+ @input_data = input_data
26
+ @stmt = input_data.tree.stmts[0].stmt
27
+
28
+ determine_class.new(stmt)
29
+ end
30
+
31
+ private
32
+
33
+ attr_reader :stmt, :input_data
34
+
35
+ def determine_class
36
+ SUPPORTED_TYPES.each do |type|
37
+ return class_for(type) if send("#{type}?")
38
+ end
39
+ end
40
+
41
+ def class_for(type)
42
+ "PgObjects::ParsedObject::#{type.to_s.classify}".constantize
43
+ end
44
+
45
+ def aggregate?
46
+ try_check_get_result { stmt.define_stmt.kind == :OBJECT_AGGREGATE }
47
+ end
48
+
49
+ def conversion?
50
+ try_check_get_result { stmt.create_conversion_stmt.conversion_name.present? }
51
+ end
52
+
53
+ def event_trigger?
54
+ try_check_get_result { stmt.create_event_trig_stmt.trigname.present? }
55
+ end
56
+
57
+ def function?
58
+ try_check_get_result { stmt.create_function_stmt.funcname.present? }
59
+ end
60
+
61
+ def materialized_view?
62
+ try_check_get_result { stmt.create_table_as_stmt.objtype == :OBJECT_MATVIEW }
63
+ end
64
+
65
+ def operator_class?
66
+ try_check_get_result { stmt.create_op_class_stmt.opclassname.present? }
67
+ end
68
+
69
+ def operator?
70
+ try_check_get_result { stmt.define_stmt.kind == :OBJECT_OPERATOR }
71
+ end
72
+
73
+ def table?
74
+ try_check_get_result { stmt.create_stmt.table_elts.present? }
75
+ end
76
+
77
+ def text_search_parser?
78
+ try_check_get_result { stmt.define_stmt.kind == :OBJECT_TSPARSER }
79
+ end
80
+
81
+ def text_search_template?
82
+ try_check_get_result { stmt.define_stmt.kind == :OBJECT_TSTEMPLATE }
83
+ end
84
+
85
+ def trigger?
86
+ try_check_get_result { stmt.create_trig_stmt.trigname.present? }
87
+ end
88
+
89
+ def type?
90
+ try_check_get_result { stmt.composite_type_stmt.typevar.present? }
91
+ end
92
+
93
+ def view?
94
+ try_check_get_result { stmt.view_stmt.view.present? }
95
+ end
96
+
97
+ def try_check_get_result(&)
98
+ result = Try(&).to_result
99
+
100
+ result.success? && result.value!
101
+ end
102
+ end
103
+ end
@@ -8,10 +8,14 @@ require 'pg_query'
8
8
  # name_of_dependency: short or full name of object as well as object_name
9
9
  #
10
10
  class PgObjects::Parser
11
+ include Import['parsed_object_factory']
12
+ include Memery
13
+
11
14
  PG_ENTITIES = %i[operator_class trigger define_statement conversion event_trigger type function table].freeze
12
15
 
13
- def initialize(source)
16
+ def load(source)
14
17
  @source = source
18
+ self
15
19
  end
16
20
 
17
21
  def fetch_directives
@@ -22,75 +26,25 @@ class PgObjects::Parser
22
26
 
23
27
  def fetch_object_name
24
28
  parse_query
25
- object_name
29
+ parsed_object.name
26
30
  rescue PgQuery::ParseError, NoMethodError
27
31
  nil
28
32
  end
29
33
 
30
34
  private
31
35
 
32
- attr_reader :stmt, :parsed
36
+ attr_reader :parsed
33
37
 
34
38
  def parse_query
35
39
  @parsed = PgQuery.parse(@source)
36
-
37
- @stmt = parsed.tree.stmts[0].stmt
38
40
  end
39
41
 
40
- def object_name
41
- PG_ENTITIES.filter_map { |entity| send(:"check_#{entity}") }.first
42
+ memoize
43
+ def parsed_object
44
+ parsed_object_factory.create_object(parsed)
42
45
  end
43
46
 
44
47
  def fetch_dependencies
45
48
  @source.split("\n").grep(/^(--|#)!/).map { |ln| ln.split[1] if ln =~ /!depends_on/ }.compact
46
49
  end
47
-
48
- # also views
49
- def table? = parsed.tables.size.positive?
50
-
51
- def check_table
52
- parsed.tables[0] if table?
53
- end
54
-
55
- def function? = parsed.functions.size.positive?
56
-
57
- def check_function
58
- parsed.functions[0] if function?
59
- end
60
-
61
- def operator_class? = stmt.respond_to?(:create_op_class_stmt) && stmt.create_op_class_stmt.present?
62
-
63
- def check_operator_class
64
- stmt.create_op_class_stmt.opclassname[0].string.sval if operator_class?
65
- end
66
-
67
- def trigger? = stmt.respond_to?(:create_trig_stmt) && stmt.create_trig_stmt.present?
68
-
69
- def check_trigger
70
- stmt.create_trig_stmt.trigname if trigger?
71
- end
72
-
73
- def define_statement? = stmt.respond_to?(:define_stmt) && stmt.define_stmt.present?
74
-
75
- def check_define_statement
76
- stmt.define_stmt.defnames[0].string.sval if define_statement?
77
- end
78
-
79
- def conversion? = stmt.respond_to?(:create_conversion_stmt) && stmt.create_conversion_stmt.present?
80
-
81
- def check_conversion
82
- stmt.create_conversion_stmt.conversion_name[0].string.sval if conversion?
83
- end
84
-
85
- def event_trigger? = stmt.respond_to?(:create_event_trig_stmt) && stmt.create_event_trig_stmt.present?
86
-
87
- def check_event_trigger
88
- stmt.create_event_trig_stmt.trigname if event_trigger?
89
- end
90
-
91
- def type? = stmt.respond_to?(:composite_type_stmt) && stmt.composite_type_stmt.present?
92
-
93
- def check_type
94
- stmt.composite_type_stmt.typevar.relname if type?
95
- end
96
50
  end
@@ -1,9 +1,6 @@
1
1
  ##
2
2
  # Brings rake tasks to rails app
3
3
  class PgObjects::Railtie < Rails::Railtie
4
- # initializer 'pg_objects.initialization' do |app|
5
- # end
6
-
7
4
  rake_tasks do
8
5
  load 'tasks/pg_objects_tasks.rake'
9
6
  end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module PgObjects
4
- VERSION = '1.2.0'
4
+ VERSION = '1.2.1'
5
5
  end
data/lib/pg_objects.rb CHANGED
@@ -1,10 +1,19 @@
1
1
  require 'pg_objects/version'
2
2
  require 'pg_objects/railtie' if defined?(Rails)
3
3
 
4
+ require 'dry-configurable'
5
+ require 'dry-container'
6
+ require 'dry-auto_inject'
7
+ require 'dry/monads'
8
+ require 'memery'
9
+
10
+ require 'pg_objects/container'
4
11
  require 'pg_objects/config'
5
12
  require 'pg_objects/db_object'
13
+ require 'pg_objects/db_object_factory'
6
14
  require 'pg_objects/logger'
7
15
  require 'pg_objects/manager'
16
+ require 'pg_objects/parsed_object'
8
17
  require 'pg_objects/parser'
9
18
 
10
19
  module PgObjects
data/pg_objects.gemspec CHANGED
@@ -44,6 +44,11 @@ Gem::Specification.new do |spec|
44
44
  spec.require_paths = ['lib']
45
45
 
46
46
  spec.add_dependency 'activerecord', '>= 6.1.7.0', '< 8'
47
+ spec.add_dependency 'dry-auto_inject', '~> 1'
48
+ spec.add_dependency 'dry-configurable', '~> 1'
49
+ spec.add_dependency 'dry-container', '0.11.0'
50
+ spec.add_dependency 'dry-monads', '~> 1.6'
51
+ spec.add_dependency 'memery', '~> 1.5.0'
47
52
  spec.add_dependency 'pg_query', '~> 5'
48
53
  spec.add_dependency 'railties', '>= 4', '< 8'
49
54
  spec.add_dependency 'rake-hooks', '~> 1'
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: pg_objects
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.2.0
4
+ version: 1.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Denis Kiselyov
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2024-02-28 00:00:00.000000000 Z
11
+ date: 2024-06-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord
@@ -30,6 +30,76 @@ dependencies:
30
30
  - - "<"
31
31
  - !ruby/object:Gem::Version
32
32
  version: '8'
33
+ - !ruby/object:Gem::Dependency
34
+ name: dry-auto_inject
35
+ requirement: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '1'
40
+ type: :runtime
41
+ prerelease: false
42
+ version_requirements: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '1'
47
+ - !ruby/object:Gem::Dependency
48
+ name: dry-configurable
49
+ requirement: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '1'
54
+ type: :runtime
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - "~>"
59
+ - !ruby/object:Gem::Version
60
+ version: '1'
61
+ - !ruby/object:Gem::Dependency
62
+ name: dry-container
63
+ requirement: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - '='
66
+ - !ruby/object:Gem::Version
67
+ version: 0.11.0
68
+ type: :runtime
69
+ prerelease: false
70
+ version_requirements: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - '='
73
+ - !ruby/object:Gem::Version
74
+ version: 0.11.0
75
+ - !ruby/object:Gem::Dependency
76
+ name: dry-monads
77
+ requirement: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - "~>"
80
+ - !ruby/object:Gem::Version
81
+ version: '1.6'
82
+ type: :runtime
83
+ prerelease: false
84
+ version_requirements: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '1.6'
89
+ - !ruby/object:Gem::Dependency
90
+ name: memery
91
+ requirement: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: 1.5.0
96
+ type: :runtime
97
+ prerelease: false
98
+ version_requirements: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: 1.5.0
33
103
  - !ruby/object:Gem::Dependency
34
104
  name: pg_query
35
105
  requirement: !ruby/object:Gem::Requirement
@@ -103,9 +173,27 @@ files:
103
173
  - lib/generators/pg_objects/install/install_generator.rb
104
174
  - lib/pg_objects.rb
105
175
  - lib/pg_objects/config.rb
176
+ - lib/pg_objects/container.rb
106
177
  - lib/pg_objects/db_object.rb
178
+ - lib/pg_objects/db_object_factory.rb
107
179
  - lib/pg_objects/logger.rb
108
180
  - lib/pg_objects/manager.rb
181
+ - lib/pg_objects/parsed_object.rb
182
+ - lib/pg_objects/parsed_object/aggregate.rb
183
+ - lib/pg_objects/parsed_object/base.rb
184
+ - lib/pg_objects/parsed_object/conversion.rb
185
+ - lib/pg_objects/parsed_object/event_trigger.rb
186
+ - lib/pg_objects/parsed_object/function.rb
187
+ - lib/pg_objects/parsed_object/materialized_view.rb
188
+ - lib/pg_objects/parsed_object/operator.rb
189
+ - lib/pg_objects/parsed_object/operator_class.rb
190
+ - lib/pg_objects/parsed_object/table.rb
191
+ - lib/pg_objects/parsed_object/text_search_parser.rb
192
+ - lib/pg_objects/parsed_object/text_search_template.rb
193
+ - lib/pg_objects/parsed_object/trigger.rb
194
+ - lib/pg_objects/parsed_object/type.rb
195
+ - lib/pg_objects/parsed_object/view.rb
196
+ - lib/pg_objects/parsed_object_factory.rb
109
197
  - lib/pg_objects/parser.rb
110
198
  - lib/pg_objects/railtie.rb
111
199
  - lib/pg_objects/version.rb