Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
SpannerのSQL解析ライブラリ "memefish" の紹介/gcpug-memefish-introduction
Search
TSUYUSATO Kitsune
February 06, 2020
Programming
3
1.1k
SpannerのSQL解析ライブラリ "memefish" の紹介/gcpug-memefish-introduction
GCPUG Tokyo Handy Spanner Day February 2020 (2020/02/06)での発表資料
TSUYUSATO Kitsune
February 06, 2020
Tweet
Share
More Decks by TSUYUSATO Kitsune
See All by TSUYUSATO Kitsune
正規表現改善報告する回 / Regexp memoization progress report
makenowjust
1
410
Make Regexp#match much faster
makenowjust
1
2.3k
ReDoS 検出の最先端 recheck の紹介 / State of the Art of ReDoS Detection
makenowjust
9
3.1k
ReDoS 検出プログラム recheck の開発 / recheck: ReDoS check program
makenowjust
0
98
Integrated Shrinking による 高階関数の自動生成 / PRO-2020-4 Generating Higher-Order Functions by Integrated Shrinking
makenowjust
0
110
ハイブリッド型ReDoS検出プログラムの実装 / PROSYM62 - A Hybrid Approach to Detect ReDoS
makenowjust
1
510
dali introduction
makenowjust
1
150
memefish the Spanner SQL parser and analyzer
makenowjust
0
2.9k
«le noir que j'ai créé»
makenowjust
0
860
Other Decks in Programming
See All in Programming
雑に思考を整理する技術と効能
konifar
55
25k
AWS Application Composerで始める、 サーバーレスなデータ基盤構築 / 20240406-jawsug-hokuriku-shinkansen
kasacchiful
1
250
OpenAPIを中心に考えるAPI開発入門 / Introduction to API Development with a Focus on OpenAPI
seike460
PRO
2
110
Git Lint
bkuhlmann
4
740
VSCodeでのDatabricks開発もお勧めしたい/I would also recommend Databricks development with VSCode.
kazumain
0
240
From Spring Boot 2 to Spring Boot 3 with Java 22 and Jakarta EE
ivargrimstad
0
880
ONE WEDGE_company_guide
1wedge_one
0
370
educure_カリキュラム生操作マニュアル.pdf
linew_official
0
460
[技育CAMPアカデミア]アイディアを形に!【超入門】スマホアプリ開発〜リリースまでの流れをご紹介
teamlab
PRO
0
340
ゆるい個人開発のススメ
kuroppe1819
10
930
Build with AI 2024 Seoul - 제로부터 시작하는 Flutter with Gemini 생활 - 박제창
itsmedreamwalker
0
200
1BRC--Nerd Sniping the Java Community
gunnarmorling
0
300
Featured
See All Featured
The Illustrated Children's Guide to Kubernetes
chrisshort
29
46k
Agile that works and the tools we love
rasmusluckow
324
20k
Fireside Chat
paigeccino
20
2.6k
Producing Creativity
orderedlist
PRO
336
39k
What’s in a name? Adding method to the madness
productmarketing
PRO
15
2.6k
Adopting Sorbet at Scale
ufuk
67
8.6k
Building Better People: How to give real-time feedback that sticks.
wjessup
354
18k
Intergalactic Javascript Robots from Outer Space
tanoku
266
26k
Statistics for Hackers
jakevdp
789
220k
How to train your dragon (web standard)
notwaldorf
72
5.1k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
60
14k
Building Applications with DynamoDB
mza
88
5.6k
Transcript
SpannerのSQL解析ライブラリ "memefish" の紹介 @MakeNowJust at GCPUG Tokyo Handy Spanner Day
February 2020 (2020/02/06) SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 1
⾃⼰紹介 HN: MakeNowJust 学⽣ 去年の夏にメルカリのインターンに参加していた 今回紹介するものも、インターンで開発したもの SpannerのSQL解析ライブラリ "memefish" の紹介 by
@MakeNowJust 2
SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 3
紹介するもの SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 4
méméfish méméfish méméfish https://makenowjust.github.io/memefish SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 5
memefish Spannerで使えるSQLを解析するためのGo⾔語のライブラリ (OSS) https://github.com/MakeNowJust/memefishで公開されている 主な機能 1. SQLのパース 2. 構⽂⽊からのSQLの⽣成 3.
SQLの意味解析・型チェック SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 6
memefishを使っているプロジェクト gcpug/handy-spanner mercari/yo SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 7
パッケージ構成 github.com/MakeNowJust/memefish/pkg 以下の重要なパッケージ token : パースに使うトークンやファイルの構造体を定義したパッケージ ast : パース結果のAST (抽象構⽂⽊)を定義したパッケージ
parser : パーサーの実装があるパッケージ analyzer : 型チェッカーのあるパッケージ go/token, go/ast, go/parser などのパッケージを参考にしている SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 8
主な機能 1. SQLのパース 2. 構⽂⽊からのSQLの⽣成 3. SQLの意味解析・型チェック 今⽇の主題 これらの機能がどのようなものなのか memefishでそれらの機能をどうやって使うのか
を説明します (前提知識: Go⾔語を知ってること) SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 9
1. SQLのパース・2. 構⽂⽊からのSQLの⽣成 SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 10
パースとは 与えられた⽂字列をSQLとして解釈して、対応する抽象構⽂⽊を組み⽴てること。 例: パースしたい⽂字列 SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 11
パース: Lexer そのまま抽象構⽂⽊を組み⽴てるのは難しいので、 まず意味のある最⼩の単位(トークン)に⽂字列を分割する。 トークンには、その部分の役割(キーワードか?識別⼦か?⽂字列リテラルか?など)も 記録されている。 SpannerのSQL解析ライブラリ "memefish" の紹介 by
@MakeNowJust 12
パース: Lexer この処理を⾏うオブジェクトを Lexer と呼ぶ。 SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust
13
パース: Parser Lexer によって分割されたトークンの列から抽象構⽂⽊を組み⽴てていく。 抽象構⽂⽊: SQLの各要素に対応する構造体 (⽊構造) この処理を⾏うオブジェクトを Parser と呼ぶ。
SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 14
使い⽅: import ⽂ まずは import 。 ast, token, parser を使う。
import ( "fmt" "log" "github.com/MakenowJust/memefish/pkg/ast" "github.com/MakenowJust/memefish/pkg/parser" "github.com/MakenowJust/memefish/pkg/token" ) SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 15
使い⽅: Parser の組み⽴て Parser は構造体なので必要なフィールドを埋めていく。 必要なフィールドは Lexer だけ。 ( Parser
が Lexer を使うので) また、パースしたい⽂字列は File という構造体に包む。 file := &token.File{ Buffer: "SELECT * FROM Singers WHERE FirstName = \"Foo\"", } p := &parser.Parser{ Lexer: &parser.Lexer{File: file}, } SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 16
使い⽅: ParseQuery の呼び出し 実際のパースは ParseQuery メソッドの呼び出しで⾏なわれる。 ParseQuery の返り値は抽象構⽂⽊とパース時のエラー。 stmt, err
:= p.ParseQuery() if err != nil { log.Fatal(err) } あとは、この stmt を使ってやりたいことをする。 stmt.Query.(*ast.Select).From.Source.(*ast.TableName).Table.Name == "Singers" // => true SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 17
使い⽅: まとめ パースしたい⽂字列を構造体 File に包む ↑を使って Lexer 、 Parser を作る
ParseQuery を呼び出してパースを実⾏する (DMLのパースなら ParseDML 、DDLのパースなら ParseDDL が使える) 結果の抽象構⽂⽊を使ってごにょごにょする SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 18
SQLの⽣成 抽象構⽂⽊の型 ast.Node の定義 type Node interface { Pos() token.Pos
End() token.Pos // Convert AST node into SQL source string (a.k.a. Unparse). SQL() string } この SQL() メソッドで、抽象構⽂⽊からSQLの⽂字列を⽣成できる。 SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 19
例: SQLの⽣成 さきほどまでのパースの例の続き // Singers の部分を Albums に差し替える stmt.Query.(*ast.Select).From.Source.(*ast.TableName).Table.Name =
"Albums" fmt.Println(stmt.SQL()) // Output: // SELECT * FROM Albums WHERE FirstName = "Foo" SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 20
3. SQLの意味解析・型チェック SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 21
意味解析・型チェック SQL中の 識別⼦がテーブル・カラム・変数名のどれなのか? 具体的には何を指しているのか? 式の結果がどのような型になるか? を求める機能。 (パースなどと⽐べるとやや不安定です……) SpannerのSQL解析ライブラリ "memefish" の紹介
by @MakeNowJust 22
意味解析・型チェック 意味解析の途中で、 存在しないテーブル・カラムを参照している おかしな操作をしている 例: ⽂字列と数値を⾜し合わせようとしている 例: WHERE の式が BOOL
値を返していない などのエラーが分かる。 SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 23
意味解析・型チェック: 疑問 Q. 実際にSpanner送って実⾏計画を⾒るなりすれば、それらのエラーは分かるのでは? memefishで意味解析をする場合、 1. ローカルで全て完結する (通信を伴わない) 2. 型情報や参照の情報をプログラムから利⽤できる
といったメリットがある。特に2番が重要。 SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 24
意味解析・型チェック: 使⽤イメージ 例えば、意味解析ではクエリの結果の各カラムがどのような名前・型なのかを取得できる。 これを利⽤すると、クエリからその結果に⼀致する構造体を⾃動⽣成する、 といったことができる。 SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust
25
意味解析・型チェック: 使⽤イメージ 例: SELECT CONCAT(FirstName, " ", LastName) AS Name,
BirthDate FROM Singers から type Result struct { Name string BirthDate time.Time } を⾃動⽣成 SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 26
→次のスライドから、これを作っていきます SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 27
使い⽅: import ⽂ 意味解析は抽象構⽂⽊に対して⾏うので、 parser, token のインポートも必要 import ( "fmt"
"log" "github.com/MakeNowJust/memefish/pkg/analyzer" "github.com/MakeNowJust/memefish/pkg/parser" "github.com/MakeNowJust/memefish/pkg/token" ) SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 28
使い⽅: パース まずはパースをする。(さっきと同じ) file := &token.File{ Buffer: "SELECT CONCAT(FirstName, \"
\", LastName) AS Name, BirthDate FROM Singers", } p := &parser.Parser{ Lexer: &parser.Lexer{File: file}, } stmt, err := p.ParseQuery() if err != nil { log.Fatal(err) } SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 29
使い⽅: Catalog の組み⽴て テーブルのスキーマ定義をまとめたものを Catalog と呼ぶ。 catalog := &analyzer.Catalog{ Tables:
map[string]*analyzer.TableSchema{ "SINGERS": { Name: "Singers", Columns: []*analyzer.ColumnSchema{ {Name: "FirstName", Type: analyzer.StringType}, {Name: "LastName", Type: analyzer.StringType}, {Name: "BirthDate", Type: analyzer.DateType}, }, }, }, } SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 30
使い⽅: Analyzer の組み⽴て Catalog と File を渡す必要がある。 File はエラー位置を実際のソースコードに対応させるために必要。 a
:= &analyzer.Analyzer{ File: file, Catalog: catalog, } SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 31
使い⽅: 意味解析の実⾏ AnalyzeQueryStatement に解析したい抽象構⽂⽊を渡すことで意味解析を実⾏できる。 返り値はエラーのみで、意味解析の結果は Analyzer ⾃⾝に保存される。 err = a.AnalyzeQueryStatement(stmt)
if err != nil { log.Fatal(err) } SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 32
使い⽅: 意味解析の結果を使う 例えば、 a.NameList には結果の各カラムの情報が保存されている。 これを使って、SQLの結果に対応する構造体の定義を出⼒する。 columns := a.NameLists[stmt.Query] fmt.Printf("type
Result struct {\n"); for _, column := range columns { fmt.Printf("\t%-9s %s\n", column.Text, mapSQLType(column.Type)) } fmt.Printf("}\n"); ( mapSQLType はSQLの型をGo⾔語の型に対応させる関数。省略) SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 33
使い⽅: まとめ 解析したいSQLをパースする スキーマをまとめた Catalog を組み⽴てる Catalog と File から
Analyzer を組み⽴てる AnalyzeQueryStatement に解析したい抽象構⽂⽊を渡す 意味解析の結果は Analyzer ⾃⾝に保存されている 他には Types フィールドに各式の型が保存されていたりする。 今回の例の全体は次のGo Playgroundから確認できます。 https://play.golang.org/p/PN5JuJKB-Mo SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 34
今回のまとめ SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 35
今回のまとめ memefishはSpannerのSQLをパース・意味解析できるGo⾔語のライブラリ SQL⽂をプログラムで扱うことができる ⾊々と⾯⽩いことに使えると思うので、記憶に⽚隅にでも留めてもらえたら その他、希望など memefishはOSSなので、バグ報告・修正などはいつでもウェルカムです memefishを使って何か作ったよ、みたいな報告もありがたいです ただ、 analyzer 周りはやや開発途中な部分があるので、
後⽅互換性の無い変更などあるかもしれません (悪しからず) SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 36
Q&A? SpannerのSQL解析ライブラリ "memefish" の紹介 by @MakeNowJust 37