Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥
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
940
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
159
220k
黒画面が最高のしごと道具である3つの理由
lighttiger2505
0
2.2k
Connect with many developers from the small plugin
lighttiger2505
0
430
作ってわかる現代のVimのAutoComplete ~そしてVimConf2019へ~
lighttiger2505
3
1.8k
自社サービスのDjangoを 1.3から1.11(LTS)に アップグレードするまでの道のり
lighttiger2505
6
3.7k
LSPがもたらしたVimプラグインの変化に思いを馳せる
lighttiger2505
2
1.5k
ターミナルアプリケーションとしてのVim
lighttiger2505
0
590
Go Language Server 使うべし
lighttiger2505
5
2.1k
Goで作るインタラクティブなCLIコマンドとそのデザイン
lighttiger2505
0
940
Other Decks in Programming
See All in Programming
안드로이드 9년차 개발자, 프론트엔드 주니어로 커리어 리셋하기
maryang
1
120
ID管理機能開発の裏側 高速にSaaS連携を実現したチームのAI活用編
atzzcokek
0
230
JETLS.jl ─ A New Language Server for Julia
abap34
1
410
モデル駆動設計をやってみようワークショップ開催報告(Modeling Forum2025) / model driven design workshop report
haru860
0
270
AIコーディングエージェント(skywork)
kondai24
0
180
エディターってAIで操作できるんだぜ
kis9a
0
730
組み合わせ爆発にのまれない - 責務分割 x テスト
halhorn
1
150
Navigation 3: 적응형 UI를 위한 앱 탐색
fornewid
1
350
20 years of Symfony, what's next?
fabpot
2
360
sbt 2
xuwei_k
0
300
バックエンドエンジニアによる Amebaブログ K8s 基盤への CronJobの導入・運用経験
sunabig
0
160
AtCoder Conference 2025「LLM時代のAHC」
imjk
2
510
Featured
See All Featured
Fantastic passwords and where to find them - at NoRuKo
philnash
52
3.5k
How to Think Like a Performance Engineer
csswizardry
28
2.4k
Balancing Empowerment & Direction
lara
5
800
Learning to Love Humans: Emotional Interface Design
aarron
274
41k
Build The Right Thing And Hit Your Dates
maggiecrowley
38
3k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
37
2.6k
Statistics for Hackers
jakevdp
799
230k
Making Projects Easy
brettharned
120
6.5k
Creating an realtime collaboration tool: Agile Flush - .NET Oxford
marcduiker
35
2.3k
Art, The Web, and Tiny UX
lynnandtonic
304
21k
Building Applications with DynamoDB
mza
96
6.8k
The Straight Up "How To Draw Better" Workshop
denniskardys
239
140k
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 όΠόΠ