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
200k
黒画面が最高のしごと道具である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.4k
LSPがもたらしたVimプラグインの変化に思いを馳せる
lighttiger2505
2
1.4k
ターミナルアプリケーションとしてのVim
lighttiger2505
0
540
Go Language Server 使うべし
lighttiger2505
5
2k
Goで作るインタラクティブなCLIコマンドとそのデザイン
lighttiger2505
0
800
Other Decks in Programming
See All in Programming
Fixstars高速化コンテスト2024準優勝解法
eijirou
0
200
ErdMap: Thinking about a map for Rails applications
makicamel
1
1.2k
Azure AI Foundryのご紹介
qt_luigi
1
260
定理証明プラットフォーム lapisla.net
abap34
1
670
バックエンドのためのアプリ内課金入門 (サブスク編)
qnighy
7
1.6k
技術を根付かせる / How to make technology take root
kubode
1
110
時計仕掛けのCompose
mkeeda
1
230
ASP. NET CoreにおけるWebAPIの最新情報
tomokusaba
0
240
DMMオンラインサロンアプリのSwift化
hayatan
0
280
Package Traits
ikesyo
2
230
【PHP】破壊的バージョンアップと戦った話〜決断と説得
satoshi256kbyte
0
110
Swiftコンパイラ超入門+async関数の仕組み
shiz
0
200
Featured
See All Featured
Automating Front-end Workflow
addyosmani
1367
200k
Practical Tips for Bootstrapping Information Extraction Pipelines
honnibal
PRO
11
910
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
330
21k
The Invisible Side of Design
smashingmag
299
50k
XXLCSS - How to scale CSS and keep your sanity
sugarenia
248
1.3M
Optimizing for Happiness
mojombo
376
70k
The Straight Up "How To Draw Better" Workshop
denniskardys
232
140k
Practical Orchestrator
shlominoach
186
10k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
39
1.9k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
7
620
Understanding Cognitive Biases in Performance Measurement
bluesmoon
27
1.5k
How To Stay Up To Date on Web Technology
chriscoyier
790
250k
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 όΠόΠ