$30 off During Our Annual Pro Sale. View Details »
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
github.com/pinzolo/sqlt
Search
pinzolo
January 18, 2019
Technology
1
310
github.com/pinzolo/sqlt
pinzolo
January 18, 2019
Tweet
Share
More Decks by pinzolo
See All by pinzolo
rubygems-mfa.pdf
pinzolo
0
130
encoding/csv
pinzolo
0
760
Redmine 3.x
pinzolo
0
3.9k
Travis CI API LT
pinzolo
1
1k
Gemfile.local
pinzolo
0
140
Tenderness driven development for Redmine plugin
pinzolo
1
4.9k
Other Decks in Technology
See All in Technology
モダンデータスタックの理想と現実の間で~1.3億人Vポイントデータ基盤の現在地とこれから~
taromatsui_cccmkhd
1
250
ExpoのインダストリーブースでみたAWSが見せる製造業の未来
hamadakoji
0
190
松尾研LLM講座2025 応用編Day3「軽量化」 講義資料
aratako
0
550
AIエージェント開発と活用を加速するワークフロー自動生成への挑戦
shibuiwilliam
4
810
ActiveJobUpdates
igaiga
1
300
Bedrock AgentCore Memoryの新機能 (Episode) を試してみた / try Bedrock AgentCore Memory Episodic functionarity
hoshi7_n
2
1.6k
まだ間に合う! Agentic AI on AWSの現在地をやさしく一挙おさらい
minorun365
17
2.4k
【U/Day Tokyo 2025】Cygames流 最新スマートフォンゲームの技術設計 〜『Shadowverse: Worlds Beyond』におけるアーキテクチャ再設計の挑戦~
cygames
PRO
2
1.4k
「図面」から「法則」へ 〜メタ視点で読み解く現代のソフトウェアアーキテクチャ〜
scova0731
0
480
子育てで想像してなかった「見えないダメージ」 / Unforeseen "hidden burdens" of raising children.
pauli
2
320
AWS re:Invent 2025~初参加の成果と学び~
kubomasataka
0
180
フルカイテン株式会社 エンジニア向け採用資料
fullkaiten
0
9.9k
Featured
See All Featured
Rails Girls Zürich Keynote
gr2m
95
14k
Google's AI Overviews - The New Search
badams
0
870
Effective software design: The role of men in debugging patriarchy in IT @ Voxxed Days AMS
baasie
0
170
The agentic SEO stack - context over prompts
schlessera
0
550
The SEO identity crisis: Don't let AI make you average
varn
0
35
Color Theory Basics | Prateek | Gurzu
gurzu
0
150
Odyssey Design
rkendrick25
PRO
0
430
Skip the Path - Find Your Career Trail
mkilby
0
25
Testing 201, or: Great Expectations
jmmastey
46
7.8k
Leo the Paperboy
mayatellez
0
1.2k
How To Stay Up To Date on Web Technology
chriscoyier
791
250k
Building Better People: How to give real-time feedback that sticks.
wjessup
370
20k
Transcript
github.com/ pinzolo/sqlt
$ whoami • NODA Masato • @pinzolo • Go ϓϥΠϕʔτͰ͍࢝Ίͯ2͙
Β͍ • SQLࣗͰॻ͖͍ͨ
sqltͱ text/template Λϕʔεʹͯ͠࡞ͨ͠ 2way SQL ϥΠϒϥ Ϧ
2way SQL ͬͯʁ • ΫΤϦϏϧμͷҰछ • ςϯϓϨʔτʹରͯ͠ύϥϝʔλΛͯ͠SQLΛੜ͢Δ • ςϯϓϨʔτࣗମ͕࣮ߦͰ͖ΔSQLͰ͋Δ
2way SQL ͬͯʁ • ΫΤϦϏϧμͷҰछ • ςϯϓϨʔτʹରͯ͠ύϥϝʔλΛͯ͠SQLΛੜ͢Δ • ςϯϓϨʔτࣗମ͕࣮ߦͰ͖ΔSQLͰ͋Δ <-
࠷େͷಛ
͜Μͳͭ ex: Doma SELECT * FROM item WHERE status =
'AVAILABLE' /*%if name != null*/ AND name = /*name*/'John Doe' /*%end*/
2way SQL ࣗମͷϝϦ οτɾσϝϦοτ ORM ૪͜͜ͰׂѪ
None
ͳͥ text/template ϕʔεͰ࡞Ζ͏ͱࢥͬͨ ͷ͔ʁ
ָ͔͔ͨͬͨ͠Β
text/template Λ͏ͱ if range ͱ੍͍ͬͨޚߏจ͕ఏڙ͞Ε͓ͯΓɺeq ne and or ͳͲͷ΄΅ if
ʹඞਢͳॲཧ࠷࣮ͷඞཁ͕ແ͍
text/template Λ͏ͱ template.FuncMap ܦ༝ͰςϯϓϨʔτͰ͑ΔؔΛొ Ͱ͖ΔͷͰɺSQLʹؔ͢ΔΈࠐΈؔϓϩδΣΫτຖͷศརؔ ͷొ͕༰қ
text/template Λ͏ͱ ύϑΥʔϚϯεΛຊՈʹͿΜ͛ΒΕΔɻ ʢͨͩ͠ɺવࣗͰScannerΛॻ͍ͨํ͕ΑΓߴੑೳͳͷʹ ͳΔʣ
ϝϦοτଟ͍
(ςϯϓϨʔτݴޠΛͬͯςϯϓϨʔτݴޠΛ࡞ΔΜ͔ͩΒ େ͕ྲྀ༻Ͱ͖ͯͨΓલͳͷ͚ͩͲ)
None
Sample code SQL SELECT * FROM users WHERE id IN
/*% in "ids" %*/(1, 2) AND name = /*% p "name" %*/'John Doe' /*%- if get "onlyMale" %*/ AND sex = 'MALE' /*%- end %*/ ORDER BY /*% out "order" %*/id
Sample code Go st := sqlt.New(sqlt.Postgres) query, args, err :=
st.Exec(s, map[string]interface{}{ "ids": []int{1, 2, 3}, "order": "name DESC", "onlyMale": false, "name": "Alex", })
Sample code Generated SQL SELECT * FROM users WHERE id
IN ($1, $2, $3) AND name = $4 ORDER BY name DESC
Sample code Generated SQL (ExecNamed) SELECT * FROM users WHERE
id IN (:ids__1, :ids__2, :ids__3) AND name = :name ORDER BY name DESC
Sample code Generated SQL (Annotation Option) SELECT * FROM users
WHERE id IN ($1, $2, $3)/*# ids */ AND name = $4/*# name */ ORDER BY name DESC
ͳͥ text/template Λ༻͍ͯ͜Μͳ͜ͱ͕ग़ དྷΔͷ͔ʁ
sqlt Λ࣮ݱ͍ͯ͠Δೋͭͷൃ 1.Template.Delims ʹΑΔ SQL ϑϨϯυϦʔͳσϦϛλ 2.ؔͰͳ͘ϝιουΛ FuncMap ʹొͯ͠෭࡞༻Λར༻͢ Δ
Template.Delims ຊདྷ {{ ͱ }} Ͱ͋Δ text/template ͷσϦϛλΛมߋ͢Δ ػೳɻ ͜ΕΛ
/*% ͱ %*/ ͱ͍͏SQLʹͱͬͯίϝϯτͰ͋Δจࣈʹ มߋ͍ͯ͠ΔͷͰɺςϯϓϨʔτͷ֤छ໋ྩΛແಟԽ͍ͯ͠Δɻ
ϝιουͷ෭࡞༻ར༻ FuncMap ʹొ͢ΔؔΛ७ਮͳؔͰͳ͘ɺಛఆͷΠϯελ ϯεʹॴଐ͢Δϝιουʹ͢Δ͜ͱʹΑͬͯεϨουϩʔΧϧͳ෭ ࡞༻Λར༻Ͱ͖Δɻ ͓ʹςϯϓϨʔτʹ͞Εͨύϥϝʔλ͔ΒɺSQL࣮ߦʹඞཁͳ ύϥϝʔλΛ࡞͢ΔͨΊʹར༻͍ͯ͠Δɻ
ྫ1ʣύϥϝʔλͷׂ SELECT * FROM users WHERE name LIKE /*% infix
"name" %*/'John Doe' /*% if get "available" %*/ AND status = /*% in "stats" %*/(NULL) /*% end %*/ /*% if get "email" %*/ AND email = /*% p "email" %*/'
[email protected]
' /*% end %*/
ྫ1ʣύϥϝʔλͷׂ 1.SQL࣮ߦ࣌ʹඞཁͳύϥϝʔλʢnameʣ 2.SQLߏங࣌ʹඞཁͳύϥϝʔλ(available) 3.྆ํʹඞཁͳύϥϝʔλʢemailʣ 4.ಛఆͷ݅࣌ʹඞཁͳύϥϝʔλʢstatsʣ ͜ͷ͏ͪɺ࣮ߦ࣌ʹ 2 ݅ʹΑͬͯ 4 Λഉআ͍ͨ͠
ྫ2ʣIN ۟ʹ͓͚ΔεϥΠεͷల։ ΄ͱΜͲͷ database/sql ͷυϥΠό WHERE id IN $1 ʹ
ରͯ͠εϥΠεΛͯ͠ల։͠ͳ͍ɻ
ྫ3ʣΤεέʔϓॲཧͨ͠ύϥϝʔλ͕ ඞཁ SELECT id , name , name = /*%
out "name" %*/'John' AS matched FROM users WHERE name LIKE /*% infix "name" %*/'John' ORDER BY matched DESC, name
ྫ3ʣΤεέʔϓॲཧͨ͠ύϥϝʔλ͕ ඞཁ ಉ͡ name ύϥϝʔλΛར༻͍ͯ͠Δ͕ɺ1ͭΊͦͷ··Ͱ͍ ͍ͷʹର͠ɺ2ͭΊ LIKE ͷରʹ͢ΔͨΊ %
_ ΛΤεέ ʔϓ͕ͨ͠ඞཁɻ
None
sqltͰղܾͰ͖Δ͜ͱ
1.SQLΛผϑΝΠϧͰཧͰ͖Δ 2.2way-SQLͳͷͰςετ͍͢͠ 3.Pure SQL ͳͷͰπʔϧͷԸܙΛड͚͍͢ 4.ύϥϝʔλʹ໊લΛ͚ΒΕΔ 5.in, suffix, prefix ͷΑ͏ͳ
SQL ઐ༻ؔʹΑΓແବͳ ॲཧΛආ͚ΒΕΔ 6.DBͷҧ͍ΛSQLͷத͚ͩʹด͡ࠐΊ͍͢
sqlt͕ղܾΕͳ͔ ͬͨ͜ͱ
SQLΠϯδΣΫγϣϯ
೦ͳ͕Β type Form struct { Name string } st :=
sqlt.New(sqlt.Postgres) query, args, err := st.Exec(s, map[string]interface{}{ "form": Form{Name: "' OR 1 = 1;"}, })
͜Μͳίʔυ͕ SELECT * FROM users /*%- $f := get "form"
%*/ WHERE name = '/*% $f.Name %*/'
͔͚ͯ͠·͏ SELECT * FROM users WHERE name = '' OR
1 = 1;
range Ͱ type V struct { Value string } st
:= sqlt.New(sqlt.Postgres) query, args, err := st.Exec(s, map[string]interface{}{ "values": []V{ V{"' OR 1 = 1;"}, V{"foo"}, V{"bar"}, }, })
ॻ͚ͯ͠·͏ SELECT * FROM users WHERE ( /*%- range $i,
$v := get "values" %*/ /*%- if ne $i 0 %*/ OR /*% end %*/ name = '/*% $v.Value %*/' /*%- end %*/ )
ͪͳΈʹ SELECT * FROM users WHERE ( /*%- range $i,
$v := get "values" %*/ /*%- if ne $i 0 %*/ OR /*% end %*/ name = /*% p (name "values" $i "Value") %*/'' /*%- end %*/ ) ҆શʹॻ͘ํ๏ఏڙ͍ͯ͠Δɻ
σϑΥϧτͷຒΊࠐΈॲཧʹରͯ͋͠·ΓʹແྗͳͷͰɺҰ࣌ม Λܦ༝͢Δ͚ͩͰ͍͘ΒͰSQLΠϯδΣΫγϣϯΛࠐΊͯ͠ ·͏ɻ σϑΥϧτͷຒΊࠐΈॲཧʹ hook Λॻ͚ͨΓ͢Δ͜ͱ͕ग़དྷΔ ͳΒରࡦͰ͖Δͷ͕ͩɺͦΜͳ͜ͱ͕ग़དྷΔͳΒ͓ͦΒ͘ html/template ͳΜͯଘࡏ͍ͯ͠ͳ͍ɻ
͑Δͷʁ • ϨϏϡʔ͕͔ͬ͠ΓճΔ • Θ͔͍ͬͯΔਓ͚ͩ • ݸਓϓϩμΫτ ʹ͑ͳ͍͜ͱͳ͍͔͠Εͳ͘ͳ͍ɻੵۃతʹ͓͢͢Ί ͠ͳ͍ɻ ʢ͕ࣗ͏ʹ͜ΕͰ·͍͍͔͋ͱࢥͬͯΔʣ
Կ͕͍͚ͳ͔ͬͨͷ͔ʁ • 7ʙ8ׂͷػೳΛຬͨ͢ͱ͍͏ϝϦοτΛ༏ઌ͗ͨ͢͠ • Ұ൪େࣄͳͱ͜ΖΛ֎͞ͳ͍ͱ͍͏ߟ͑Λ༏ઌ͖͢ • ָʹղܾͰ͖Δ͜ͱ୭͔͕ղܾ͍ͯ͠Δ • ͍͟ͱ͍͏ͱ͖ʹϨϕϧ෦ΛίϯτϩʔϧͰ͖Δ͔ͬͯͷ Ϛδେࣄ
ڭ܇
अಓʹ҆қʹඈͼ͔ͭͳ ͍