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
github.com/pinzolo/sqlt
Search
pinzolo
January 18, 2019
Technology
1
300
github.com/pinzolo/sqlt
pinzolo
January 18, 2019
Tweet
Share
More Decks by pinzolo
See All by pinzolo
rubygems-mfa.pdf
pinzolo
0
110
encoding/csv
pinzolo
0
740
Redmine 3.x
pinzolo
0
3.9k
Travis CI API LT
pinzolo
1
990
Gemfile.local
pinzolo
0
140
Tenderness driven development for Redmine plugin
pinzolo
1
4.9k
Other Decks in Technology
See All in Technology
GitHub Copilot の概要
tomokusaba
1
100
Абьюзим random_bytes(). Фёдор Кулаков, разработчик Lamoda Tech
lamodatech
0
310
変化する開発、進化する体系時代に適応するソフトウェアエンジニアの知識と考え方(JaSST'25 Kansai)
mizunori
0
160
登壇ネタの見つけ方 / How to find talk topics
pinkumohikan
3
330
_第3回__AIxIoTビジネス共創ラボ紹介資料_20250617.pdf
iotcomjpadmin
0
150
第9回情シス転職ミートアップ_テックタッチ株式会社
forester3003
0
170
Кто отправит outbox? Валентин Удальцов, автор канала Пых
lamodatech
0
310
Wasm元年
askua
0
120
Definition of Done
kawaguti
PRO
6
470
Prox Industries株式会社 会社紹介資料
proxindustries
0
220
Amazon Bedrockで実現する 新たな学習体験
kzkmaeda
1
410
Amplifyとゼロからはじめた AIコーディング 成果と展望
mkdev10
1
380
Featured
See All Featured
How to Think Like a Performance Engineer
csswizardry
24
1.7k
Git: the NoSQL Database
bkeepers
PRO
430
65k
Thoughts on Productivity
jonyablonski
69
4.7k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
35
2.3k
Documentation Writing (for coders)
carmenintech
71
4.9k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
45
7.4k
Responsive Adventures: Dirty Tricks From The Dark Corners of Front-End
smashingmag
252
21k
What's in a price? How to price your products and services
michaelherold
246
12k
A better future with KSS
kneath
239
17k
YesSQL, Process and Tooling at Scale
rocio
173
14k
The Myth of the Modular Monolith - Day 2 Keynote - Rails World 2024
eileencodes
26
2.8k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
331
22k
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ׂͷػೳΛຬͨ͢ͱ͍͏ϝϦοτΛ༏ઌ͗ͨ͢͠ • Ұ൪େࣄͳͱ͜ΖΛ֎͞ͳ͍ͱ͍͏ߟ͑Λ༏ઌ͖͢ • ָʹղܾͰ͖Δ͜ͱ୭͔͕ղܾ͍ͯ͠Δ • ͍͟ͱ͍͏ͱ͖ʹϨϕϧ෦ΛίϯτϩʔϧͰ͖Δ͔ͬͯͷ Ϛδେࣄ
ڭ܇
अಓʹ҆қʹඈͼ͔ͭͳ ͍