vimから直接データベースを触る場合は、dbext.vim
を使用すれば良いとのこと。
今回接続したいのDBはSQLiteだけだが、dbext.vim
はその他多くのDB(Oracle, Sybase, Microsoft, MySQL, DBI,..)に対応しているとのこと。
dbextのインストール
NeoBundle 'vim-scripts/dbext.vim', '18.0'
公式のバージョンは20.0だが、githubには19.0までが上がっている。
ただし19.0で加えられた修正に少し問題があったため、ここでは特にこだわりもないため18.0を使用した。
(具体的にはcmd_terminator
の定義に問題あり。明示的にcmd_terminator
を指定するなどで回避はできる)
接続設定
接続先の指定方法には何種類かの方法があるが、
接続パラメータをまとめた接続プロファイルを使用するのが簡単かと思う。
- 接続パラメータを個別に
.vimrc
に設定 - 接続プロファイルを
.vimrc
に設定 - ウィザート的に接続パラーメタを指定(
<Leader>sbp
で利用可能) - Modelineを使用して接続パラメータを設定
接続プロファイルの設定
プロファイルは好きなだけ作成可能。
詳細はヘルプに用例がたくさんあるのでそちらを参照。
" 環境に合わせてクライアントプログラムを変更
" (ver.20.0 からはデフォルトでsqlite3)
let g:dbext_default_SQLITE_bin = 'sqlite3'
" プロファイルの定義
let g:dbext_default_profile_MySQL_test = 'type=SQLSRV:integratedlogin=1:dbname=myDB'
let g:dbext_default_profile_SQLServer_test = 'type=SQLSRV:integratedlogin=1:dbname=myDB'
let g:dbext_default_profile_test = 'type=SQLITE:dbname=/dbpath/test.db'
"デフォルトで使用するプロファイルを指定
let g:dbext_default_profile = 'test'
プロファイルの切り替え
プロファイルを切り替える場合は :DBSetOption profile=test
として直接指定するか、
<Leader>sbp
によるウィザートから選択する。
DBアクセス
テーブル一覧取得
<Leader>slt
とすれば画面下部のResultウィンドウに接続先DBのテーブル一覧が表示される。
Connection: T(SQLITE) D(/dbpath/test.db) at 03:33
Tables
------
Alphabeticallistofproducts
OrdersQry
Categories
ProductSalesfor1997
CategorySalesfor1997
Products
CurrentProductList
テーブル内容表示
テーブル名にカーソルを置いて<Leader>st
にてテーブル内容が表示される。
SQL文字列上で<Leader>se
でもSQLが実行されその結果が表示される。
Connection: T(SQLITE) D(/dbpath/test.db) at 03:35
TerritoryID TerritoryDescription RegionID
----------- -------------------------------- ----------
01581 Westboro 1
01730 Bedford 1
01833 Georgetow 1
02116 Boston 1
02139 Cambridge 1
02184 Braintree 1
02903 Providence 1
この時Javascriptファイルなどで、以下のように結合された文字列でも、<Leader>se
にてちゃんとSQLとして解釈し実行してくれる。
なお、この場合はプレースホルダの値を入力するプロンプトが表示される。
他のコマンド
他にもいろいろできますが、以下に一部だけ掲載。
テーブル以外にもViewやProcedureにも対応しているので利用したい場合はヘルプ参照。
デフォルトでのマッピングはすべて<Leader>s
で開始される。
これはg:dbext_map_prefix
で変更可能。
normalモード
キー | コマンド | 意味 |
---|---|---|
<Leader>sbp | DBPromptForBufferParameters | 接続先設定ウィザート |
<Leader>sh | DBHistory | 実行履歴表示 |
<Leader>slt | DBListTable | テーブルリスト表示 |
<Leader>sdt | DBDescribeTable | カーソル上のテーブル定義表示 |
<Leader>sdta | DBDescribeTableAskName | 任意のテーブル定義表示 |
<Leader>st | DBSelectFromTable | カーソル上のテーブルデータ表示 |
<Leader>sta | DBSelectFromTableAskName | 任意のテーブルデータ表示 |
<Leader>stw | DBSelectFromTableWithWhere | カーソル上テーブルデータ表示。Where条件指定可能 |
<Leader>sq | DBExecSQL | 任意のSQL実行 |
<Leader>se | DBExecSQLUnderCursor | カーソル上のSQL実行 |
visualモード
キー | コマンド | 意味 |
---|---|---|
<Leader>sdt | DBDescribeTable | 選択テーブル定義表示 |
<Leader>st | DBSelectFromTable | 選択テーブルの内容を表示 |
<Leader>se | DBExecVisualSQL | 選択SQLの実行 |
補完
SQLファイルを開き、
例えばO
を入力した状態で<C-c>t
を押すと、Oで始まるテーブルリストが表示される。
この状態で<Right>
を押すとそのテーブルのカラムリストが表示される。
単純に<C-c>c
だけでもカラムリストが表示される。
その場合のテーブルは前回選択したテーブルとなるが、これはSQLの文脈によって動的に切り替わる。(テーブル別名に合わせて表示されるカラムリストが変わる)
ちなみにテーブルリストで<C-c>L
押すとカラムを一気に出力できる。
この時の表別名OD
は自動で生成され、出力時に表示されるプロンプト画面にて変更も可能。
あるいはカーソルがテーブル上にある状態で:DBListColumn
か<Leader>slc
とすればカラム一覧がコピーされるので、それを貼り付けても同じようなことができる。
キーマッピング
補完に関するキーマッピンはこんな感じ。インサートモードです。
キー | 補完対象 |
---|---|
<C-c>a | syntax |
<C-c>k | sqlKeyword |
<C-c>f | sqlFunction |
<C-c>o | sqlOption |
<C-c>T | sqlType |
<C-c>s | sqlStatement |
<C-c>t | table |
<C-c>p | procedure |
<C-c>v | view |
<C-c>c | column |
<C-c>l | column_csv |
<C-c>R | キャッシュクリア |
<Right> | テーブルリストで押すとカラムリストへ |
<Left> | カラムリストで押すとテーブルリストへ |
<C-c>L | テーブルリストで押すとカラム一覧出力 |
キーマッピング変更
<Right>``<Left>
は遠いのでこれも変更可能。
let g:ftplugin_sql_omni_key = '<C-c>'
let g:ftplugin_sql_omni_key_right = '<C-d>'
let g:ftplugin_sql_omni_key_left = '<C-u>'
Javascriptからの利用
上記の補完はSQLファイルでしか使用できず、
Javascriptファイルにて補完したかったのでちょっと考えてみた。
ファイルタイプの変更
単純に:set ft=sql
でファイルタイプを変更すれば補完できる。
これはヘルプ(:h ft_sql
)にも書いてある方法なのだが、後で戻す必要もありよろしくない。
omnifuncの設定
JavascriptでSQLのomnifunc
を利用できれば良いので以下のように設定する。
neocompleteを使用している前提。
autocmd FileType javascript setlocal omnifunc=sqlcomplete#Complete
if !exists('g:neocomplcache_omni_functions')
let g:neocomplete#sources#omni#functions = {}
endif
let g:neocomplete#sources#omni#functions.javascript = ['javascriptcomplete#CompleteJS']
こうすれば普段はneocompleteによるJavascriptのオムニ補完がされ、
<C-x><C-o>
にて明示的にオムニ補完した場合にはSQLの補完が行われる。
ただこの方法では<C-c>t
などの補完は使えないので。
SQLの補完を直接呼び出す
シンプルに必要な補完は明示的に割り当ててやる方法も採用した。
これでSQLの場合と同じ方法で補完が利用できる。
exec 'inoremap <silent> '.g:ftplugin_sql_omni_key_right.' <C-R>=sqlcomplete#DrillIntoTable()<CR>'
exec 'inoremap <silent> '.g:ftplugin_sql_omni_key_left.' <C-R>=sqlcomplete#DrillOutOfColumns()<CR>'
exec 'inoremap <buffer> '.g:ftplugin_sql_omni_key.'t <C-\><C-O>:call sqlcomplete#Map("table")<CR><C-X><C-O>'
exec 'inoremap <buffer> '.g:ftplugin_sql_omni_key.'c <C-\><C-O>:call sqlcomplete#Map("column")<CR><C-X><C-O>'
exec 'inoremap <buffer> '.g:ftplugin_sql_omni_key.'l <C-\><C-O>:call sqlcomplete#Map("column-csv")<CR><C-X><C-O>'
exec 'inoremap <buffer> '.g:ftplugin_sql_omni_key.'R <C-\><C-O>:call sqlcomplete#Map("resetCache")<CR><C-X><C-O>'
まとめ
個人的な用途としては十分利用可能になった。
ただJavascriptからSQLite接続でしか利用していないものの多少問題もある。
例えば..
- シングルクォーテーションで囲ったSQL文字列は実行できない(ダブルクオーテーションならOK)
- テーブル定義にてカラム名が
[ ]
で囲まれているとカラムリストが正しく生成されない
シングルクォーテーションの問題は、
コマンド呼び出しを少し修正してプラグインに渡す前に置換することで対応した。
また[ ]
で囲ったテーブルは現在使用していないので今のところは関係ない。
最悪、DB毎で解析に使用される関数が以下のように分離されているので、
案外簡単に修正できそうなため問題が生じればその時に対応を考える感じでいく。
SQLITEの場合
- DB_SQLITE_describeProcedure
- DB_SQLITE_describeTable
- DB_SQLITE_execSql
- DB_SQLITE_getDictionaryProcedure
- DB_SQLITE_getDictionaryTable
- DB_SQLITE_getDictionaryView
- DB_SQLITE_getListColumn
- DB_SQLITE_getListProcedure
- DB_SQLITE_getListTable
- DB_SQLITE_getListView
- DB_SQLITE_stripHeaderFooter