finox 0.1.0-aarch64-linux → 0.2.0-aarch64-linux
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +25 -1
- data/LICENSE-THIRD-PARTY.txt +1095 -0
- data/README.md +89 -17
- data/lib/finox/3.1/finox.so +0 -0
- data/lib/finox/3.2/finox.so +0 -0
- data/lib/finox/3.3/finox.so +0 -0
- data/lib/finox/3.4/finox.so +0 -0
- data/lib/finox/4.0/finox.so +0 -0
- data/lib/finox/version.rb +1 -1
- metadata +5 -5
- data/.rspec +0 -3
- data/.rubocop.yml +0 -8
data/README.md
CHANGED
|
@@ -2,44 +2,49 @@
|
|
|
2
2
|
|
|
3
3
|
A MySQL query parser for Ruby, powered by [sqlparser-rs](https://github.com/apache/datafusion-sqlparser-rs).
|
|
4
4
|
|
|
5
|
-
Finox parses SQL with Rust and
|
|
5
|
+
Finox parses SQL with Rust and exposes tables, columns, fingerprints and the raw AST.
|
|
6
6
|
|
|
7
7
|
## Installation
|
|
8
8
|
|
|
9
|
-
Add to your Gemfile:
|
|
10
|
-
|
|
11
9
|
```bash
|
|
12
10
|
bundle add finox
|
|
13
11
|
```
|
|
14
12
|
|
|
15
|
-
Or
|
|
13
|
+
Or without Bundler:
|
|
16
14
|
|
|
17
15
|
```bash
|
|
18
16
|
gem install finox
|
|
19
17
|
```
|
|
20
18
|
|
|
21
|
-
|
|
19
|
+
Precompiled native gems are available for Ruby 3.1–4.0 on the following
|
|
20
|
+
platforms, so installation there requires no Rust toolchain:
|
|
21
|
+
|
|
22
|
+
| OS | Platforms |
|
|
23
|
+
| ------- | ------------------------------------------------ |
|
|
24
|
+
| Linux | x86_64, aarch64 (glibc and musl variants) |
|
|
25
|
+
| macOS | x86_64, arm64 |
|
|
26
|
+
| Windows | x64-mingw-ucrt |
|
|
27
|
+
|
|
28
|
+
On any other platform the source gem is installed instead, and compiling it
|
|
29
|
+
requires a Rust toolchain.
|
|
22
30
|
|
|
23
31
|
## Usage
|
|
24
32
|
|
|
33
|
+
`Finox.parse` returns a `Finox::Result`:
|
|
34
|
+
|
|
25
35
|
```ruby
|
|
26
36
|
require "finox"
|
|
27
37
|
|
|
28
|
-
|
|
29
|
-
# =>
|
|
38
|
+
result = Finox.parse("SELECT `name` FROM `users` WHERE id = 1")
|
|
39
|
+
# => #<Finox::Result>
|
|
30
40
|
|
|
31
|
-
|
|
32
|
-
# => [
|
|
33
|
-
#
|
|
34
|
-
#
|
|
35
|
-
#
|
|
36
|
-
# span: {start: {line: 1, column: 8}, end: {line: 1, column: 14}}}}}]
|
|
41
|
+
result.tables # => ["users"]
|
|
42
|
+
result.columns # => ["name", "id"]
|
|
43
|
+
result.statement_types # => ["Query"]
|
|
44
|
+
result.normalize # => "SELECT `name` FROM `users` WHERE id = ?"
|
|
45
|
+
result.fingerprint # => "24e307ca0f02abfc"
|
|
37
46
|
```
|
|
38
47
|
|
|
39
|
-
`Finox.parse` returns one Hash per statement, so `"SELECT 1; SELECT 2"` yields an array of two.
|
|
40
|
-
|
|
41
|
-
Key convention (from serde's externally tagged enums): enum variant names are `String` keys (`"Query"`, `"Select"`, `"Identifier"`), struct fields are `Symbol` keys (`:body`, `:projection`, `:value`).
|
|
42
|
-
|
|
43
48
|
Invalid SQL raises `Finox::ParseError`:
|
|
44
49
|
|
|
45
50
|
```ruby
|
|
@@ -47,6 +52,69 @@ Finox.parse("SELEKT 1")
|
|
|
47
52
|
# => Finox::ParseError: sql parser error: Expected: an SQL statement, found: SELEKT at Line: 1, Column: 1
|
|
48
53
|
```
|
|
49
54
|
|
|
55
|
+
### Table classification
|
|
56
|
+
|
|
57
|
+
`#select_tables`, `#dml_tables` and `#ddl_tables` classify the referenced
|
|
58
|
+
tables by how they are used: read, written by DML (`INSERT` / `UPDATE` /
|
|
59
|
+
`DELETE`) or targeted by DDL (`CREATE TABLE` / `ALTER TABLE` / `DROP TABLE` /
|
|
60
|
+
`TRUNCATE` etc.). A table appearing in multiple roles is listed in each.
|
|
61
|
+
|
|
62
|
+
```ruby
|
|
63
|
+
result = Finox.parse("INSERT INTO logs SELECT message FROM events; DROP TABLE archives")
|
|
64
|
+
|
|
65
|
+
result.tables # => ["logs", "events", "archives"]
|
|
66
|
+
result.select_tables # => ["events"]
|
|
67
|
+
result.dml_tables # => ["logs"]
|
|
68
|
+
result.ddl_tables # => ["archives"]
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
#### Known limitations
|
|
72
|
+
|
|
73
|
+
Extraction is syntactic, with no schema knowledge and only coarse scope
|
|
74
|
+
resolution:
|
|
75
|
+
|
|
76
|
+
- A CTE name shadows a same-named real table everywhere in the statement,
|
|
77
|
+
even inside the CTE's own definition.
|
|
78
|
+
- Multi-table `UPDATE` (`UPDATE t1 JOIN t2 ... SET t2.x = 1`) reports only
|
|
79
|
+
`t1` in `#dml_tables`.
|
|
80
|
+
- `#columns` does not resolve table aliases (`u.id` stays `u.id`).
|
|
81
|
+
|
|
82
|
+
### Normalization and fingerprints
|
|
83
|
+
|
|
84
|
+
`#normalize` replaces literals with `?` placeholders and deparses from the
|
|
85
|
+
AST, so formatting and keyword case are normalized as well. `#fingerprint` is
|
|
86
|
+
a 64-bit hex hash (xxhash64) of the normalized SQL — stable across literal
|
|
87
|
+
and formatting differences, but not guaranteed to be stable across finox
|
|
88
|
+
versions, since the normalized form depends on the bundled sqlparser-rs.
|
|
89
|
+
Recompute stored fingerprints when upgrading finox.
|
|
90
|
+
|
|
91
|
+
```ruby
|
|
92
|
+
Finox.parse("select * from users where id=1").normalize
|
|
93
|
+
# => "SELECT * FROM users WHERE id = ?"
|
|
94
|
+
|
|
95
|
+
Finox.parse("select * from users where id=1").fingerprint ==
|
|
96
|
+
Finox.parse("SELECT * FROM users WHERE id = 42").fingerprint
|
|
97
|
+
# => true
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
### Raw sqlparser-rs AST
|
|
101
|
+
|
|
102
|
+
For anything not covered above, `#statements` exposes sqlparser-rs's raw AST of each parsed statement as plain
|
|
103
|
+
Ruby Hashes and Arrays:
|
|
104
|
+
|
|
105
|
+
```ruby
|
|
106
|
+
ast = Finox.parse("SELECT `name` FROM `users` WHERE id = 1").statements.first
|
|
107
|
+
# => {"Query" => {"with" => nil, "body" => {"Select" => {...}}, ...}}
|
|
108
|
+
|
|
109
|
+
ast.dig("Query", "body", "Select", "projection")
|
|
110
|
+
# => [{"UnnamedExpr" =>
|
|
111
|
+
# {"Identifier" =>
|
|
112
|
+
# {"value" => "name",
|
|
113
|
+
# "quote_style" => "`",
|
|
114
|
+
# "span" => {"start" => {"line" => 1, "column" => 8},
|
|
115
|
+
# "end" => {"line" => 1, "column" => 14}}}}}]
|
|
116
|
+
```
|
|
117
|
+
|
|
50
118
|
## Development
|
|
51
119
|
|
|
52
120
|
```bash
|
|
@@ -58,3 +126,7 @@ bundle exec rake # compile + spec + rubocop
|
|
|
58
126
|
## License
|
|
59
127
|
|
|
60
128
|
[MIT](LICENSE.txt)
|
|
129
|
+
|
|
130
|
+
Precompiled gems statically link Rust crates, including sqlparser-rs
|
|
131
|
+
(Apache-2.0). See [LICENSE-THIRD-PARTY.txt](LICENSE-THIRD-PARTY.txt) for
|
|
132
|
+
their licenses and attributions.
|
data/lib/finox/3.1/finox.so
CHANGED
|
Binary file
|
data/lib/finox/3.2/finox.so
CHANGED
|
Binary file
|
data/lib/finox/3.3/finox.so
CHANGED
|
Binary file
|
data/lib/finox/3.4/finox.so
CHANGED
|
Binary file
|
|
Binary file
|
data/lib/finox/version.rb
CHANGED
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: finox
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: aarch64-linux
|
|
6
6
|
authors:
|
|
7
7
|
- kyuuri1791
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: exe
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2026-07-
|
|
11
|
+
date: 2026-07-18 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
13
|
description: Parses MySQL queries with the Rust sqlparser crate (via magnus) and returns
|
|
14
14
|
the AST as plain Ruby Hashes and Arrays.
|
|
@@ -17,9 +17,8 @@ executables: []
|
|
|
17
17
|
extensions: []
|
|
18
18
|
extra_rdoc_files: []
|
|
19
19
|
files:
|
|
20
|
-
- ".rspec"
|
|
21
|
-
- ".rubocop.yml"
|
|
22
20
|
- CHANGELOG.md
|
|
21
|
+
- LICENSE-THIRD-PARTY.txt
|
|
23
22
|
- LICENSE.txt
|
|
24
23
|
- README.md
|
|
25
24
|
- Rakefile
|
|
@@ -28,6 +27,7 @@ files:
|
|
|
28
27
|
- lib/finox/3.2/finox.so
|
|
29
28
|
- lib/finox/3.3/finox.so
|
|
30
29
|
- lib/finox/3.4/finox.so
|
|
30
|
+
- lib/finox/4.0/finox.so
|
|
31
31
|
- lib/finox/version.rb
|
|
32
32
|
homepage: https://github.com/kyuuri1791/finox
|
|
33
33
|
licenses:
|
|
@@ -48,7 +48,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
|
48
48
|
version: '3.1'
|
|
49
49
|
- - "<"
|
|
50
50
|
- !ruby/object:Gem::Version
|
|
51
|
-
version:
|
|
51
|
+
version: 4.1.dev
|
|
52
52
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
53
53
|
requirements:
|
|
54
54
|
- - ">="
|
data/.rspec
DELETED