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
Golangで作るSQL Language Server(sqls)
Search
Toshikazu Ohashi
November 13, 2021
Programming
1
870
Golangで作るSQL Language Server(sqls)
Go Conference 2021 Autumn Track A
Toshikazu Ohashi
November 13, 2021
Tweet
Share
More Decks by Toshikazu Ohashi
See All by Toshikazu Ohashi
無自覚にメンバーの心理的安全性を奪っていた経験から得た学び
lighttiger2505
153
210k
黒画面が最高のしごと道具である3つの理由
lighttiger2505
0
2k
Connect with many developers from the small plugin
lighttiger2505
0
370
作ってわかる現代のVimのAutoComplete ~そしてVimConf2019へ~
lighttiger2505
3
1.6k
自社サービスのDjangoを 1.3から1.11(LTS)に アップグレードするまでの道のり
lighttiger2505
6
3.5k
LSPがもたらしたVimプラグインの変化に思いを馳せる
lighttiger2505
2
1.4k
ターミナルアプリケーションとしてのVim
lighttiger2505
0
540
Go Language Server 使うべし
lighttiger2505
5
2k
Goで作るインタラクティブなCLIコマンドとそのデザイン
lighttiger2505
0
810
Other Decks in Programming
See All in Programming
JAWS Days 2025のインフラ
komakichi
1
360
PHPカンファレンス名古屋2025 タスク分解の試行錯誤〜レビュー負荷を下げるために〜
soichi
1
760
.NET Frameworkでも汎用ホストが使いたい!
tomokusaba
0
210
AIレビュー導入によるCIツールとの共存と最適化
kamo26sima
1
1k
Domain-Driven Design (Tutorial)
hschwentner
13
22k
Jakarta EE meets AI
ivargrimstad
0
750
複数のAWSアカウントから横断で 利用する Lambda Authorizer の作り方
tc3jp
0
130
[JAWS DAYS 2025] 最近の DB の競合解決の仕組みが分かった気になってみた
maroon1st
0
190
推しメソッドsource_locationのしくみを探る - はじめてRubyのコードを読んでみた
nobu09
2
360
やっと腹落ち「スプリント毎に動くモノをリリースする」〜ゼロから始めるメガバンクグループのアジャイル実践〜
sasakendayo
0
210
Modern Angular with Signals and Signal StoreNew Rules for Your Architecture @bastacon 2025 in Frankfurt
manfredsteyer
PRO
0
110
DRFを少しずつ オニオンアーキテクチャに寄せていく DjangoCongress JP 2025
nealle
2
300
Featured
See All Featured
Facilitating Awesome Meetings
lara
53
6.3k
Bash Introduction
62gerente
611
210k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.2k
Writing Fast Ruby
sferik
628
61k
Large-scale JavaScript Application Architecture
addyosmani
511
110k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
175
52k
It's Worth the Effort
3n
184
28k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
Java REST API Framework Comparison - PWX 2021
mraible
29
8.4k
Helping Users Find Their Own Way: Creating Modern Search Experiences
danielanewman
29
2.5k
Side Projects
sachag
452
42k
For a Future-Friendly Web
brad_frost
176
9.6k
Transcript
GolangͰ࡞Δ SQL Language Server(sqls) Go Conference 2021 Autumn Track A
lighttiger2505@גࣜձࣾMobility Technologies
ࣗݾհ lighttiger2505 / Toshikazu Ohashi • גࣜձࣾMobility Technologiesॴଐ • αʔόʔαΠυΤϯδχΞ
• ͖ͳΤσΟλVim/NeoVim
ΠϯτϩμΫγϣϯ
sqls An implementation of the Language Server Protocol for SQL.
sqlsͱ • Language Server Protocol(ҎԼ LSP)Λ༻͍ͯΤσΟλͱ௨৴͢ΔSQL ͷLanguage Server(ҎԼ ݴޠαʔόʔ) •
LSPͱϓϩάϥϜݴޠͷ։ൃࢧԉػೳ(ҎԼ ΠϯςϦηϯε)ΛΤ σΟλʹఏڙ͢Δαʔόɺ͓Αͼͦͷ௨৴༰Λنఆͨ͠ϓϩτί ϧɻMicrosoft࡞
HPQMT(PMBOH DMBOHE$MBOH TRMT42- -BOHVBHF4FSWFS1SPUPDPM MTQ LSΫϥΠΞϯτ͕͋ΔΤσΟλͰ͋ΕͲͷΤσΟλͰ ݴޠͷΠϯςϦηϯεͷԸܙΛड͚Δ͜ͱ͕Ͱ͖Δ
ࣗಈิ
αϒΫΤϦࣗಈิ
ఆٛࢀর
Πϯαʔτೖྗิॿ
ΫΤϦ࣮ߦ
ຊͷΰʔϧ GoݴޠͰ࡞Γํ͕Α͘Θ͔Βͳ͍ͷΛ࡞Δํ๏Λڞ༗͢Δ ⊗ ࣅͨΑ͏ͳ͜ͱΛࣗͰͰ͖ΔͱࢥͬͯΒ͏ ⊗ GoͰ࡞ΒΕͨศརπʔϧ͕ੈքʹ૿͑Δ
ΞδΣϯμ લఏ • ᶃͳͥͭ͘Δͷ͔ɻͦͷಈػ • ᶄͲ͏ͭ͘Δͷ͔ɻͦͷํ ࣮ફฤ • ᶅΤσΟλͱLSPͰ௨৴͢ΔͨΊʹͲ͏ͨ͠Β •
ᶆSQLΛͲ͏ͬͯղੳ͢Ε͍͍͔ • ᶇෳͷσʔλϕʔεʹͲ͏ରԠ͢Ε͍͍͔ ·ͱΊ
ᶃͳͥͭ͘Δͷ͔ɻͦͷಈػ
ੈͷதʹSQLͷΠϯςϦηϯε͕গͳ͍ • SQLΛૢ࡞͢Δͱ͖ࣗಈิఆٛࢀরͰ͖ͳ͍ͷ͕ෆຬ • ิͰ͖͍ͯ • ਖ਼֬͡Όͳ͍ • SELECT Exprิͯ͠ଞͰิ͠ͳ͍
• DBπʔϧਾ͚͑ͷΤσΟλ্Ͱ͔͠ΠϯςϦηϯε͕ಈ࡞͠ͳ͍
dbcli͚͕ͩٹ͍ͩͬͨ • DBeaver, DataGripͱൺֱͯ͠ิ ͕ਖ਼͔֬ͭߴ • λʔϛφϧ͔Βଈ࣌ىಈ • ීஈࣄͰ͏Α͏ͳDBαϙʔτ •
DBଓཧ͕໘ • ࣗͰπʔϧΛ࡞ͬͨ
Ұ΄ͲdbcliΛͬͨ݁Ռͷෆຬ • 1ϥΠϯΤσΟλͳͷͰෳߦͷΫΤϦฤूͮ͠Β͍ • αϒΫΤϦͳͲͷෳࡶͳΫΤϦͷิͰ͖ͳ͍ • ΧϥϜͷৄࡉςʔϒϧͷৄࡉΛࢀর͢Δͱ͖ɺςʔϒϧৄࡉΛௐ ΔผΟϯυΛ։͍ͯࢀর͢Δඞཁ͕͋Δ
ݴޠαʔόʔͱLSP • ࣌(2018ͷౙࠒ)gopls͕։ൃ͞ΕɺGoͷࣗಈิݴޠαʔόʔ Λ͏ͷ͕ྑ͍ͱ͍͏ঢ়گʹ • ΤσΟλʔ͕ΠϯςϦηϯεΛಘΔͱ͖ݴޠαʔόʔ͕ୈҰީิʹͳ Δͱ͍͏ྲྀΕ • SQLͷݴޠαʔόʔ͕͋Εɺͯ͢ͷͯ͢ղܾ͢ΔͷͰ ͱ͍͏ண
ᶄͲ͏ͭ͘Δͷ͔ɻͦͷํ
࠷খཁ݅Λ·ͱΊΔ • LSPʹ४ڌͨ͠ϦΫΤετ/ϨεϙϯεΛฦͤΔ • SQLͷจ຺ΛཧղͰ͖Δ • ͦΕʹΑͬͯࣗಈิ͕Ͱ͖Δ • ෳछྨͷσʔλϕʔεʹରԠ͢Δ͜ͱ͕Ͱ͖Δ •
ॳظஈ֊ͰMySQLͷΈ
TRMT .Z42- 1PTUHSF 42- TRMJUF MTQ MTQ MTQ TRMEBUBCBTF TRMEBUBCBTF
ղܾ͠ͳ͚Ε͍͚ͳ͍՝͕̏ͭ TRMEBUBCBTF SQLϑΝΠϧ
TRMT .Z42- 1PTUHSF 42- TRMJUF MTQ MTQ MTQ TRMEBUBCBTF TRMEBUBCBTF
ΤσΟλͱLSPͰ௨৴͢ΔͨΊʹͲ͏ͨ͠Β͍͍͔ TRMEBUBCBTF SQLϑΝΠϧ
TRMT .Z42- 1PTUHSF 42- TRMJUF MTQ MTQ MTQ TRMEBUBCBTF TRMEBUBCBTF
TRMEBUBCBTF SQLΛղੳ͢ΔʹͲ͏͢Ε͍͍͔ SQLϑΝΠϧ
TRMT .Z42- 1PTUHSF 42- TRMJUF MTQ MTQ MTQ TRMEBUBCBTF TRMEBUBCBTF
TRMEBUBCBTF ෳͷσʔλϕʔεʹͲ͏ରԠ͢Ε͍͍͔ SQLϑΝΠϧ
Θ͔ΒΜ͚Ͳ ͱΓ͋͑ͣ ࡞Ζ͏
ҠಈͰਓΛͤʹɻ ϞϏϦςΟςΫϊϩδʔζ ఏɹɹڙ ϓϩϞʔγϣϯΛؚΈ·͢
ʮҠಈͰਓΛͤʹɻʯΛϛογϣϯʹ No.1*λΫγʔΞϓϦʮGOʯAIυϥϨ ίαʔϏεʮDRIVE CHARTʯͳͲΛ։ൃ ͍ͯ͠·͢ *App AnnieௐʛλΫγʔंؔ࿈ΞϓϦʹ͓͚Δຊࠃμϯϩʔυ(iOS/ Google Play߹ࢉ) ௐࠪظؒɿ202010݄1ʙ20219݄30
ϓϩϞʔγϣϯΛؚΈ·͢
GoΤϯδχΞ ΛઈࢍืूதͰ͢ ϓϩϞʔγϣϯΛؚΈ·͢
ᶅΤσΟλͱLSPͰ ௨৴͢ΔͨΊʹͲ͏ͨ͠Β͍͍͔
TRMT .Z42- 1PTUHSF 42- TRMJUF MTQ MTQ MTQ TRMEBUBCBTF TRMEBUBCBTF
ΤσΟλͱLSPͰ௨৴͢ΔͨΊʹͲ͏ͨ͠Β͍͍͔ TRMEBUBCBTF SQLϑΝΠϧ
LSPʹΑΔΤσΟλͱͷ௨৴ • ΤσΟλͱݴޠαʔόʔJSON-RPC 2.0Ͱ௨৴͢Δ • RPC(Remote Procedure Callͷུ)ݺͼग़͠ݩͱผͷϓϩάϥϜ ͷϝιουΛݺͼग़͢ •
JSON-RPCϝιουͷίʔϧͱϨεϙϯεΛJSONͰߦ͏ • ݴޠαʔόʔͱݴ͏͕ΤσΟλͱಉ͡PC্ʹ্ཱͪ͛ͯιέοτܦ ༝Ͱ௨৴͢Δͷ͕ओ
JSON-RPCͷ௨৴ྫ(ఆٛݩδϟϯϓ) { "jsonrpc": "2.0" , "id" : 1 , "method":
"textDocument/definition" , "params": { "textDocument": { "uri": "file:///cpp/use.cpp " } , "position": { "line": 3 , "character": 1 2 } } } { "jsonrpc": "2.0" , "id": 1 , "result": { "uri": "file:///cpp/provide.cpp" , "range": { "start": { "line": 0 , "character": 4 } , "end": { "line": 0 , "character": 1 1 } } } } ΤσΟλ ϦΫΤετ ݴޠαʔόʔ Ϩεϙϯε
GolangͰͷJSON-RPCͷ࣮ํ๏ • Goͷ͍͍ͱ͜ΖࣅͨΑ͏ͳιϑτΣΞ͕͏͢Ͱʹ͋Δ ݴޠαʔόʔ ղઆ HPQMT (Pͷ։ൃνʔϜ͕։ൃ͍ͯ͠Δ(PMBOHެࣜͷݴޠαʔόʔ CJOHP TBJCJOHࢯ͕։ൃɻHPQMTҎલ͔Β͋Δ(PMBOHͷݴޠαʔόʔɻݱࡏHPQMTʹ ౷߹ɻHPQMTΑΓػೳ͕গͳ͘γϯϓϧɻ࣮ॳظͬͪ͜Λࢀߟʹͨ͠
FGNMBOHTFSWFS NBUUOࢯ͕։ൃɻMJOUFSͷ࣮ߦ݁ՌΛύʔεͯ͠MTQܗࣜͷMJOU݁Ռ EJBHOPTUJDT ͱ͍͏ ʹม͠+40/31$ܗࣜͰ͢൚༻ݴޠαʔόʔ
JSON-RPCߏஙͷஈऔΓ • ͲͷαʔόʔJSON-RPC2ͷ࣮ʹsourcegraph/jsonrpc2Λ͍ͬͯΔ • efm-langserver͔Βݴޠαʔόʔͱͯ͠࠷ݶΓཱͭίʔυΛҾ༻ • ࠷γϯϓϧͳ࡞ΓͩͬͨͨΊ • sourcegraph/jsonrpc2ͱbingo͔ΒJSON-RPC2ͷςετίʔυΛҾ༻ͯ͠ ୯ମςετߏங
• ࣮ࡍʹLSΫϥΠΞϯτͱૄ௨ͯ͠ਖ਼ৗಈ࡞͢Δ͜ͱΛ֬ೝ
ᶆSQLΛղੳ͢Δʹ Ͳ͏͢Ε͍͍͔
TRMT .Z42- 1PTUHSF 42- TRMJUF MTQ MTQ MTQ TRMEBUBCBTF TRMEBUBCBTF
TRMEBUBCBTF SQLΛղੳ͢ΔʹͲ͏͢Ε͍͍͔ SQLϑΝΠϧ
SQLΛղੳ͢Δʹ • Golangͷgo/astύοέʔδͷΑ͏ͳղੳϥΠϒϥϦ͕ඞཁ • ϥΠϒϥϦΛ୳͢ͱҎԼͷΑ͏ͳͷ͕ݟ͔ͭΔ ύʔαʔ ղઆ YXC TRMQBSTFS 7JUFTTͱ͍͏.Z42-ͷΫϥελΛߏங͢ΔγεςϜͰར༻͞Ε͍ͯΔύʔαʔ
ΛϥΠϒϥϦԽͨ͠ͷ BLJUP YTRMQBSTFS 3VTUͷBOEZHSPWFTRMQBSTFSSTΛࢀߟʹ࡞ΒΕͨύʔαʔɻTRMTͰ ͍ͬͯͳ͍͕MFYFS΄΅͜ΕΛࢀߟʹ͍ͯ͠Δ
ͲͷΑ͏ͳಈ͖Λ͢Δ͔ݕূ͢Δ • SQLΛύʔεͯ͠ߏମΛprint͢Δ͚ͩͷ؆қCLIΛ࡞ͬͯݕূ package mai n import ( "fmt "
"os " "github.com/k0kubun/pp " "github.com/xwb1989/sqlparser " ) func main() { stmt, err := sqlparser.Parse(os.Args[0] ) if err != nil { fmt.Println("parse error:", err ) retur n } pp.Print(stmt ) }
͜ͷͱ͖͜͏ࢥ͍ͬͯ·ͨ͠ ͳΜͩ؆୯͡Όͳ͍͔ɻ ͜ΕͳΒࣗಈิ͙ͩͧ͢ɻ
ݕূͷ݁Ռࣗಈิʹ͑ͳ͍͜ͱ͕Θ͔Δ • ݕূͨ݁͠Ռɺsqls༻్Ͱطଘύʔαʔ͑ͳ͍͜ͱ͕Θ͔Δ SELECT id, | FROM city INSERT INTO
city (id, |) UPDATE city SET CountryCode='USA', |
GOͷߏจ package mai n import "fmt " func main() {
msg := "hello world " fmt.Sprintln(| } SELECT `ID` , | FROM `city ` WHERE `CountryCode` = 'USA ' ORDER BY `District` SQLͷߏจ
GOͷߏจ package mai n import "fmt " func main() {
msg := "hello world " fmt.Sprintln(| } SELECT `ID` , | FROM `city ` WHERE `CountryCode` = 'USA ' ORDER BY `District` SQLͷߏจ • ߏจͷ্ؔɺ1Statement͕͍ • 1Statementͷதʹ(ςʔϒϧ)ఆٛใؚ͕·Ε͍ͯΔ
GOͷߏจ package mai n import "fmt " func main() {
msg := "hello world " fmt.Sprintln(| } SELECT `ID` , | FROM `city ` WHERE `CountryCode` = 'USA ' ORDER BY `District` SQLͷߏจ • ߏจͷ্ؔɺ1Statement͕͍ • 1Statementͷதʹ(ςʔϒϧ)ఆٛใؚ͕·Ε͍ͯΔ
GOͷߏจ package mai n import "fmt " func main() {
msg := "hello world " fmt.Println(| } SELECT `ID` , | FROM `city ` WHERE `CountryCode` = 'USA ' ORDER BY `District` SQLͷߏจ • ଞݴޠͳΒύʔεࣦഊͨ͠1StatementΛಡΈඈͯ͠ऴΘΓ • SQL1StatementதͷΤϥʔΛׂͯ͠ղऍ͢Δඞཁ͕͋Δ
ݱࡏSQLͷࣗಈิ͕Ͱ͖͍ͯΔOSS • dbcliγϦʔζɻPythonɻ֤DBͷCLIίϚϯυͷΘΓʹ͏͜ͱͰ CLI্ͰΫΤϦͷࣗಈิ͕Ͱ͖Δ ίϚϯυ ղઆ QHDMJ QPTUHSF42-ͷ$-*ίϚϯυସ NZDMJ .Z42-ͷ$-*ίϚϯυସ
MJUFDMJ 42-JUFͷ$-*ίϚϯυସ NTTRMDMJ .JDSPTPGU42-4FSWFSͷ$-*ίϚϯυସ
dbcliγϦʔζ͕ར༻͍ͯ͠ΔSQLύʔαʔ • andialbrecht/sqlparse • ͍Θ͘sqlparse is a non-validating SQL parser
for Python. • Goͷύʔαʔͷͱ͖ͱಉ༷ʹSQLͷύʔε݁ՌΛඳը͢Δ͚ͩͷCLI ίϚϯυΛ࡞ͬͯࢼ͢ • ΤϥʔΛಡΈඈͤΔఔ·Ͱจ຺ͷղੳΛεΩοϓ͍ͯͨ͠
طଘͷSQLύʔε
non-validatingͳSQLύʔε
di f
di f จ຺ΛऔΒͳ͍ɻSelectͰදࣔ͢ΔΧϥϜͱ͔ςʔϒϧͷఆٛ
ϝϦσϝ • ϝϦοτ • ଟগͷΤϥʔ͕͋ͬͯͳ͘ύʔεͰ͖Δ • σϝϦοτ • From۟Ͱఆٛ͞ΕͨςʔϒϧΛҾ͖ग़͢ͳͲͷॲཧ͕໘ •
lintͷ࣮ͱ͔ΊΜͲ͍͘͞(ͳͷͰ͍ͬͯͳ͍) • αϒΫΤϦཧԋࢉࢠͳͲ࠶ؼతͳॲཧ͕͍͠ • αϒΫΤϦղੳͷίʔυࠓͰݟͨ͘ͳ͍
ཧ۶Θ͔͕ͬͨɺશʹࣗݾྲྀͰ࣮͢Δͷා ͍ͷͰɺύʔαʔͮ͘ΓͷษڧΛ͢Δ͜ͱʹͨ͠ ͓͢͢Ίʂʂʂ
̍ϲ݄ษڧͯ͠Θ͔ͬͨ͜ͱ • ߏจΛղੳ͢ΔͨΊʹࣈ۟ղੳث(Lexer),ߏจղੳث(Parser)͕ඞཁ • ύʔαʔΛ࡞ΔͨΊʹύʔαʔδΣωϨʔλͳΔศརπʔϧ͕͋Δ • DSLΛఆٛͯ͠ಡΈࠐΉͱύʔαʔ(߹ʹΑͬͯϨΩαʔ)Λ ੜ ࣈ۟ղੳث -FYFS
ߏจղੳث 1BSTFS τʔΫϯྻ AST ιʔείʔυ
sqlsͷΞϓϩʔν • ύʔαʔδΣωϨʔλʔ vs ࣗ࡞ύʔαʔ • ͲͷδΣωϨʔλʔͳΒnon-validatingͳύʔαʔ͕࡞ΕΔ͔ෆ໌ • ࣗ࡞ͰύʔαʔͳΒࣗ࡞ͳͷͰͳΜͰͰ͖Δ •
ࠓࢥ͑tree-sitterͱ͔͋ͬͨɻษڧෆ • ࣗ࡞ύʔαʔͷ࡞Λܾҙ • ϨΩαʔxsqlparserΛࢀߟʹ͢ΕͦΜͳʹ࿑ྗͳ͘࡞Εͦ͏
ύʔαʔ࡞Γํߨ࠲(ͦͷ̍) • andialbrecht/sqlparse͔ΒύʔεͷςετίʔυΛݟ͚ͭΔ • ҎԼΛsqlparseͱಉͷ݁Ռ͕ಘΒΕΔ·Ͱ܁Γฦ͢ 1. ύʔε͢ΔରΛܾΊΔ(ΧϥϜྻͱ͔) 2. ରΛύʔε͢ΔςετίʔυΛsqlsʹҠ২ 3.
ςετίʔυͷظΛຬͨ͢
ύʔαʔ࡞Γํߨ࠲(ͦͷ̎) • ςετ͠·͢ • ςετ͠·͢ • ςετ͠·͢ • ςετ͠·͢ •
ςετ͠·͢ • ςετ͠·͢ςετ͠·͢ςετ͠·͢ςετ͠·͢ςετ͠·͢ςετ͠·͢ςετ͠· ͢ςετ͠·͢ςετ͠·͢ςετ͠·͢ςετ͠·͢ςετ͠·͢ςετ͠·͢ςετ͠ ·͢ςετ͠·͢ςετ͠·͢ςετ͠·͢ςετ͠·͢ςετ͠·͢ςετ͠·͢ςετ ͠·͢ςετ͠·͢ςετ͠·͢ςετ͠·͢ςετ͠·͢ςετ͠·͢…
ॳΊͯsqlsͰࣗಈิΛ͍ͯ͠Δ༷ࢠ
ᶇෳͷσʔλϕʔεʹ Ͳ͏ରԠ͢Ε͍͍͔
TRMT .Z42- 1PTUHSF 42- TRMJUF MTQ MTQ MTQ TRMEBUBCBTF TRMEBUBCBTF
TRMEBUBCBTF ෳͷσʔλϕʔεʹͲ͏ରԠ͢Ε͍͍͔ SQLϑΝΠϧ
੍ͱϧʔϧΛઃ͚Δ • sqls͋͘·ͰࣗͷͨΊͷπʔϧ • ༗ঈͷDBʹରԠ͠ͳ͍ • ։ൃऀ͍ͩ͠Ͱଓݕূ͕Ͱ͖ͳ͘ͳΔ • BigQuery •
Snow fl ake • database/sqlʹޓͷ͋ΔDriver͕ͳ͍ͷʹରԠ͠ͳ͍
ΠϯλϑΣʔεΛ༻ҙ type DBRepository interface { Driver() dialect.DatabaseDrive r CurrentDatabase(ctx context.Context)
(string, error ) Databases(ctx context.Context) ([]string, error ) CurrentSchema(ctx context.Context) (string, error ) Schemas(ctx context.Context) ([]string, error ) SchemaTables(ctx context.Context) (map[string][]string, error ) DescribeDatabaseTable(ctx context.Context) ([]*ColumnDesc, error ) DescribeDatabaseTableBySchema(ctx context.Context, schemaName string) ([]*ColumnDesc, error ) Exec(ctx context.Context, query string) (sql.Result, error ) Query(ctx context.Context, query string) (*sql.Rows, error ) }
ͳͥΠϯλϑΣʔε͕ඞཁ͔ • υϥΠόՃʹඞཁͳ߲Λ໌ࣔ • ςʔϒϧͳͲͷϝλใͷऔಘํ๏͕DB͝ͱʹҧ͏ • mysql, postgresqlͳΒinformation_schema • sqlite3ͳΒsqlite_master
ΠϯλϑΣʔεΘ͚ͨ͠Ռ • ࣗͰ࣮ͨ͠ͷDBଓMySQL͚ͩ • PostgreSQLͱSQLite3mattn͞Μ • Microsoft SQL Serveralexhokl͞Μ •
༗ঈͷDBΛՃͨ͠PullRequest͕དྷΔ͕Ϛʔδ͠ͳ͍
·ͱΊ • ڧ͍ಈػ(VimͰSQLͷิ͕͍ͨ͠)͕͋ΕؤுΕΔ • ࡞Γํ͕Θ͔Βͳ͍ͱ͖ɺࣅͨ՝Λղܾ͢Δπʔϧ୳ͤ͋Δ • طଘπʔϧ/ϥΠϒϥϦ͕՝ʹϑΟοτ͠ͳ͚Εࣗ࡞ࢹʹೖΕΔ • ΜͰ͍Δؒʹॻ͚ͨΓ͢Δ͠ɺବͰ৽͍͠՝͕ݟ͑Δ •
෦ద༻Ͱ͖Δͷ͋ΔͷͰίʔυΛಡΉ͜ͱΛڪΕͳ͍ • ॳظείʔϓͰ͖Δ͚ͩখ͘͢͞Δ
See you again όΠόΠ