rack-dev_insight 0.2.2 → 0.3.0

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: 420b7dc55809b5c012b31b2bed5831c52e9da31d69744bc69191fc61a9d6a682
4
- data.tar.gz: 151dfe8d28aea14369e116b35b5d0e67c362458aaca221f3d759b6605097a216
3
+ metadata.gz: cbb5f9291376068796d23a7453b4a4c892a4f87744e3dd60ffefa3cb6df33ab9
4
+ data.tar.gz: 162b2adc0edb597c1154b2592aef379411d97eeaec3b1d9bb8b42f50a3c5af22
5
5
  SHA512:
6
- metadata.gz: 8b4da50d262af9891a986bda5eefc9e556296dad9abfca9667bbca92a70a0505515dde7070652c48b7d32535941b8f6dc25c3a764d985b19f05a356e090343a7
7
- data.tar.gz: 37b43dc7cf80e252e8d4816390eb2843627eb31b991d623700de02c8e9b892696331dd071008bc4e99da3c42349de1b23854f33ea7e474bba689daba0e8bb2ad
6
+ metadata.gz: dffa38c4ee3037673ab6ef6e086c77f0d44122146144034a9387a2162454c49e2d41e50412deac611d1730d4772271bb099a127690770e3f230c10b0360e0140
7
+ data.tar.gz: dabfbb00c1b734caa6b91e38df5c478183376a3c3200012b0f317c69e6d2dd793156d3f39048efd9c9f9c21fa603d0a50aebd27ccb1804118e60665e032bfb81
@@ -2,12 +2,7 @@
2
2
 
3
3
  module Rack
4
4
  class DevInsight
5
- # Definitions must be synced with ext/rack_dev_insight/src/errors.rs
6
5
  class Error < StandardError
7
6
  end
8
- class ExtError < Error
9
- end
10
- class ParserError < ExtError
11
- end
12
7
  end
13
8
  end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Rack
4
+ class DevInsight
5
+ module Extractor
6
+ class << self
7
+ def extract_crud_tables(dialect_name, statement)
8
+ crud_tables = SqlInsight.extract_crud_tables(dialect_name, statement)
9
+ results = { 'CREATE' => [], 'READ' => [], 'UPDATE' => [], 'DELETE' => [] }
10
+
11
+ crud_tables.each do |crud_table|
12
+ results['CREATE'].concat(crud_table.create_tables.map(&:name).map(&:value))
13
+ results['READ'].concat(crud_table.read_tables.map(&:name).map(&:value))
14
+ results['UPDATE'].concat(crud_table.update_tables.map(&:name).map(&:value))
15
+ results['DELETE'].concat(crud_table.delete_tables.map(&:name).map(&:value))
16
+ end
17
+
18
+ results
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -5,7 +5,7 @@ module Rack
5
5
  module Normalizer
6
6
  class << self
7
7
  def normalize(dialect_name, statement)
8
- _normalize(dialect_name, statement)
8
+ SqlInsight.normalize(dialect_name, statement)
9
9
  end
10
10
  end
11
11
  end
@@ -13,11 +13,11 @@ module Rack
13
13
  end
14
14
 
15
15
  def add(dialect_name, statement, duration, query_id)
16
- crud_tables = Extractor::CrudTables.extract(dialect_name, statement)
16
+ crud_tables = Extractor.extract_crud_tables(dialect_name, statement)
17
17
 
18
18
  crud_tables.each do |type, tables|
19
19
  tables.each do |table|
20
- key = "#{type}_#{table.downcase}"
20
+ key = "#{type}_#{table}"
21
21
  data = @cached_data[key] ||= CrudAggregation.new(@id += 1, type, table, 0, 0, [])
22
22
  data.count += 1
23
23
  data.duration += duration
@@ -15,7 +15,7 @@ module Rack
15
15
  @queries.add(statement, binds, backtrace, duration)
16
16
  @crud_aggregations.add(dialect, statement, duration, @queries.id)
17
17
  @normalized_aggregations.add(dialect, statement, duration, @queries.id)
18
- rescue ExtError => e
18
+ rescue SqlInsight::Error => e
19
19
  @errored_queries.add(@queries.id, e.message, statement, backtrace, duration)
20
20
  end
21
21
 
@@ -2,6 +2,6 @@
2
2
 
3
3
  module Rack
4
4
  class DevInsight
5
- VERSION = '0.2.2'
5
+ VERSION = '0.3.0'
6
6
  end
7
7
  end
@@ -1,8 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  require 'securerandom'
4
- require_relative 'dev_insight/ext/extractor'
5
- require_relative 'dev_insight/ext/normalizer'
4
+ require 'sql_insight'
6
5
  require_relative 'dev_insight/recorder/api_recorder'
7
6
  require_relative 'dev_insight/recorder/request_recorder'
8
7
  require_relative 'dev_insight/recorder/sql_recorder'
@@ -19,17 +18,10 @@ require_relative 'dev_insight/utils/camelizer'
19
18
  require_relative 'dev_insight/config'
20
19
  require_relative 'dev_insight/context'
21
20
  require_relative 'dev_insight/errors'
21
+ require_relative 'dev_insight/extractor'
22
+ require_relative 'dev_insight/normalizer'
22
23
  require_relative 'dev_insight/sql_dialects'
23
24
  require_relative 'dev_insight/version'
24
-
25
- # https://github.com/rake-compiler/rake-compiler/blob/master/README.md
26
- # Technique to lookup the fat binaries first, and then lookup the gems compiled by the end user.
27
- begin
28
- RUBY_VERSION =~ /(\d+\.\d+)/
29
- require_relative "dev_insight/#{Regexp.last_match(1)}/rack_dev_insight"
30
- rescue LoadError
31
- require_relative 'dev_insight/rack_dev_insight'
32
- end
33
25
  # Railtie
34
26
  require_relative 'dev_insight/railtie' if defined?(Rails)
