🍋

VimのBigQuery簡易プラグインを作ってる(2)

2022/10/16に公開

リポジトリ
https://github.com/IwasakiYuuki/bqrunner.vim

前回の記事
https://zenn.dev/pluck/articles/f82e2144e55295

作りたいもの・機能

  • (Must)vim上で編集しているStandard SQLの必要な処理バイト数がわかる
  • (Must)vim上で編集しているStandard SQLがエラーが返るかどうかわかる
  • (Must)エラー文を手元で確認できるようにする
  • (Want)Standard SQLの補完機能(関数やDBのカラム名)

この記事で書く内容

  • (Must)エラー文を手元で確認できるようにする

現在のプラグイン全貌(bqrunner.vim)

├── README.md
├── test.bq
├── doc
├── autoload # こっちに主に処理を書く
│   └── bqrunner.vim
└── plugin # こっちはプラグインのコマンド定義
    └── bqrunner.vim

今回はQuickfixにエラー文を表示するだけなので,autoload/bqrunner.vimに処理をほんの少し追記するだけ.

Quickfixにエラー文を挿入する

autoload/bqrunner.vim 一部抜粋
fun! bqrunner#dry_run(file) abort
  let l:command = 'cat ' . a:file . ' | bq query --dry_run --use_legacy_sql=false --'
  let l:result = system(l:command)
  let w:bqrunner_is_query_success = s:is_query_success(l:result)
  if w:bqrunner_is_query_success
    let l:bytes = s:get_bytes_from_result(l:result)
    let w:bqrunner_dry_run_bytes = s:convert_bytes_unit(l:bytes)
  else
    let w:bqrunner_error_msg = s:get_error_msg_from_result(l:result)
    call setqflist([w:bqrunner_error_msg], 'r')
  endif
endf

fun! s:get_error_msg_from_result(result) abort
  if match(a:result, '\[[0-9]\+:[0-9]\+\]') != -1
    let l:ml = matchlist(a:result, '\[\([0-9]\+\):\([0-9]\+\)\]')
    return {
    \ 'filename': @%,
    \ 'lnum': l:ml[1],
    \ 'vcol': l:ml[2],
    \ 'text': a:result,
    \ 'type': 'E',
    \ 'nr': '1',
    \ }
  else
    return {
    \ 'filename': @%,
    \ 'text': a:result,
    \ 'type': 'E',
    \ 'nr': '1',
    \ }
  endif
endf

help setqflistでドキュメントを確認すると,引数に指定された形式の辞書の配列(下のlist)を取るようになっているため,それに合わせてfilenamelnum(行数)などの指定してあげる.

help setqflist
setqflist({list} [, {action} [, {what}]])		*setqflist()*
		Create or replace or add to the quickfix list.

		If the optional {what} dictionary argument is supplied, then
		only the items listed in {what} are set. The first {list}
		argument is ignored.  See below for the supported items in
		{what}.
							*setqflist-what*
		When {what} is not present, the items in {list} are used.  Each
		item must be a dictionary.  Non-dictionary items in {list} are
		ignored.  Each dictionary item can contain the following
		entries:

		    bufnr	buffer number; must be the number of a valid
				buffer
		    filename	name of a file; only used when "bufnr" is not
				present or it is invalid.
		    module	name of a module; if given it will be used in
				quickfix error window instead of the filename.
		    lnum	line number in the file
		    pattern	search pattern used to locate the error
		    col		column number
		    vcol	when non-zero: "col" is visual column
				when zero: "col" is byte index
		    nr		error number
		    text	description of the error
		    type	single-character error type, 'E', 'W', etc.
		    valid	recognized error message

そして今回のl:resultはbqコマンドのエラー出力で[2:9]のように行数と列数(先頭からのバイト数)がわかる場合があるので,その場合のみQuickfixにもその情報を渡してあげる.

実際の画面はこんな感じで,上のSQLではFROMで指定しているテーブルが存在していないというエラーが出ている.

このプラグインでDryRunが走った時点でエラーがあればQuickfixに格納されるので,好きなタイミングで:copenでQuickfixを開いて確認する感じ.

他にも,エラーの行数・列数がわかる場合は下のようになる.
(hogehogeというカラムが存在しないと言われており,Quickfixから該当箇所に飛べる)

次やること

  • (Want)Standard SQLの補完機能(関数やDBのカラム名)

正直これは結構難しそう.関数の補完となると言語サーバが必要になりそうだけど,ちょっと探したけど無かったのでDBカラム名やテーブル名の補完だけ頑張ろうかな...

でもとりあえず,手元のエディタでクエリの成功・失敗と必要な処理バイト数,あとエラー文も確認できるようにはなった.

Discussion