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
860
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
152
210k
黒画面が最高のしごと道具である3つの理由
lighttiger2505
0
2k
Connect with many developers from the small plugin
lighttiger2505
0
360
作ってわかる現代の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
コミュニティ駆動 AWS CDK ライブラリ「Open Constructs Library」 / community-cdk-library
gotok365
2
140
Unity Android XR入門
sakutama_11
0
160
Rubyで始める関数型ドメインモデリング
shogo_tksk
0
120
ARA Ansible for the teams
kksat
0
150
Introduction to kotlinx.rpc
arawn
0
700
Amazon ECS とマイクロサービスから考えるシステム構成
hiyanger
2
570
Multi Step Form, Decentralized Autonomous Organization
pumpkiinbell
1
750
Amazon Q Developer Proで効率化するAPI開発入門
seike460
PRO
0
110
Boost Performance and Developer Productivity with Jakarta EE 11
ivargrimstad
0
340
Pythonでもちょっとリッチな見た目のアプリを設計してみる
ueponx
1
570
第3回関東Kaggler会_AtCoderはKaggleの役に立つ
chettub
3
1k
クリーンアーキテクチャから見る依存の向きの大切さ
shimabox
2
470
Featured
See All Featured
The Art of Delivering Value - GDevCon NA Keynote
reverentgeek
10
1.3k
Thoughts on Productivity
jonyablonski
69
4.5k
Designing for Performance
lara
604
68k
Writing Fast Ruby
sferik
628
61k
Optimizing for Happiness
mojombo
376
70k
Typedesign – Prime Four
hannesfritz
40
2.5k
Raft: Consensus for Rubyists
vanstee
137
6.8k
Measuring & Analyzing Core Web Vitals
bluesmoon
6
240
The MySQL Ecosystem @ GitHub 2015
samlambert
250
12k
Visualization
eitanlees
146
15k
Fireside Chat
paigeccino
34
3.2k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
33
2.1k
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 όΠόΠ