35
27
  # Patches
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-dev_insight
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Takahiro Ebato
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2024-01-03 00:00:00.000000000 Z
11
+ date: 2024-03-17 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rack
@@ -25,44 +25,35 @@ dependencies:
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
27
  - !ruby/object:Gem::Dependency
28
- name: rb_sys
28
+ name: sql_insight
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: 0.9.85
33
+ version: 0.1.0
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
38
  - - "~>"
39
39
  - !ruby/object:Gem::Version
40
- version: 0.9.85
41
- description: A rack middleware for analyzing SQL queries and HTTP request / response
42
- data. Chrome extension is needed to display the analysis result.
40
+ version: 0.1.0
41
+ description: An observability tool for Rack applications, analyzing SQL and HTTP with
42
+ a Chrome extension as a dashboard
43
43
  email:
44
44
  - takahiro.ebato@gmail.com
45
45
  executables: []
46
- extensions:
47
- - ext/rack_dev_insight/extconf.rb
46
+ extensions: []
48
47
  extra_rdoc_files: []
49
48
  files:
50
- - Cargo.lock
51
- - Cargo.toml
52
- - ext/rack_dev_insight/Cargo.toml
53
- - ext/rack_dev_insight/extconf.rb
54
- - ext/rack_dev_insight/src/errors.rs
55
- - ext/rack_dev_insight/src/extractor.rs
56
- - ext/rack_dev_insight/src/lib.rs
57
- - ext/rack_dev_insight/src/normalizer.rs
58
49
  - lib/rack/dev_insight.rb
59
50
  - lib/rack/dev_insight/config.rb
60
51
  - lib/rack/dev_insight/context.rb
61
52
  - lib/rack/dev_insight/disable_net_http_patch.rb
62
53
  - lib/rack/dev_insight/enable_sql_patch.rb
63
54
  - lib/rack/dev_insight/errors.rb
64
- - lib/rack/dev_insight/ext/extractor.rb
65
- - lib/rack/dev_insight/ext/normalizer.rb
55
+ - lib/rack/dev_insight/extractor.rb
56
+ - lib/rack/dev_insight/normalizer.rb
66
57
  - lib/rack/dev_insight/patches/api/net_http.rb
67
58
  - lib/rack/dev_insight/patches/sql/mysql2.rb
68
59
  - lib/rack/dev_insight/patches/sql/pg.rb
@@ -109,5 +100,6 @@ requirements: []
109
100
  rubygems_version: 3.5.3
110
101
  signing_key:
111
102
  specification_version: 4
112
- summary: A rack middleware for analyzing SQL queries and HTTP request / response data.
103
+ summary: An observability tool for Rack apps, analyzing SQL and HTTP with a Chrome
104
+ extension as a dashboard
113
105
  test_files: []
