rack-dev_insight 0.2.2 → 0.3.0

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: 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