MySQL道普請便り

第6回 mysqlコマンドラインクライアントにページャーを指定する

この記事を読むのに必要な時間:およそ 4 分

勉強のためにMySQLをインストールしてデータを投入してみたはいいものの…バンドルされている標準のmysqlコマンドラインクライアントは,使いにくくありませんか? 飾りっ気のないプロンプトにパースが面倒なASCIIの罫線,無いも同然なTabキー補完,間違えて10万行くらいヒットしてしまうと見えなくなる先頭の行…。

今回はそんな悩みを解決するためのmysqlコマンドラインクライアントのTIPSとして,pagerサブコマンドを紹介します。この機能はmysqlコマンドラインクライアントの機能であるため,それ以外のコマンドラインクライアントでは利用できません。また,Windows版のmysqlコマンドラインクライアント(サーバはWindows版のものでも構いません。クライアントです)はページャーに対応していないのでごめんなさい。

デモンストレーション環境について

去る2015/10/21,MySQLの最新版となるMySQL 5.7が製品リリースされました。

が,この回で利用している環境は,第2回 MySQLにはじめてのデータを入れてみるで利用したものを「そのまま」利用しています(つまり,MySQL 5.6のままです)⁠2015/11/02現在,MySQLのyumリポジトリを新しくセットアップしようとした場合,MySQL 5.7がデフォルトで有効となったリポジトリが登録されますmysql-community-release-*.rpmだったファイル名が,mysql57-community-release-*.rpmに変わっています)が,今回紹介するTIPSはMySQL 5.6でもMySQL 5.7でも有効なものを紹介しますので,どちらのバージョンのクライアントでも問題ありません(そして古いMySQL 5.1やMySQL 5.5のクライアントでも問題ありません)⁠

なお,自身の利用しているmysqlコマンドラインクライアントのバージョンを確認するには,--versionオプションを利用します(例として,MySQL 5.7, 5.6, 5.5のコマンドラインクライアントの出力を記載しておきます)⁠


$ /usr/mysql/5.7.9/bin/mysql --version  ### MySQL 5.7のコマンドラインクライアント
/usr/mysql/5.7.9/bin/mysql  Ver 14.14 Distrib 5.7.9, for Linux (x86_64) using  EditLine wrapper

$ /usr/mysql/5.6.27/bin/mysql --version ### MySQL 5.6のコマンドラインクライアント
/usr/mysql/5.6.27/bin/mysql  Ver 14.14 Distrib 5.6.27, for Linux (x86_64) using  EditLine wrapper

$ /usr/mysql/5.5.46/bin/mysql --version ### MySQL 5.5のコマンドラインクライアント
/usr/mysql/5.5.46/bin/mysql  Ver 14.14 Distrib 5.5.46, for Linux (x86_64) using  EditLine wrapper

オプション記法の約束事

本題に入る前に,mysqlコマンド(に限らず,MySQLのプログラム全般…mysqlコマンドやmysqldumpコマンドなどのクライアント,MySQLサーバであるmysqldコマンドも同様です)の解釈するオプションの記法について記載しておきます。

mysqlコマンドの解釈する,⁠値を取るオプション」は原則「ショートオプション 空白文字 値」⁠ショートオプション 値」⁠ロングオプション 空白文字 値」⁠ロングオプション イコール 値」のいずれかの形式で与える必要があります。たとえば,接続ユーザーを指定する-u--userオプションを与える方法は以下の4通りです。

  • mysql -u root ⁠ショートオプション 空白文字 値)
  • mysql -uroot ⁠ショートオプション 値)
  • mysql --user root ⁠ロングオプション 空白文字 値)
  • mysql --user=root ⁠ロングオプション イコール 値)

ただし,パスワード-pまたは--passwordオプションのみ例外となっていて,⁠ショートオプション 値」⁠ロングオプション イコール 値」のいずれかの形式しか取れなくなっています(空白文字を入れて指定する形式が利用できません)⁠