data/Cargo.lock DELETED
@@ -1,415 +0,0 @@
1
- # This file is automatically @generated by Cargo.
2
- # It is not intended for manual editing.
3
- version = 3
4
-
5
- [[package]]
6
- name = "aho-corasick"
7
- version = "1.1.2"
8
- source = "registry+https://github.com/rust-lang/crates.io-index"
9
- checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
10
- dependencies = [
11
- "memchr",
12
- ]
13
-
14
- [[package]]
15
- name = "bindgen"
16
- version = "0.69.1"
17
- source = "registry+https://github.com/rust-lang/crates.io-index"
18
- checksum = "9ffcebc3849946a7170a05992aac39da343a90676ab392c51a4280981d6379c2"
19
- dependencies = [
20
- "bitflags",
21
- "cexpr",
22
- "clang-sys",
23
- "lazy_static",
24
- "lazycell",
25
- "peeking_take_while",
26
- "proc-macro2",
27
- "quote",
28
- "regex",
29
- "rustc-hash",
30
- "shlex",
31
- "syn 2.0.45",
32
- ]
33
-
34
- [[package]]
35
- name = "bitflags"
36
- version = "2.4.1"
37
- source = "registry+https://github.com/rust-lang/crates.io-index"
38
- checksum = "327762f6e5a765692301e5bb513e0d9fef63be86bbc14528052b1cd3e6f03e07"
39
-
40
- [[package]]
41
- name = "cexpr"
42
- version = "0.6.0"
43
- source = "registry+https://github.com/rust-lang/crates.io-index"
44
- checksum = "6fac387a98bb7c37292057cffc56d62ecb629900026402633ae9160df93a8766"
45
- dependencies = [
46
- "nom",
47
- ]
48
-
49
- [[package]]
50
- name = "cfg-if"
51
- version = "1.0.0"
52
- source = "registry+https://github.com/rust-lang/crates.io-index"
53
- checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
54
-
55
- [[package]]
56
- name = "clang-sys"
57
- version = "1.7.0"
58
- source = "registry+https://github.com/rust-lang/crates.io-index"
59
- checksum = "67523a3b4be3ce1989d607a828d036249522dd9c1c8de7f4dd2dae43a37369d1"
60
- dependencies = [
61
- "glob",
62
- "libc",
63
- "libloading",
64
- ]
65
-
66
- [[package]]
67
- name = "glob"
68
- version = "0.3.1"
69
- source = "registry+https://github.com/rust-lang/crates.io-index"
70
- checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
71
-
72
- [[package]]
73
- name = "indoc"
74
- version = "2.0.4"
75
- source = "registry+https://github.com/rust-lang/crates.io-index"
76
- checksum = "1e186cfbae8084e513daff4240b4797e342f988cecda4fb6c939150f96315fd8"
77
-
78
- [[package]]
79
- name = "lazy_static"
80
- version = "1.4.0"
81
- source = "registry+https://github.com/rust-lang/crates.io-index"
82
- checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
83
-
84
- [[package]]
85
- name = "lazycell"
86
- version = "1.3.0"
87
- source = "registry+https://github.com/rust-lang/crates.io-index"
88
- checksum = "830d08ce1d1d941e6b30645f1a0eb5643013d835ce3779a5fc208261dbe10f55"
89
-
90
- [[package]]
91
- name = "libc"
92
- version = "0.2.151"
93
- source = "registry+https://github.com/rust-lang/crates.io-index"
94
- checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
95
-
96
- [[package]]
97
- name = "libloading"
98
- version = "0.8.1"
99
- source = "registry+https://github.com/rust-lang/crates.io-index"
100
- checksum = "c571b676ddfc9a8c12f1f3d3085a7b163966a8fd8098a90640953ce5f6170161"
101
- dependencies = [
102
- "cfg-if",
103
- "windows-sys",
104
- ]
105
-
106
- [[package]]
107
- name = "log"
108
- version = "0.4.20"
109
- source = "registry+https://github.com/rust-lang/crates.io-index"
110
- checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
111
-
112
- [[package]]
113
- name = "magnus"
114
- version = "0.6.2"
115
- source = "registry+https://github.com/rust-lang/crates.io-index"
116
- checksum = "4778544796676e8428e9c622460ebf284bea52d8b10db3aeb449d8b5e61b3a13"
117
- dependencies = [
118
- "magnus-macros",
119
- "rb-sys",
120
- "rb-sys-env",
121
- "seq-macro",
122
- ]
123
-
124
- [[package]]
125
- name = "magnus-macros"
126
- version = "0.6.0"
127
- source = "registry+https://github.com/rust-lang/crates.io-index"
128
- checksum = "5968c820e2960565f647819f5928a42d6e874551cab9d88d75e3e0660d7f71e3"
129
- dependencies = [
130
- "proc-macro2",
131
- "quote",
132
- "syn 2.0.45",
133
- ]
134
-
135
- [[package]]
136
- name = "memchr"
137
- version = "2.7.1"
138
- source = "registry+https://github.com/rust-lang/crates.io-index"
139
- checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
140
-
141
- [[package]]
142
- name = "minimal-lexical"
143
- version = "0.2.1"
144
- source = "registry+https://github.com/rust-lang/crates.io-index"
145
- checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a"
146
-
147
- [[package]]
148
- name = "nom"
149
- version = "7.1.3"
150
- source = "registry+https://github.com/rust-lang/crates.io-index"
151
- checksum = "d273983c5a657a70a3e8f2a01329822f3b8c8172b73826411a55751e404a0a4a"
152
- dependencies = [
153
- "memchr",
154
- "minimal-lexical",
155
- ]
156
-
157
- [[package]]
158
- name = "peeking_take_while"
159
- version = "0.1.2"
160
- source = "registry+https://github.com/rust-lang/crates.io-index"
161
- checksum = "19b17cddbe7ec3f8bc800887bab5e717348c95ea2ca0b1bf0837fb964dc67099"
162
-
163
- [[package]]
164
- name = "proc-macro2"
165
- version = "1.0.73"
166
- source = "registry+https://github.com/rust-lang/crates.io-index"
167
- checksum = "2dd5e8a1f1029c43224ad5898e50140c2aebb1705f19e67c918ebf5b9e797fe1"
168
- dependencies = [
169
- "unicode-ident",
170
- ]
171
-
172
- [[package]]
173
- name = "quote"
174
- version = "1.0.34"
175
- source = "registry+https://github.com/rust-lang/crates.io-index"
176
- checksum = "22a37c9326af5ed140c86a46655b5278de879853be5573c01df185b6f49a580a"
177
- dependencies = [
178
- "proc-macro2",
179
- ]
180
-
181
- [[package]]
182
- name = "rack_dev_insight"
183
- version = "0.1.0"
184
- dependencies = [
185
- "indoc",
186
- "magnus",
187
- "rb-sys-test-helpers",
188
- "sqlparser",
189
- "tap",
190
- ]
191
-
192
- [[package]]
193
- name = "rb-sys"
194
- version = "0.9.85"
195
- source = "registry+https://github.com/rust-lang/crates.io-index"
196
- checksum = "05b780e6858b0b0eced1d55d0f097c024b77a37b41f83bd35341130f78e37c51"
197
- dependencies = [
198
- "rb-sys-build",
199
- ]
200
-
201
- [[package]]
202
- name = "rb-sys-build"
203
- version = "0.9.85"
204
- source = "registry+https://github.com/rust-lang/crates.io-index"
205
- checksum = "44957a3bc513dad1b0f20bdd0ee3b82e729a59da44086a6b40d8bc71958a6db8"
206
- dependencies = [
207
- "bindgen",
208
- "lazy_static",
209
- "proc-macro2",
210
- "quote",
211
- "regex",
212
- "shell-words",
213
- "syn 2.0.45",
214
- ]
215
-
216
- [[package]]
217
- name = "rb-sys-env"
218
- version = "0.1.2"
219
- source = "registry+https://github.com/rust-lang/crates.io-index"
220
- checksum = "a35802679f07360454b418a5d1735c89716bde01d35b1560fc953c1415a0b3bb"
221
-
222
- [[package]]
223
- name = "rb-sys-test-helpers"
224
- version = "0.2.0"
225
- source = "registry+https://github.com/rust-lang/crates.io-index"
226
- checksum = "bbd592029353df7955a76ca0b1bf0d9ccc57feab96615f80d1fe756462864949"
227
- dependencies = [
228
- "rb-sys",
229
- "rb-sys-env",
230
- "rb-sys-test-helpers-macros",
231
- ]
232
-
233
- [[package]]
234
- name = "rb-sys-test-helpers-macros"
235
- version = "0.2.0"
236
- source = "registry+https://github.com/rust-lang/crates.io-index"
237
- checksum = "c21f156459adb755d58f73dbd783dc1de8b403635e637f7d1daec1c7a920c1f5"
238
- dependencies = [
239
- "quote",
240
- "syn 2.0.45",
241
- ]
242
-
243
- [[package]]
244
- name = "regex"
245
- version = "1.10.2"
246
- source = "registry+https://github.com/rust-lang/crates.io-index"
247
- checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
248
- dependencies = [
249
- "aho-corasick",
250
- "memchr",
251
- "regex-automata",
252
- "regex-syntax",
253
- ]
254
-
255
- [[package]]
256
- name = "regex-automata"
257
- version = "0.4.3"
258
- source = "registry+https://github.com/rust-lang/crates.io-index"
259
- checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
260
- dependencies = [
261
- "aho-corasick",
262
- "memchr",
263
- "regex-syntax",
264
- ]
265
-
266
- [[package]]
267
- name = "regex-syntax"
268
- version = "0.8.2"
269
- source = "registry+https://github.com/rust-lang/crates.io-index"
270
- checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f"
271
-
272
- [[package]]
273
- name = "rustc-hash"
274
- version = "1.1.0"
275
- source = "registry+https://github.com/rust-lang/crates.io-index"
276
- checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
277
-
278
- [[package]]
279
- name = "seq-macro"
280
- version = "0.3.5"
281
- source = "registry+https://github.com/rust-lang/crates.io-index"
282
- checksum = "a3f0bf26fd526d2a95683cd0f87bf103b8539e2ca1ef48ce002d67aad59aa0b4"
283
-
284
- [[package]]
285
- name = "shell-words"
286
- version = "1.1.0"
287
- source = "registry+https://github.com/rust-lang/crates.io-index"
288
- checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
289
-
290
- [[package]]
291
- name = "shlex"
292
- version = "1.2.0"
293
- source = "registry+https://github.com/rust-lang/crates.io-index"
294
- checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380"
295
-
296
- [[package]]
297
- name = "sqlparser"
298
- version = "0.41.0"
299
- source = "registry+https://github.com/rust-lang/crates.io-index"
300
- checksum = "5cc2c25a6c66789625ef164b4c7d2e548d627902280c13710d33da8222169964"
301
- dependencies = [
302
- "log",
303
- "sqlparser_derive",
304
- ]
305
-
306
- [[package]]
307
- name = "sqlparser_derive"
308
- version = "0.2.1"
309
- source = "registry+https://github.com/rust-lang/crates.io-index"
310
- checksum = "3e9c2e1dde0efa87003e7923d94a90f46e3274ad1649f51de96812be561f041f"
311
- dependencies = [
312
- "proc-macro2",
313
- "quote",
314
- "syn 1.0.109",
315
- ]
316
-
317
- [[package]]
318
- name = "syn"
319
- version = "1.0.109"
320
- source = "registry+https://github.com/rust-lang/crates.io-index"
321
- checksum = "72b64191b275b66ffe2469e8af2c1cfe3bafa67b529ead792a6d0160888b4237"
322
- dependencies = [
323
- "proc-macro2",
324
- "quote",
325
- "unicode-ident",
326
- ]
327
-
328
- [[package]]
329
- name = "syn"
330
- version = "2.0.45"
331
- source = "registry+https://github.com/rust-lang/crates.io-index"
332
- checksum = "0eae3c679c56dc214320b67a1bc04ef3dfbd6411f6443974b5e4893231298e66"
333
- dependencies = [
334
- "proc-macro2",
335
- "quote",
336
- "unicode-ident",
337
- ]
338
-
339
- [[package]]
340
- name = "tap"
341
- version = "1.0.1"
342
- source = "registry+https://github.com/rust-lang/crates.io-index"
343
- checksum = "55937e1799185b12863d447f42597ed69d9928686b8d88a1df17376a097d8369"
344
-
345
- [[package]]
346
- name = "unicode-ident"
347
- version = "1.0.12"
348
- source = "registry+https://github.com/rust-lang/crates.io-index"
349
- checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b"
350
-
351
- [[package]]
352
- name = "windows-sys"
353
- version = "0.48.0"
354
- source = "registry+https://github.com/rust-lang/crates.io-index"
355
- checksum = "677d2418bec65e3338edb076e806bc1ec15693c5d0104683f2efe857f61056a9"
356
- dependencies = [
357
- "windows-targets",
358
- ]
359
-
360
- [[package]]
361
- name = "windows-targets"
362
- version = "0.48.5"
363
- source = "registry+https://github.com/rust-lang/crates.io-index"
364
- checksum = "9a2fa6e2155d7247be68c096456083145c183cbbbc2764150dda45a87197940c"
365
- dependencies = [
366
- "windows_aarch64_gnullvm",
367
- "windows_aarch64_msvc",
368
- "windows_i686_gnu",
369
- "windows_i686_msvc",
370
- "windows_x86_64_gnu",
371
- "windows_x86_64_gnullvm",
372
- "windows_x86_64_msvc",
373
- ]
374
-
375
- [[package]]
376
- name = "windows_aarch64_gnullvm"
377
- version = "0.48.5"
378
- source = "registry+https://github.com/rust-lang/crates.io-index"
379
- checksum = "2b38e32f0abccf9987a4e3079dfb67dcd799fb61361e53e2882c3cbaf0d905d8"
380
-
381
- [[package]]
382
- name = "windows_aarch64_msvc"
383
- version = "0.48.5"
384
- source = "registry+https://github.com/rust-lang/crates.io-index"
385
- checksum = "dc35310971f3b2dbbf3f0690a219f40e2d9afcf64f9ab7cc1be722937c26b4bc"
386
-
387
- [[package]]
388
- name = "windows_i686_gnu"
389
- version = "0.48.5"
390
- source = "registry+https://github.com/rust-lang/crates.io-index"
391
- checksum = "a75915e7def60c94dcef72200b9a8e58e5091744960da64ec734a6c6e9b3743e"
392
-
393
- [[package]]
394
- name = "windows_i686_msvc"
395
- version = "0.48.5"
396
- source = "registry+https://github.com/rust-lang/crates.io-index"
397
- checksum = "8f55c233f70c4b27f66c523580f78f1004e8b5a8b659e05a4eb49d4166cca406"
398
-
399
- [[package]]
400
- name = "windows_x86_64_gnu"
401
- version = "0.48.5"
402
- source = "registry+https://github.com/rust-lang/crates.io-index"
403
- checksum = "53d40abd2583d23e4718fddf1ebec84dbff8381c07cae67ff7768bbf19c6718e"
404
-
405
- [[package]]
406
- name = "windows_x86_64_gnullvm"
407
- version = "0.48.5"
408
- source = "registry+https://github.com/rust-lang/crates.io-index"
409
- checksum = "0b7b52767868a23d5bab768e390dc5f5c55825b6d30b86c844ff2dc7414044cc"
410
-
411
- [[package]]
412
- name = "windows_x86_64_msvc"
413
- version = "0.48.5"
414
- source = "registry+https://github.com/rust-lang/crates.io-index"
415
- checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
data/Cargo.toml DELETED
@@ -1,7 +0,0 @@
1
- # This Cargo.toml is here to let externals tools (IDEs, etc.) know that this is
2
- # a Rust project. Your extensions dependencies should be added to the Cargo.toml
3
- # in the ext/ directory.
4
-
5
- [workspace]
6
- members = ["./ext/rack_dev_insight"]
7
- resolver = "2"
@@ -1,20 +0,0 @@
1
- [package]
2
- name = "rack_dev_insight"
3
- version = "0.1.0"
4
- edition = "2021"
5
- authors = ["Takahiro Ebato <takahiro.ebato@gmail.com>"]
6
- license = "MIT"
7
- publish = false
8
-
9
- [lib]
10
- crate-type = ["cdylib"]
11
-
12
- [dependencies]
13
- magnus = { version = "0.6.2" } # add features = ["embed"] when cargo build
14
- sqlparser = { version = "0.41.0", features = ["visitor"] }
15
- tap = { version = "1.0.1" }
16
- indoc = { version = "2" }
17
-
18
- [dev-dependencies]
19
- magnus = { version = "0.6.2", features = ["embed"] }
20
- rb-sys-test-helpers = { version = "0.2" }
@@ -1,6 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- require 'mkmf'
4
- require 'rb_sys/mkmf'
5
-
6
- create_rust_makefile('rack/dev_insight/rack_dev_insight')
@@ -1,32 +0,0 @@
1
- use magnus::{class, exception::ExceptionClass, prelude::*, value::Lazy, RClass, RModule};
2
-
3
- // define module Rack
4
- pub static RACK: Lazy<RModule> = Lazy::new(|ruby| ruby.define_module("Rack").unwrap());
5
-
6
- // define class Rack::DevInsight
7
- pub static DEV_INSIGHT: Lazy<RClass> = Lazy::new(|ruby| {
8
- ruby.get_inner(&RACK)
9
- .define_class("DevInsight", class::object())
10
- .unwrap()
11
- });
12
-
13
- // define class Rack::DevInsight::Error < StandardError
14
- pub static ERROR: Lazy<ExceptionClass> = Lazy::new(|ruby| {
15
- ruby.get_inner(&DEV_INSIGHT)
16
- .define_error("Error", ruby.exception_standard_error())
17
- .unwrap()
18
- });
19
-
20
- // define class Rack::DevInsight::ExtError < Rack::DevInsight::Error
21
- pub static EXT_ERROR: Lazy<ExceptionClass> = Lazy::new(|ruby| {
22
- ruby.get_inner(&DEV_INSIGHT)
23
- .define_error("ExtError", ruby.get_inner(&ERROR))
24
- .unwrap()
25
- });
26
-
27
- // define class Rack::DevInsight::ParserError < Rack::DevInsight::ExtError
28
- pub static PARSER_ERROR: Lazy<ExceptionClass> = Lazy::new(|ruby| {
29
- ruby.get_inner(&DEV_INSIGHT)
30
- .define_error("ParserError", ruby.get_inner(&EXT_ERROR))
31
- .unwrap()
32
- });
@@ -1,354 +0,0 @@
1
- use std::collections::HashMap;
2
- use std::ops::ControlFlow;
3
-
4
- use crate::errors::PARSER_ERROR;
5
- use magnus::{Error, Ruby};
6
- use sqlparser::ast::TableFactor::Table;
7
- use sqlparser::ast::{Statement, TableFactor, Visit, Visitor};
8
- use sqlparser::dialect::dialect_from_str;
9
- use sqlparser::parser::Parser;
10
- use tap::Tap;
11
-
12
- #[derive(Default, Debug, PartialEq)]
13
- #[magnus::wrap(class = "Rack::DevInsight::Extractor::CrudTables")]
14
- pub struct CrudTables {
15
- create_tables: Vec<String>,
16
- read_tables: Vec<String>,
17
- update_tables: Vec<String>,
18
- delete_tables: Vec<String>,
19
- }
20
-
21
- impl CrudTables {
22
- pub fn create_tables(&self) -> Vec<String> {
23
- self.create_tables.clone()
24
- }
25
- pub fn read_tables(&self) -> Vec<String> {
26
- self.read_tables.clone()
27
- }
28
- pub fn update_tables(&self) -> Vec<String> {
29
- self.update_tables.clone()
30
- }
31
- pub fn delete_tables(&self) -> Vec<String> {
32
- self.delete_tables.clone()
33
- }
34
- }
35
-
36
- #[derive(Default, Debug)]
37
- pub struct CrudTableExtractor {
38
- create_tables: Vec<String>,
39
- read_tables: Vec<String>,
40
- update_tables: Vec<String>,
41
- delete_tables: Vec<String>,
42
- aliases: HashMap<String, String>,
43
- to_subtract_from_read: Vec<String>,
44
- }
45
-
46
- impl Visitor for CrudTableExtractor {
47
- type Break = ();
48
-
49
- fn pre_visit_table_factor(&mut self, table_factor: &TableFactor) -> ControlFlow<Self::Break> {
50
- if let Table { name, alias, .. } = table_factor {
51
- self.read_tables.push(name.0[0].value.clone());
52
- if let Some(alias) = alias {
53
- self.aliases
54
- .insert(alias.name.value.clone(), name.0[0].value.clone());
55
- }
56
- }
57
- ControlFlow::Continue(())
58
- }
59
-
60
- fn pre_visit_statement(&mut self, statement: &Statement) -> ControlFlow<Self::Break> {
61
- match statement {
62
- Statement::Insert { table_name, .. } => {
63
- self.create_tables.push(table_name.0[0].value.clone());
64
- self.to_subtract_from_read
65
- .push(table_name.0[0].value.clone());
66
- }
67
- Statement::Update { table, .. } => {
68
- if let Table { name, .. } = &table.relation {
69
- self.update_tables.push(name.0[0].value.clone());
70
- self.to_subtract_from_read.push(name.0[0].value.clone());
71
- }
72
- }
73
- Statement::Delete {
74
- tables,
75
- from,
76
- using,
77
- ..
78
- } => {
79
- if !tables.is_empty() {
80
- for obj_name in tables {
81
- self.delete_tables.push(obj_name.0[0].value.clone());
82
- self.to_subtract_from_read.push(obj_name.0[0].value.clone());
83
- }
84
- } else {
85
- for table_with_joins in from {
86
- if let Table { name, .. } = &table_with_joins.relation {
87
- self.delete_tables.push(name.0[0].value.clone());
88
- self.to_subtract_from_read.push(name.0[0].value.clone());
89
- // subtract again since using contains the same table
90
- if using.is_some() {
91
- self.to_subtract_from_read.push(name.0[0].value.clone());
92
- }
93
- }
94
- }
95
- }
96
- }
97
- _ => {}
98
- }
99
- ControlFlow::Continue(())
100
- }
101
- }
102
-
103
- impl CrudTableExtractor {
104
- pub fn extract(
105
- ruby: &Ruby,
106
- dialect_name: String,
107
- subject: String,
108
- ) -> Result<CrudTables, Error> {
109
- let statements = match dialect_from_str(dialect_name) {
110
- Some(dialect) => match Parser::parse_sql(dialect.as_ref(), &subject) {
111
- Ok(statements) => statements,
112
- Err(error) => {
113
- return Err(Error::new(ruby.get_inner(&PARSER_ERROR), error.to_string()));
114
- }
115
- },
116
- None => {
117
- return Err(Error::new(
118
- magnus::exception::arg_error(),
119
- "Dialect not found",
120
- ));
121
- }
122
- };
123
- let mut visitor = CrudTableExtractor::default();
124
- statements.visit(&mut visitor);
125
- let create_tables = visitor
126
- .convert_alias_to_original(visitor.create_tables.clone())
127
- .tap_mut(|vec| vec.sort());
128
- let read_tables = visitor
129
- .convert_alias_to_original(visitor.read_tables.clone())
130
- .tap_mut(|vec| vec.sort());
131
- let update_tables = visitor
132
- .convert_alias_to_original(visitor.update_tables.clone())
133
- .tap_mut(|vec| vec.sort());
134
- let delete_tables = visitor
135
- .convert_alias_to_original(visitor.delete_tables.clone())
136
- .tap_mut(|vec| vec.sort());
137
- Ok(CrudTables {
138
- read_tables: visitor.subtract(
139
- read_tables,
140
- visitor.convert_alias_to_original(visitor.to_subtract_from_read.clone()),
141
- ),
142
- create_tables,
143
- update_tables,
144
- delete_tables,
145
- })
146
- }
147
-
148
- fn convert_alias_to_original(&self, tables: Vec<String>) -> Vec<String> {
149
- tables
150
- .into_iter()
151
- .map(|table| {
152
- if let Some(original) = self.aliases.get(&table) {
153
- original.clone()
154
- } else {
155
- table
156
- }
157
- })
158
- .collect()
159
- }
160
-
161
- fn subtract(&self, read_tables: Vec<String>, mut to_subtracts: Vec<String>) -> Vec<String> {
162
- read_tables
163
- .into_iter()
164
- .filter(|read| {
165
- if let Some(pos) = to_subtracts.iter().position(|sub| sub == read) {
166
- to_subtracts.remove(pos);
167
- false
168
- } else {
169
- true
170
- }
171
- })
172
- .collect()
173
- }
174
- }
175
-
176
- // Thorough tests are written in Ruby. Basic cases are here for sanity check and to help debug.
177
- #[cfg(test)]
178
- mod tests {
179
- use super::*;
180
- use indoc::indoc;
181
- use rb_sys_test_helpers::with_ruby_vm;
182
-
183
- #[test]
184
- fn test_select_statement() {
185
- with_ruby_vm(|| {
186
- let ruby = Ruby::get().unwrap();
187
- let sql = "SELECT a FROM t1 WHERE b = 1 AND c in (2, 3) AND d LIKE '%foo'; SELECT b FROM t2 WHERE c = 4";
188
- match CrudTableExtractor::extract(&ruby, String::from("mysql"), sql.into()) {
189
- Ok(result) => assert_eq!(result, CrudTables {
190
- create_tables: vec![],
191
- read_tables: vec!["t1".to_string(), "t2".to_string()],
192
- update_tables: vec![],
193
- delete_tables: vec![],
194
- }),
195
- Err(error) => unreachable!("Should not have errored. Error: {}", error)
196
- }
197
- }).unwrap()
198
- }
199
-
200
- #[test]
201
- fn test_complicated_select_statement() {
202
- with_ruby_vm(|| {
203
- let ruby = Ruby::get().unwrap();
204
- let sql = indoc! {" \
205
- SELECT a \
206
- FROM t1 \
207
- INNER JOIN t2 ON t1.b = t2.b \
208
- WHERE c IN ( \
209
- SELECT c \
210
- FROM t3 \
211
- WHERE d = 1 \
212
- ) \
213
- "};
214
- match CrudTableExtractor::extract(&ruby, String::from("mysql"), sql.into()) {
215
- Ok(result) => assert_eq!(
216
- result,
217
- CrudTables {
218
- create_tables: vec![],
219
- read_tables: vec!["t1".to_string(), "t2".to_string(), "t3".to_string()],
220
- update_tables: vec![],
221
- delete_tables: vec![],
222
- }
223
- ),
224
- Err(error) => unreachable!("Should not have errored. Error: {}", error),
225
- }
226
- })
227
- .unwrap()
228
- }
229
-
230
- #[test]
231
- fn test_complicated_insert_statement() {
232
- with_ruby_vm(|| {
233
- let ruby = Ruby::get().unwrap();
234
- let sql = indoc! {" \
235
- INSERT INTO t1 (a, b) \
236
- SELECT t2_alias.a, t2_alias.b \
237
- FROM t2 t2_alias \
238
- INNER JOIN t3 t3_alias ON t2_alias.c = t3_alias.c \
239
- WHERE t3_alias.d IN ( \
240
- SELECT d \
241
- FROM t4 \
242
- WHERE e = 1 \
243
- ) \
244
- "};
245
- match CrudTableExtractor::extract(&ruby, String::from("mysql"), sql.into()) {
246
- Ok(result) => assert_eq!(
247
- result,
248
- CrudTables {
249
- create_tables: vec!["t1".to_string()],
250
- read_tables: vec!["t2".to_string(), "t3".to_string(), "t4".to_string()],
251
- update_tables: vec![],
252
- delete_tables: vec![],
253
- }
254
- ),
255
- Err(error) => unreachable!("Should not have errored. Error: {}", error),
256
- }
257
- })
258
- .unwrap()
259
- }
260
-
261
- #[test]
262
- fn test_complicated_update_statement() {
263
- with_ruby_vm(|| {
264
- let ruby = Ruby::get().unwrap();
265
- let sql = indoc! {"\
266
- UPDATE t1
267
- JOIN t2 ON t1.a = t2.a
268
- JOIN t3 ON t2.a = t3.a
269
- LEFT JOIN t4 ON t1.d = t4.a
270
- SET t1.b = t2.b, t1.c = t3.c
271
- WHERE t4.b = 1
272
- AND t2.e = 2
273
- AND t3.f = 3
274
- "};
275
- match CrudTableExtractor::extract(&ruby, String::from("mysql"), sql.into()) {
276
- Ok(result) => assert_eq!(
277
- result,
278
- CrudTables {
279
- create_tables: vec![],
280
- read_tables: vec!["t2".to_string(), "t3".to_string(), "t4".to_string()],
281
- update_tables: vec!["t1".to_string()],
282
- delete_tables: vec![],
283
- }
284
- ),
285
- Err(error) => unreachable!("Should not have errored. Error: {}", error),
286
- }
287
- })
288
- .unwrap()
289
- }
290
-
291
- #[test]
292
- fn test_complicated_delete_statement() {
293
- with_ruby_vm(|| {
294
- let ruby = Ruby::get().unwrap();
295
- let sql = indoc! {" \
296
- DELETE t1_alias, t2_alias \
297
- FROM t1 AS t1_alias \
298
- INNER JOIN t2 AS t2_alias ON t1_alias.a = t2_alias.a \
299
- WHERE t1.b IN ( \
300
- SELECT b \
301
- FROM t3 \
302
- WHERE c = 1 \
303
- ) \
304
- "};
305
- match CrudTableExtractor::extract(&ruby, String::from("mysql"), sql.into()) {
306
- Ok(result) => assert_eq!(
307
- result,
308
- CrudTables {
309
- create_tables: vec![],
310
- read_tables: vec!["t3".to_string()],
311
- update_tables: vec![],
312
- delete_tables: vec!["t1".to_string(), "t2".to_string()],
313
- }
314
- ),
315
- Err(error) => unreachable!("Should not have errored. Error: {}", error),
316
- }
317
- })
318
- .unwrap()
319
- }
320
-
321
- #[test]
322
- fn test_multiple_statements() {
323
- with_ruby_vm(|| {
324
- let ruby = Ruby::get().unwrap();
325
- let sql = "SELECT a FROM t1 WHERE b = 1; INSERT INTO t2 (a, b) VALUES (1, 2); UPDATE t3 SET a = 1 WHERE b = 2; DELETE FROM t4 WHERE a = 1";
326
- match CrudTableExtractor::extract(&ruby, String::from("mysql"), sql.into()) {
327
- Ok(result) => assert_eq!(
328
- result,
329
- CrudTables {
330
- create_tables: vec!["t2".to_string()],
331
- read_tables: vec!["t1".to_string()],
332
- update_tables: vec!["t3".to_string()],
333
- delete_tables: vec!["t4".to_string()],
334
- }
335
- ),
336
- Err(error) => unreachable!("Should not have errored. Error: {}", error),
337
- }
338
- })
339
- .unwrap()
340
- }
341
-
342
- #[test]
343
- fn test_invalid_sql() {
344
- with_ruby_vm(|| {
345
- let ruby = Ruby::get().unwrap();
346
- let sql = "SELECT a FROM t1 WHERE b = 1 WHERE c in (2, 3";
347
- match CrudTableExtractor::extract(&ruby, String::from("mysql"), sql.into()) {
348
- Ok(_) => unreachable!("Should have errored"),
349
- Err(error) => assert!(error.is_kind_of(ruby.get_inner(&PARSER_ERROR))),
350
- }
351
- })
352
- .unwrap()
353
- }
354
- }
@@ -1,31 +0,0 @@
1
- use extractor::CrudTableExtractor;
2
- use extractor::CrudTables;
3
- use magnus::{class, define_module, function, method, prelude::*, Error};
4
- use normalizer::Normalizer;
5
-
6
- mod errors;
7
- mod extractor;
8
- mod normalizer;
9
-
10
- #[magnus::init]
11
- fn init() -> Result<(), Error> {
12
- let rack_module = define_module("Rack").unwrap();
13
- let dev_insight_class = rack_module
14
- .define_class("DevInsight", class::object())
15
- .unwrap();
16
-
17
- let normalizer_module = dev_insight_class.define_module("Normalizer").unwrap();
18
- normalizer_module.define_singleton_method("_normalize", function!(Normalizer::normalize, 2))?;
19
-
20
- let extractor_module = dev_insight_class.define_module("Extractor").unwrap();
21
- let crud_tables_class = extractor_module
22
- .define_class("CrudTables", class::object())
23
- .unwrap();
24
- crud_tables_class
25
- .define_singleton_method("_extract", function!(CrudTableExtractor::extract, 2))?;
26
- crud_tables_class.define_method("_create_tables", method!(CrudTables::create_tables, 0))?;
27
- crud_tables_class.define_method("_read_tables", method!(CrudTables::read_tables, 0))?;
28
- crud_tables_class.define_method("_update_tables", method!(CrudTables::update_tables, 0))?;
29
- crud_tables_class.define_method("_delete_tables", method!(CrudTables::delete_tables, 0))?;
30
- Ok(())
31
- }
@@ -1,97 +0,0 @@
1
- use std::ops::ControlFlow;
2
-
3
- use crate::errors::PARSER_ERROR;
4
- use magnus::{exception, Error, Ruby};
5
- use sqlparser::ast::Value::Placeholder;
6
- use sqlparser::ast::{Expr, VisitMut, VisitorMut};
7
- use sqlparser::dialect::dialect_from_str;
8
- use sqlparser::parser::Parser;
9
-
10
- pub struct Normalizer;
11
-
12
- impl VisitorMut for Normalizer {
13
- type Break = ();
14
-
15
- fn post_visit_expr(&mut self, expr: &mut Expr) -> ControlFlow<Self::Break> {
16
- if let Expr::Value(value) = expr {
17
- *value = Placeholder("?".into());
18
- }
19
- ControlFlow::Continue(())
20
- }
21
- }
22
-
23
- impl Normalizer {
24
- pub fn normalize(
25
- ruby: &Ruby,
26
- dialect_name: String,
27
- subject: String,
28
- ) -> Result<Vec<String>, Error> {
29
- let mut statements = match dialect_from_str(&dialect_name) {
30
- Some(dialect) => match Parser::parse_sql(dialect.as_ref(), &subject) {
31
- Ok(statements) => statements,
32
- Err(error) => {
33
- return Err(Error::new(ruby.get_inner(&PARSER_ERROR), error.to_string()))
34
- }
35
- },
36
- None => {
37
- return Err(Error::new(
38
- exception::arg_error(),
39
- format!("Dialect not found {}", dialect_name),
40
- ))
41
- }
42
- };
43
- statements.visit(&mut Self);
44
- Ok(statements
45
- .into_iter()
46
- .map(|statement| statement.to_string())
47
- .collect::<Vec<String>>())
48
- }
49
- }
50
-
51
- // Thorough tests are written in Ruby. Basic cases are here for sanity check and to help debug.
52
- #[cfg(test)]
53
- mod tests {
54
- use super::*;
55
- use rb_sys_test_helpers::with_ruby_vm;
56
-
57
- #[test]
58
- fn test_single_sql() {
59
- with_ruby_vm(|| {
60
- let ruby = Ruby::get().unwrap();
61
- let sql = "SELECT a FROM t1 WHERE b = 1 AND c in (2, 3) AND d LIKE '%foo'";
62
- match Normalizer::normalize(&ruby, String::from("mysql"), sql.into()) {
63
- Ok(result) => assert_eq!(
64
- result,
65
- ["SELECT a FROM t1 WHERE b = ? AND c IN (?, ?) AND d LIKE ?"]
66
- ),
67
- Err(error) => unreachable!("Should not have errored. Error: {}", error),
68
- }
69
- })
70
- .unwrap();
71
- }
72
-
73
- #[test]
74
- fn test_multiple_sqls() {
75
- with_ruby_vm(|| {
76
- let ruby = Ruby::get().unwrap();
77
- let sql = "SELECT a FROM t1 WHERE b = 1 AND c in (2, 3) AND d LIKE '%foo'; SELECT a FROM t1 WHERE b = 1 AND c in (2, 3) AND d LIKE '%foo'";
78
- match Normalizer::normalize(&ruby, String::from("mysql"), sql.into()) {
79
- Ok(result) => assert_eq!(result, ["SELECT a FROM t1 WHERE b = ? AND c IN (?, ?) AND d LIKE ?", "SELECT a FROM t1 WHERE b = ? AND c IN (?, ?) AND d LIKE ?"]),
80
- Err(error) => unreachable!("Should not have errored. Error: {}", error)
81
- }
82
- }).unwrap();
83
- }
84
-
85
- #[test]
86
- fn test_incorrect_sql() {
87
- with_ruby_vm(|| {
88
- let ruby = Ruby::get().unwrap();
89
- let invalid_sql = "SELECT a FROM t1 WHERE b = 1 WHERE c in (2, 3)";
90
- match Normalizer::normalize(&ruby, String::from("mysql"), invalid_sql.into()) {
91
- Ok(_) => unreachable!("Should have errored"),
92
- Err(error) => assert!(error.is_kind_of(ruby.get_inner(&PARSER_ERROR))),
93
- }
94
- })
95
- .unwrap();
96
- }
97
- }
@@ -1,21 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Rack
4
- class DevInsight
5
- module Extractor
6
- class CrudTables
7
- class << self
8
- def extract(dialect_name, statement)
9
- crud_tables = _extract(dialect_name, statement)
10
- {
11
- 'CREATE' => crud_tables._create_tables,
12
- 'READ' => crud_tables._read_tables,
13
- 'UPDATE' => crud_tables._update_tables,
14
- 'DELETE' => crud_tables._delete_tables,
15
- }
16
- end
17
- end
18
- end
19
- end
20
- end
21
- end