AIã»æ©æ¢°å¦ç¿ãã¼ã ã®åå·(@kitagry)ã§ãã ãã®ããã°ã¯ã¨ã ã¹ãªã¼ã¢ããã³ãã«ã¬ã³ãã¼11æ¥ç®ã®è¨äºã§ãã
ãã®ããã°ã§ã¯ã¿ã¤ãã«éãOSSã§ä½æãã¦ããbqlsã¨ããLanguage Serverã«ã¤ãã¦ç´¹ä»ãã¾ãã
- bqlsã«ã¤ãã¦
- Language Serverã¨ã¯
- ä½æ bqlsãä½ã£ãã®ã
- ã©ããã£ã¦è£å®ãããã®ã
- Language Serverãªãã§ã¯ã®ãã¼ã¹ã®é£ãã
- ãªãã¨ããã¼ã¹ãã
- ä¿®æ£æ¹æ³ãèãã
- ã¾ã¨ã
- We are hiring
bqlsã«ã¤ãã¦
bqlsã¯Google Cloudã®ãã¼ã¿ã¦ã§ã¢ãã¦ã¹ã§ããBigQueryã®Language Serverã§ãã 主ãªç¹å¾´ã¨ãã¦ã¯æ¬¡ã®ã¨ããã§ãã
- Language Serverãªã®ã§ä¸»è¦ãªã¨ãã£ã¿(VS Code, Vim, Emacsãªã©)ã§å©ç¨ã§ããã
- BigQueryã®ç·¨éæ¯æ´(è£å®ã»è§£æã»SQLã®å®è¡ãªã©)
Language Serverã¨ã¯
Language Serverã¨ã¯ã³ã¼ãã®è£å®ã解æã¨ãã£ãæ©è½ãæä¾ãããµã¼ãã¼ã§ãã goplsãrust-analyzerã¨ãã£ãåLanguage Serverã¯Language Server Protocolï¼ä»¥éLSPï¼ã¨ãããããã³ã«ã«æ²¿ã£ãå®è£ ããã¦ãã¾ãã ãã®ãããã³ã«ã«å¾ããã¨ã«ãã£ã¦ãã¨ãã£ã¿ãIDEãªã©ã¯åãå®è£ ã§è£å®ãå®ç¾©ã¸ã£ã³ãããªãã¡ã¯ã¿ãªã³ã°ãªã©ãæ§ã ãªè¨èªã§å©ç¨ã§ãã¾ãã LSP以åã§ã¯åã¨ãã£ã¿ãåè¨èªã®ãµãã¼ããå®è£ ãã¦ãããããã¨ãã£ã¿ãã¨ã«è¨èªãµãã¼ããå®è£ ããå¿ è¦ãããã¾ããã LSPã使ããã¨ã§ãã¨ãã£ã¿ãIDEã¯Language Serverã¨ã®éä¿¡ã«éä¸ããLanguage Serverã¯è¨èªåºæã®æ©è½ãæä¾ãããã¨ã«éä¸ã§ãã¾ãã
ã¤ã¾ããä»åã®BigQueryç¨ã®Language Serverã¯LSPã«å¾ããã¨ã§è£å®ãªã©ã®æ©è½ã®æ©æµãå¾ããã¨ãã§ããã®ã§ãã
ä½æ bqlsãä½ã£ãã®ã
BigQueryã¯Web UIãæä¾ãã¦ããããã®ä¸ã§è£å®ããã©ã¼ãããã®æ©è½ãæä¾ãã¦ãã¾ãã ãããããã®è£å®ãå人çã«ã¯ã¨ã¦ãé ãæãã¦ããæ®æ®µæ¸ãã¨ãã«ã¯ã»ã¨ãã©å©ç¨åºæ¥ãªãç¶æ ã§ããã ãªã«ããåã¯æ®æ®µNeovimãå©ç¨ãã¦ããã®ã§ããããããã®ã·ã§ã¼ãã«ãããå©ç¨åºæ¥ãªããã¨ã«æ¯åã¹ãã¬ã¹ãæãã¦ãã¾ããã ããã§ããã¼ã«ã«ã®ã¨ãã£ã¿(Neovim)ã§BigQueryã®SQLãå¿«é©ã«æ¸ãæ¹æ³ãæ¢ããã¨ã«ãã¾ããã
BigQueryã¯SQLã«ãã£ã¦å®è¡åºæ¥ã¾ãã ããã¦ããã¡ããã§ããSQLã®Language Serverãè¤æ°åå¨ãã¾ãã åãç¥ã£ã¦ããLanguage Serverã¨ãã¦ã¯sql-language-serverãsqlsãããã¾ãã sqlsã¯BigQueryããµãã¼ããã¦ãã¾ããããsql-language-serverã¯adapterã¨ãã¦BigQueryã®ãµãã¼ãããã¦ãã¾ãã ããããå®éã«åã使ã£ã¦ã¿ãã¨ãããã®ãµãã¼ãã¯ä¸ååã«æãã¦ãã¾ããã
å人çãªæè¦ã§ãããåSQLã®å®è¡ç°å¢ã«ã¯æ¹è¨ãããBigQueryã¯ä»ã®RDBMSãªã©ã¨æ¯è¼ãã¦ç¹ã«ãã®æ¹è¨ãå¼·ãæãã¦ãã¾ãã ãã®ãããBigQueryã§å¿«é©ã«SQLãæ¸ãããã«ã¯BigQueryå°ç¨ã®Language Serverã§ãªãã¨ãããªãã®ã§ã¯ãªããã¨æ¼ ç¶ã¨æãã¦ãã¾ããã ãããªãã®ã¯å½ç¶ããã¯ãããªããBigQueryç¨ã®SQLãæ¸ãã¨ãã«ã¯Web UIä¸ã§æ¸ãããè³å è£å®ãããããã¦æ¸ãã¦ãã¾ããã
ãããªã¢ã¤ã¢ã¤ãæãã¦ããã¨ãã«ãgoccyããã®BigQueryã¨ãã¥ã¬ã¼ã¿ã®ä½ãæ¹ã¨ããã¹ã©ã¤ãã«åºä¼ãã¾ããã ããã¯Googleã®GitHub Orgã§æä¾ããã¦ããOSSã§ããzetasqlãå©ç¨ãã¦ãããã®ã§ããã ããã«é©ãã¹ããã¨ã«zetasqlãC++ã§æ¸ããã¦ããã®ãGoã§ã©ããããgo-zetasqlãå ¬éãã¦ããã¦ãã¾ããã åã¯Goã§Language Serverãä½ã£ãçµé¨ããã£ã*1ã®ã§ãBigQueryã®Language Serverãä½ã£ã¡ãããã¼ã¨ããããªã§bqlsãä½æãããã¨ã«ãã¾ããã ãããgo-zetasqlãç¡ããã°ä½ããã¨æããããªãã£ãã®ã§goccyããã«ã¯ãããæè¬ãã¦ãã¾ãã
ã©ããã£ã¦è£å®ãããã®ã
è£å®ãããããã«ã¯SQLã®ãã¼ã¹ãè¡ãå¿ è¦ãããã¾ãã ãã¼ã¹ã«ã¯åè¿°ããéããgo-zetasqlãå©ç¨ãã¦ãã¼ã¹ããã¾ãã
catalog := types.NewSimpleCatalog(catalogName)
langOpt := zetasql.NewLanguageOptions()
opts := zetasql.NewAnalyzerOptions()
opts.SetLanguage(langOpt)
output, _ := zetasql.AnalyzeStatement("SELECT created_at FROM `bigquery-public-data.samples.github_nested`", catalog, opts)
fmt.Println(output.Statement().DebugString())
çµæã¯æ¬¡ã®ãããªå½¢ã«ãªãã¾ãã
QueryStmt +-output_column_list= | +-bigquery-public-data.samples.github_nested.created_at#3 AS created_at [STRING] +-query= +-ProjectScan +-parse_location=0-67 +-column_list=[bigquery-public-data.samples.github_nested.created_at#3] +-input_scan= +-TableScan(parse_location=23-67, column_list=bigquery-public-data.samples.github_nested.[repository#1, actor_attributes#2, created_at#3, public#4, actor#5, payload#6, url#7, type#8], table=bigquery-public-data.samples.github_nested, column_index_list=[0, 1, 2, 3, 4, 5, 6, 7])
ç°¡åã«èª¬æãããã¨ãQueryStmt
ãï¼ã¤ã®SQLã¯ã¨ãªæã表ãã¦ãã¾ãã
ããã¦ãQueryStmt
ã®query
ã®è¦ç´ ã§ããProjectScan
ãSELECT
ããå§ã¾ãã¯ã¨ãªã®å
容ã«ã¤ãã¦è¡¨ãã¦ãã¾ãã
ãã®è¦ç´ ã§ããinput_scan
ãFROM
以éã®å
容ã表ãã¦ãããä»åã¯bigquery-public-data.samples.github_nested
ã¨ãããã¼ãã«ãæãã¦ãã¾ãã
åãã¼ãã«ãä½ã®ã«ã©ã ãæã£ã¦ãããã¨ããæ
å ±ãanalyzerãèå¥ã§ããããã«ããå¿
è¦ãããã®ã§ãããã©ã®ããã«ç»é²ãããã«ã¤ãã¦ã¯æ¬ããã°ã§ã¯çç¥ãã¾ãã
ã¨ã«ãããgo-zetasqlãå©ç¨ãããã¨ã«ãã£ã¦ç°¡åã«ãã¼ã¹ãè¡ããã¨ãåºæ¥ã¾ããã
ãã®æ
å ±ãå©ç¨ãã¦ãSELECT
ã®å¾ãã§è£å®ããã¨ãã«ã¯ãã¼ãã«æ
å ±ããã«ã©ã ãã¼ã¿ãå¼ã£å¼µãåºãã¦è£å®ãããã°ããã®ã§ãã
Language Serverãªãã§ã¯ã®ãã¼ã¹ã®é£ãã
åç¯ã§ã¯ãã¼ã¹ããåºæ¥ãã°è£å®ãåãã¨ããã話ããã¾ããã ã¾ããå®éã«ãã¼ã¹ãåºæ¥ã¦ãè£å®ãåºãã®ã¯ç°¡åã§ã¯ç¡ãã®ã§ãããç°¡åã¨ãããã¨ã«ãã¦ãã®ã¾ã¾é²ãã¾ãã ããã§ã¯Language Serverãªãã§ã¯ã®ãã¼ã¹ã®é£ããã«ã¤ãã¦èãã¦ã¿ã¾ãããã
ã¿ãªãããè£å®ã欲ããå ´é¢ã¨ã¯ã©ã®ãããªç¶æ³ã§ããããï¼
次ã®ãããªã¯ã¨ãªãæ¸ããã¨ãã®ãã¼ã¹ã«ã¤ãã¦èãã¦ã¿ã¾ãããï¼|
ã¯ã«ã¼ã½ã«ã®ä½ç½®ã表ãã¦ãã¾ãï¼ã
SELECT | FROM `project.dataset.table`
ãã®ãã¿ã¼ã³ã¯é »åºãã¾ãã
project.dataset.table
ã«ã©ã®ãããªã«ã©ã ãããããåãããªãã¨ãã«è£å®ã«ãã£ã¦é¸æãããå ´é¢ã§ãã
ãã¦ããã®ã¯ã¨ãªãzetasqlã§ãã¼ã¹ããã¨ã©ããªãã§ããããï¼
INVALID_ARGUMENT: Syntax error: SELECT list must not be empty
SELECTã®ä¸ã®ãªã¹ãã空ã§ã¯ãããªãã¨ãã趣æ¨ã®ã¨ã©ã¼ãè¿ã£ã¦ãã¾ãã ãããBigQueryã®ã¯ã¨ãªã®çµæãè¿ããµã¼ãã¼ãä½ãã ãã§ããã°SQLããã¼ã¹ã«å¤±æããå ´åã¯ãã®ã¾ã¾ã¦ã¼ã¶ã¼ã«ã¨ã©ã¼ãè¿ãã ãã§è¯ãã§ãããã ããããç·¨éããä¸ã§ã¯SQLãææ³çã«æ£ãããªãç¶æ³ãã»ã¨ãã©ãªã®ã§ãã ãããªä¸ã§ãè£å®ãªã©ã®æ©è½ã使ãããã«ãªãã¨ããã¼ã¹ããæ å ±ãåå¾ããªãã¨ãããªãã®ãLanguage Serverãªãã§ã¯ã®ãã¼ã¹ã®é£ããã§ãã
ãªãã¨ããã¼ã¹ãã
ãã®ãããªãã¼ã¹ã®é£ããã¯Language Serverç¹æã®ãã®ã§ãããã ãã®ãããåLanguage Serverãã©ã®ããã«ãããã®åé¡ã解決ãã¦ãããã調ã¹ã¦ã¿ããã¨ã«ãã¾ããã
ã¾ãåãã«åè¿°ããsqlsãã©ã®ããã«ãã¼ã¹ãã¦ããã®ãã調ã¹ã¦ã¿ã¾ãã sqlsã«ã¤ãã¦ã¯ãä½è ã®lighttiger2505ãããããã°ã«ã©ã®ãããªæ¹éã§å®è£ ããããæ¸ãã¦ãã ãã£ã¦ããã®ã§ãããåèã«ããã¦ããã ãã¾ããã sqlsã§ã¯æ§æãã°ã«ã¼ãã³ã°å¦çããéä¸ã§ã¨ã©ã¼ã«ãªã£ã¦ãã¹ã«ã¼ãããããªãã¼ãµã¼ãèªä½ãã¦ããããã§ãï¼ã¾ã¡ãã£ã¦ãããããã¾ããï¼ã ä»ã«ãRustã®Language Serverã§ããrust-analyzerãåæ§ã«Rustæ¬ä½ã¨ã¯ç°ãªãç¬èªã®ãã¼ãµã¼ãå®è£ ãã¦ããããã§ã*2ã Rustãå ¬å¼ã©ã¤ãã©ãªã¨ãã¦æä¾ãã¦ãããã¼ãµã¼ã«ã¤ãã¦ã¯å®ç¾©åå¾ã®ã¨ããªã©ã«å©ç¨ãã¦ããããã§ãã å ¬å¼ãã¼ãµã¼ã¨éãç¬èªãã¼ãµã¼ã§ã¯ã¨ã©ã¼ããã£ã¦ãå¦çãæ¢ãããã¨ç¡ãçµæãè¿ããããªä½ãã«ãªã£ã¦ããããã§ãã
sqlsãrust-analyzerã®ãããªç¬èªãã¼ãµã¼ãå®è£
ãã以å¤ã«ã¯æ¹æ³ã¯ç¡ãã®ã§ããããï¼
Goã®Language Serverã§ããgoplsã¯ç¬èªãã¼ãµã¼ãå®è£
ããã«å
¬å¼ã©ã¤ãã©ãªã§ããgo/parser
ãç¨ãã¦å®è£
ããã¦ãã¾ãã
goplsã§ã¯ãªãã¨ããã¼ã¹ãã§ããã¾ã§æ©æ¢°çã«ä¿®æ£ã試ã¿ãã¨ããæ¹æ³ãåããã¦ãã¾ãã
bqlsã§ã¯goplsã¨åæ§ã«ãã¼ã¹ãæåããã¾ã§ãã¡ã¤ã«ãä¿®æ£ããã¨ããæ¹æ³ãæ¡ç¨ãã¾ããã
ãã®æ¹æ³ã®ã¡ãªããã¯ãªãã¨ãã£ã¦ããã¼ãµã¼ãå®è£
ããã³ã¹ããæããã¨ãªãå®è£
ãã§ãããã¨ã§ãã
ãã¡ãªããã¨ãã¦ã¯ãã¡ã¤ã«ã®ä¿®æ£ãä¸å®å
¨ã ã¨ãã¼ã¹ãåºæ¥ãªããã¨ã§ã*3ã
ä¿®æ£æ¹æ³ãèãã
å ç¨ã®ä¾ã§ãã次ã®SQLæã«ã¤ãã¦èãã¦ã¿ã¾ãã
SELECT | FROM `project.dataset.table` -- INVALID_ARGUMENT: Syntax error: SELECT list must not be empty
ãã®ä¾ã§ã¯SELECTã¨FROMã®éã«ä½ãç¡ããã¨ãåé¡ã«ãªã£ã¦ãã¾ãã
ãã®ããããã®ä¾ã§ã¯é©å½ã«*
ãªã©ãããããã¨ã«ãã£ã¦ææ³ã¨ã©ã¼ã¯ç¡ããªãããã§ãã
SELECT * FROM `project.dataset.table` -- ok
ã§ã¯ç¶ãã¦æ¬¡ã®SQLæã«ã¤ãã¦èãã¦ã¿ã¾ãããã
SELECT i FROM `project.dataset.table` -- Unrecognized name: i
ãã®ããã«ãã¼ãã«ã«åå¨ããªãèå¥åãæ¸ããã¨ã¯ç·¨éããä¸ã§ã¯å¤ãããã¾ãã
ä¾ãã°ããã¼ãã«ã«identity
ã¨ããååã®ã«ã©ã ããã£ãå ´åã«ã¯i
ããé çªã«å
¥åãã¦ããã¾ãã
ã¦ã¼ã¶ã¼ãidentity
ãå
¥åãããã¾ã§ãã®ã¨ã©ã¼ãåºç¶ãã¾ãããæ£ç´è£å®ã§ã±ã£ã¨é¸æããããªãã¨ããã§ãã
ãã®ã¨ã©ã¼ã«ã¤ãã¦ã*
ãå
¥ããã ãã§è¯ãã§ããããï¼
SELECT * FROM `project.dataset.table` -- ok
å®ã¯æ¬¡ã®ãããªã±ã¼ã¹ã§ã¯*
ã ã¨ã¨ã©ã¼ã解æ¶åºæ¥ã¾ããã
SELECT id, i| -- Unrecognized name: i name FROM `project.dataset.table`
ããã*
ã§ç½®ãæããã¨æ¬¡ã®ãããªã¨ã©ã¼ã«ãªã£ã¦ãã¾ãã¾ãã
SELECT id, * name -- Syntax error: Expected end of input but got identifier "name" FROM `project.dataset.table`
ãã®ããã«SQLãæ©æ¢°çã«ç´ãã®ã¯ãªããªãèãããã¨ãå¤ãæ£ç´å¤§å¤ã§ããã ãããªããã¼ãµã¼ãèªä½ããã»ããè¯ãã£ãã®ã§ã¯ã¨èªåèªçããããã¦ãã¾ãã
ã¡ãªã¿ã«ä¸ã®ä¾ã«ã¤ãã¦bqlsã§ã¯1
ã¨ããINT64ãªãã©ã«ã§ç½®ãæãããã¨ã«ãã£ã¦ãã¼ã¹ããã¦ãã¾ãã
SELECT id, 1 name --ok FROM `project.dataset.table`
1 name
ã®ããã«æ¸ãã¨1 AS name
ã¨åçã®ææ³ã«ãªãããããã¼ã¹ã¯å¯è½ã§ãã
ããã§ãããã¤ã対å¿ã§ããªããã¿ã¼ã³ãããã®ã§ããè¯ãæ¹æ³ã模索ä¸ã§ãã
ã¾ã¨ã
æ¬ããã°ã§ã¯BigQueryç¨ã®Language Serverãå®è£ ãã話ã«ã¤ãã¦æ¸ãã¾ããã bqlsã¯èªåãæºè¶³ããå½¢ã«ãªãã°ããããªã¨æã£ã¦ãã³ã½ã³ã½ä½ã£ã¦ããã®ã§ããæè¿Issueãã¡ãã¡ãå±ãããã«ãªãããããªãå ¬éã¾ã§ãã¡ãããã¨æã£ã¦ããã°åããã«è³ãã¾ããã
æ£ç´ãzetasqlã¨ããC++ã©ã¤ãã©ãªãcgoã§å©ç¨ããããã«ãªã£ãçµæã¯ãã¹ã³ã³ãã¤ã«ãåºæ¥ãªããªããããã¨æ ¼éãã話ãªã©ãããã®ã§ãããã®è©±ã¯ã¾ãå¾æ¥ã©ããã§æ¸ãããè¯ããªã¨æãã¾ãã èªåã¨ãã¦ã¯å¾æã§ã¯ãªãè¨èªã触ãã¨ããç·¨éãé£ããã¨ãã«Language Serverãä½ããã¨ã§èªåã®ï¼ããã¦ä»ã®äººã®ï¼ï¼éçºä½é¨ãåä¸ããããã¨ãã§ããã¨ããçµé¨ãåºæ¥ãã®ã¯è¯ãã£ãã§ãã
We are hiring
ãªã«ãéçºã§è©°ã¾ã£ãã¨ãã«ãLanguage Serverãä½ããªã©ã¶ã£é£ãã é¸æè¢ãåãã仲éãåéãã¦ãã¾ãã ã«ã¸ã¥ã¢ã«é¢è«ãªã©ãåéãã¦ããã®ã§ã¾ã話ãã¦ã¿ããã¨ããæ¹ãæ¯éã
ã¨ã³ã¸ãã¢æ¡ç¨ãã¼ã¸ã¯ãã¡ã
ã«ã¸ã¥ã¢ã«é¢è«ããæ°è»½ã«ã©ãã
ã¤ã³ã¿ã¼ã³ã常æåéãã¦ãã¾ã
*1:Regoã¨ããè¨èªãåå¼·ãã¦ãã¾ããããå½æLanguage Serverããªãã¦å®è¡ã¾ã§ã¨ã©ã¼ãåããããè¾ããªã£ã¦ãã¾ãããããã§regolsã¨ããLanguage Serverãä½æãã¾ããã
*2:https://github.com/rust-lang/rust-analyzer/blob/067b4a32dd267d2599f908fc556491be45af7176/docs/dev/architecture.md#cratesparser
*3:ã¡ãªã¿ã«åã以åä½ã£ãregolsã§ã¯ãã®ç¯ã§æããï¼ã¤ã®ææ³ã®ã©ã¡ãã使ã£ã¦ãã¾ãããregolsã§ã¯ãã¼ã¹å¯è½ã§ãã£ãææ°ç¶æ ã®æ§ææ¨ãä¿åãã¦ãããããããã®å·®åããè£å®ãã¹ãåè£ãæ¨è«ããã¨ãã£ãæ¹æ³ã§è¡ã£ã¦ãã¾ãã