これは,-pオプションは「値を指定された場合はそれをパスワードとして扱う」⁠値が指定されずオプションのみ指定された場合はパスワードプロンプトを表示する」という2通りの動作があるためこのような制約になっています。空白文字を許して値を解釈しようとすると,空白文字の次に来る文字列がパスワードなのか別のオプションなのかの判定がつかないのです(もし-pに空白値のパターンが許されたとすると,mysql -p database1「database1というパスワードを指定し,カレントデータベースは指定しない」⁠パスワードは指定せずパスワードプロンプトを表示し,カレントデータベースはdatabase1とする」と構文上区別がつかなくなります)⁠パスワードの指定時は-p'your_password'もしくは--password='your_password'の形式しか取れないことを憶えておいてください。

pagerオプション

mysqlコマンドにページャーを指定するには,--pagerオプションを指定するか,または,コマンドラインクライアントを起動した状態でpagerサブコマンドを利用します。百聞は一見に如かずと言います。まずは--pagerオプションにlessコマンドを指定して試してみましょう。

$ mysql --pager=less
mysql> SELECT NOW();

おわかりいただけたでしょうか。SELECT NOW()ステートメントの結果がいつも通りターミナルに流れるのではなく,パイプでlessコマンドに渡されたかのように振る舞います。このステートメントでは1行しか結果が返らないので感慨が薄いのですが…そうですね,たとえばこんなステートメントはどうでしょうか。

mysql> SHOW TABLES FROM information_schema;

information_schemaデータベースに含まれるテーブルを一覧するためのSQLですが,これはそこそこ行数があるのでlessコマンドの意味があるのではないでしょうか。さてこの出力結果を見ていると,INNODB_*というテーブルがいくつかあるのが目につきました。lessコマンドにつなぐことができるのであれば,grepコマンドにつなぐことも簡単です。出力結果からINNODB_*にマッチしそうなテーブルだけをページャーを使ってフィルタリングしてみます。

$ mysql --pager="grep 'INNODB_'"
mysql> SHOW TABLES FROM information_schema;

想像した通りに出力されたでしょうか? カラム名の表示やASCIIで引かれた罫線だけの行は出力されませんでした。

図1 ページャーを使ったフィルタリングの結果

図1 ページャーを使ったフィルタリングの結果

これは,カラム名の行や罫線だけの行も含めたmysqlコマンドの出力結果をそのまま全てgrepコマンドに渡したため,"INNODB_"を含まない行であるこれらはgrepコマンドによってフィルタリングされてしまったからです。またその一方で,出力の最後の61 rows in set (x.xx sec)の行は"INNODB_"を含まないにも関わらずフィルタリングされることなく出力されています。これはこの行を出力する部分だけがページャーを通さずに直接sprintfでバッファに書き込まれているためなのですが,どういう思想でこうなっているのかはよくわかりません(興味のある方はこのあたりで実装されているので眺めてみてください)⁠

さて,勘の良い方はすでに気付かれているかも知れませんが,pagerオプションには「パイプを含めた複数のコマンド」を指定することもできます。たとえばさっきのgrepコマンドでフィルタリングをしつつ,その結果をlessコマンドに渡す,というようなオプションの記述は以下のようになります。

$ mysql --pager="grep 'INNODB_' | less"
mysql> SHOW TABLES FROM information_schema;

とても簡単ですね。しかし,ページャーを切り替えるために,都度mysqlコマンドを一度終了してpagerオプションをセットするのは少し面倒です。mysqlコマンドで接続したままページャーを切り替えるためのサブコマンド(ドキュメントなどでは単に「コマンド」とされていますが,mysqlコマンド以外のシェルから起動するコマンドと混同を避けるため,本記事の中ではmysqlコマンド内の「サブコマンド」というスタンスを取って記述しています)pagerサブコマンドです。そのまんまですね。

著者プロフィール

yoku0825

GMOメディア株式会社のDBA。日本MySQLユーザ会員。主に地雷担当。主食はMySQLだがPercona Server,MariaDB,InfiniDBにMroongaストレージエンジンなど,mysqldでありさえすれば雑食。

Twitter:@yoku0825

コメント

コメントの記入