開発に SQLite を使う時の注意点

皆さんは Web アプリの RDBMS には何を使っていますか?
巷では MySQL(MariaDB)、Oracle、PostgreSQL あたりが主流と聞きます。

しかし、これらを開発時に使うのはセットアップが面倒ですよね?
はい、そこ「Docker 使え」とか言わない。

面倒なので SQLite を使ってしまう時ありませんか?
え、使わない?ここは「使う」って言う所ですよ。空気読んでください。

というわけで(無理矢理ですが) SQLite で開発する時のトラップ注意点です。

一言で済みます。「データ型が INTEGER、REAL、TEXT、BLOB しかない!」のです。
つまり DATE とか TIME とか TIMESTAMP とかが無いのです。
まあ、他に DECIMAL とか BOOLEAN も使えませんが今回は見なかったことにします。

よって、SQL 文で日付形式や時間形式の演算および比較ができません。
…ええ、お察しの通り色々コード書いてから気付きましたとも。
指定日を含む期間を探す関数のテストを書いた時に判明しましたよ…
なまじ(文字列型としての)比較が期待通り動くものだから発覚が遅れました。

これから PostgreSQL を準備して再テスト&書き直しです。
Twelve factor app 10.開発/本番一致の意味が身に染みました。
願わくば、この記事が誰かの転ばぬ先の杖になると良いのですが。

gitprep の docker 化

前略
クラウド(ようやく)始めました。

「そうだ、Gitprep 入れてみよう!」
→ セットアップでエラー
→ いろいろ試してもエラー
…サーバ引っ越しの度にこんなエラー地獄では耐えられません。

「そうだ、Docker 使おう!」
→ perl イメージある
→ mojolicious イメージある
→ ソースコード足せば動く?

(3時間経過)

「や、やっと動いた…」
→ 他にも同じ苦労をする人がいるかも…(← いません)
→ 公開しなきゃ
→ ウェブログに投稿だ!

(1時間経過)

「記事書けたけど Dockerfile より短い…何故?」 ← 今ここ
作ったファイルはこちら

こっそり quickutil を使ってみた

トラブってたのを一つ前の記事に書いたわけですが、今度は調査メモです。

ネットを彷徨っていたところ quickutil の記事を見付けまして、色々試してみたんですよ。
まあ、公式サイトの http://quickutil.org/ の方で「under maintainance」って書いてあるので駄目元だったんですが。
なんとなく動いた感じなので方法をコッソリと書いておこうかと。
もちろん、やる場合には自己責任です。っていうかメンテ明けまで待つのが正しい態度ですよね…

使うだけなら次のようにすればいいです。
あらかじめ quicklisp を使えるようにしておいて下さい。
使いたいユーティリティは :shuffle だとします。適宜、置き換え願います。
リストを渡すので、一度に複数でも大丈夫のようです。

;; 準備
(ql:quickload 'quickutil)
;; 利用のための宣言(引数はキーワードのリストらしい)
(qtlc:utilize-utilities '(:shuffle))

;; 利用は "qtl:ユーティリティ名" で呼び出す模様
(qtl:shuffle '(3 2 1))

なお、ユーティリティのリストは以下で見られました。

;; 準備
(ql:quickload 'quickutil-utilities)

;; 全部
(qtl-utl:all-utilities)
;; カテゴリの一覧
(qtl-utl:all-categories)
;; カテゴリ内にあるユーティリティの一覧(例では integers カテゴリ)
(qtl-utl:utils-in-category :integers)

Use at your own risk!

いきなり slime が動かなくなった件

原因は不明ながら、slime が急にエラーで動かなくなってしまったので経過をメモ。
(思い出しながら書いているので、あやふやな部分あり)

検索したサイトを見ながら popwin の設定やら ac-slime のインストールやらをしていたら、ある時 M-x slime するとエラーするようになってしまった。
※正確には swank サーバへの接続待ちのままになった。表示通りに M-x slime-abort-connection するとキャンセルされて REPL には入れる。

その状態で (require 'asdf) (require 'alexandria) すると /usr/share/common-lisp/source/cl-asdf/build/asdf-TMP.lisp が FILE OPEN エラーになってデバッガに入ってしまった。
emacs を終了してコンソールから直接 sbcl で実行しても同じエラーになった。

~/.cache/common-lisp/ を削除してみたが直らず。
apt で slime と cl-asdf を再インストールしてもダメ。

以前に作成した以下のファイルを削除したら slime は起動するようになった。

;;;; ~/.config/common-lisp/source-registry.conf
(:source-registry
  (:tree "~/quicklisp/dists/")
  :INHERIT-CONFIGURATION)


require もエラーしなくなった… はず。ただ、相変らず (require 'alexandria) の返り値が nil だったのでダメかと思って作業を継続した。
この時点で最終結果と同じ状態に戻っていたのかもしれない。
(require 'asdf) の返り値が nil だったかは覚えていない。

その後、~/quicklisp/ も削除して slime から (load "/usr/share/cl-quicklisp/quicklisp.lisp") (quicklisp-quickstart:install) で再インストールしてみた。
ここで (ql:quickload 'alexandria) するとインストールが行われ、(alexandria:lastcar '(a b c)) が動作した。
そのまま更に (ql:add-to-init-file) を実行して設定ファイル(sbcl だったので ~/.sbclrc)に quicklisp の自動ロードを設定した。
一旦 emacs を再起動し、require するも返り値は nil のまま。
コンソールから sbcl でやっても同じく nil が返っていたが、何の気なしに alexandria:lastcar をやってみたら動作した。

ふと思い付いて .sbclrc の quicklisp 設定をコメントアウトしてから、コンソールで (require 'alexandria) したらエラーになった。
そのまま (load "~/quicklisp/setup.lisp") したところ alexandria:lastcar が動作した。

quicklisp 設定をコメントアウトしたままの状態で ~/.config/common-lisp/source-registry.conf をエラー前に戻してみた。
そうしたら (require 'alexandria) がエラーせずに nil を返し、alexandria:lastcar も動作するようになった。

元々は .sbclrc の quicklisp 設定はコメントアウトされていたので、結局エラー前と同じ設定に戻ったことになる。
経過から見るとキャッシュを壊していた確率が高いが、問題の原因は特定できず…
とりあえず動作するので、まあいいかと。

最終的にはコンソールでも slime でも以下のように動いている。
(行頭に「?>」があるのがプロンプトと入力内容で、次のプロンプトまでが出力)

?> (require 'asdf)
("ASDF" "asdf" "UIOP" "uiop")

?> (alexandria:lastcar '(a b c))
※以下のエラーが発生した
debugger invoked on a SB-INT:SIMPLE-READER-PACKAGE-ERROR in thread
#:
Package ALEXANDRIA does not exist.

Stream: #

Type HELP for debugger help, or (SB-EXT:EXIT) to exit from SBCL.

restarts (invokable by number or by possibly-abbreviated name):
0: [ABORT] Exit debugger, returning to top level.

(SB-IMPL::READER-FIND-PACKAGE "ALEXANDRIA" #)

※ 0 でデバッガを終了してトップレベルに戻る

?> (require 'alexandria)
nil

?> (alexandria:lastcar '(a b c))
c

以上。

persp-mode を設定してみた(ついでに helm も)

えー、今回は common lisp のコードを書こうと思ったらキーバインドが気になって、init.el を編集してるうちに elisp パッケージ探しに走ってしまい、気が付いたらリファレンスを見ながら elisp を書いていたという yak shaving の最たるものになってしまいました。
なので、せめて動いたコード片だけでも載せておこうと思います。

以下は persp-mode で新規パースペクティブを作成した時(厳密にはバッファがないパースペクティブに切り替えた時)にバッファを選択して登録する設定です。
毎度おなじみ rubikitch 様のサイトからコピーして、四苦八苦しながら希望する動作になるよう改造(改悪?)しました。
ホント、いつもお世話になってます。密度の濃い情報ありがとうございます。 > rubikitch 様
設定した persp-mode のバージョンは 20161226.2218 です。

;;; persp-mode 設定
(setq persp-add-on-switch-or-display t)
(persp-mode 1)
;;; 新規パースペクティブ作成時に追加するバッファを選択する
(defun persp-register-buffers () ; 関数名変更
  (interactive)
  (dolist (bufname (condition-case _
                       (helm-comp-read
                        "Buffers: "
                        (mapcar 'buffer-name (buffer-list))
                        :must-match t
                        :marked-candidates t)
                     (quit nil)))
    (persp-add-buffer (get-buffer bufname))))
;; ここから追加分
(defun persp-register-buffers-if-empty (mode)
  (interactive)
  (if (null (persp-buffer-list)) ; パースペクティブのバッファが空の時だけ
      (persp-register-buffers))) ; 上のバッファ選択関数を呼ぶ
(add-hook 'persp-activated-functions 'persp-register-buffers-if-empty) ; フック名が変わった?

それから、persp-mode 用の helm アクションも見様見真似で作ってみました。
いちおう動いているようですが、使用は自己責任でお願いします。

(defun helm-persp-add-buffer (buffer-or-name)
  (persp-add-buffer (helm-marked-candidates)))
(defun helm-persp-kill-buffer (buffer-or-name)
  (persp-kill-buffer (helm-marked-candidates)))
(setq helm-type-buffer-actions
      (append helm-type-buffer-actions
              '(("Add buffer(s) to perspective" . helm-persp-add-buffer)
                ("Kill buffer(s) from perspective." . helm-persp-kill-buffer))))

以上です。

nodoka で右 Shift キーが効かなかった件

昨日に引き続きキーカスタマイズのネタです。

実は Windows で Emacs 似のキーバインドを使いたいために nodoka というユーティリティを使っているんです。
で、今まで気付いては忘れてた挙動に「右 Shift キーでは Shift されない」というのがありました。

今回よく調べてみたところ、nodoka を一時停止すると問題無く Shift されるので、設定が原因だろうと色々試しました。
調査とログのダイアログを駆使して探った結果、下のような設定で無事に動きました。


# 右 Shift のキー名を定義
def key E0RightShift E0RShift = E0-0x36
# 右 Shift を 左 Shift とみなす
def subst E0RShift = LShift
# 仮想キーの Shift が押されるように設定
keymap Global
mod shift += E0RShift
key *E0RShift = *LShift
# nodoka を使いたくないキーマップ(KeymapDefault)にも適用
keymap KeymapDefault
mod shift += E0RShift
key *E0RShift = *LShift

これはマニュアル(カスタマイズ詳細)中央あたりの次の部分を参考にしました。

なお、右シフトキーが使えないことは致命的なので、ホスト側の のどか設定ファイルでは、window RemoteDesktop /mstsc\.exe/ を記述し、ホスト側でのキー入れ替えは無いことにして、リモート側のどかの設定ファイルでは、下記のような設定をすると良いでしょう。

def key E0RightShift E0RShift = E0-0x36

mod shift += E0RShift

key *E0RShift = *LShift

カスタマイズまわりはハマると面倒ですね。

Putty 経由の Emacs で C-M-S-v が入らない件(未解決)

今回は Emacs です。
以前から使ってはいたのですが、ここを参考に設定しなおしてみようかと思いまして。

とりあえず Ubuntu Linux の仮想マシンを用意して Putty でログインして Emacs をいじっていました。
で、サンプルの通りにキーバインド「C-,」を割り当てて使ってみると動きません。
現在の割り当てを調べる「C-h c C-,」を使ったところ、どうも「C-,」が Linux に入っていないようでした。

この問題については最終的にこのサイトを参考にして解決できました。

該当ページ中から「xterm風定義」リンクを辿ると他のキー一覧もあります。
その中でカンマを示す「VKey188」の行ですが、以下(4番目が \033[27;6;60~)が正しいのではないかと思います。
VKey188=\054,<,\033[27;5;44~,\033[27;6;60~,\033\054,\033<,\033[27;13;44~,\033[27;14;60~

引き続いて「C-M-v」の別ウィンドウスクロールの逆方向版を「C-M-S-v」(Shift を追加する)に割り当てようとしましたが、こちらは解決できませんでした。
「C-,」と同様に「VKey…」を追加すればいいかと思って下のように色々試したのですがダメでした。

試した内容

  • VKey86=,,,,,,,\033[27;14;118~
  • VKey86=,,,,,,,\033[27;14;86~
  • VKey86=,,,,,,,\033[27;14;v~
  • VKey86=,,,,,,,\033[27;14;V~
  • VKey86=,,,,,,,\033[27;5;118~
  • VKey86=,,,,,,,\033[27;5;86~
  • VKey86=,,,,,,,\033[27;5;v~
  • VKey86=,,,,,,,\033[27;5;V~

カンマ区切りのキーコード出力部の内容は 「\033[27;≪修飾コード≫;≪キーコード≫~」だろうと思っています。
この中にある「27」は多分 Escape キーの VKey コードでしょう。

どれも思うようにいかなかったので、現在はエスケープシーケンスの規則を調査中です。
参考サイトに書いてある気もしますが、英語を読むのが面倒なので Try&Error で頑張ります。

参考サイト

ちなみに「C-,」問題は nadoka で「key C-Comma = &SendText("\e[27;5;44~")」でも解決できましたが、対象文字列を入れる時に一文字ずつ(少しだけ)ウェイトがかかって微妙な気分になるので止めました…

コードのスタイルを統一するなら EditorConfig

複数の作業環境を渡り歩いてソースコードを編集することって結構ありますよね?
こんな時、新しく編集した部分だけインデント文字(タブかスペース)やオフセットが変わってしまって、手作業でスタイルを合わせる破目になった経験があるでしょう。
テキストエディタが同じなら作業前に設定ファイルをコピーすればなんとかなりますが、違うエディタだと設定に使った時間の方がコーディング時間より長くなったという悲劇(笑い話?)も聞きます。

そんな時に頼りになる最終兵器 EditorConfig を発見しました。
共通の設定ファイルを用意しておけば、エディタにプラグインを入れるだけで同じスタイルで書けるようにしてくれます。
設定できる項目はインデント文字、オフセット幅、改行文字、文字コード等です。
ディレクトリを遡りながら設定ファイルを探すので、スタイルがプロジェクトごとに違っていても対応できます。

興味がわいた方は、分かりやすい説明がここにあるので参照してみてください。

参考

  • 公式サイトはここ
  • Emacs 用プラグインは Github

パスワードの別メール送信は無意味

仕事でファイルをメールする時に、暗号化したファイルを添付したメールと、そのパスワードを書いたメールを別々に送信するケースをよく見かけます。

私はこれを無意味だと思っています。
なぜなら、暗号化ファイルのメールを入手できるならば、パスワードのメールも入手できると考えるのが妥当だからです。
暗号化ファイルとパスワードの両方が揃ってしまえば、元のファイルを(暗号化せずに)そのまま送ったのと同じ事になります。
むしろ『安全に送った』気になる分だけ逆に危険です。

安全な方法で一番簡単なのは『電話する』ことです。
次点としては『SMSで送る』(スマホや携帯で相手の電話番号を使ってメッセージを送る機能)でしょうか。
どちらの場合も『メールとは別の手段』を使って『メールアドレスとは別の方法』で指定した相手に伝わる点が重要です。

どうしてもメールする場合には、せめてパスワード文字列の一部分だけを伝えて、それの【前】と【後ろ】に事前に決めておいた文字列を追加するくらいの用心をすべきです。
例えば【前】には「mae_」を、【後ろ】には「_usiro」を付けると事前に決めておけば、メールで「pass」と送った場合の実際のパスワードは「mae_pass_usiro」になるわけです。
次の機会にパスワードとして「word」とメールしたら、実際のパスワードには「mae_word_usiro」を使えばいいわけです。
これならばメールにパスワード全文が記載されないので、多少はマシになります。
もちろん、前後に追加する文字列はメール以外の手段で伝えるのは言うまでもありません。

ちなみにパスワードの類似品として『パスフレーズ』というものが使える場合もあって、きちんと使えばこちらの方が強度が高いそうです。

以上、知らないと怖いパスワードの話でした。

暗号化とか署名とかハッシュとか

まずは、ざっくりとした一覧です。

こうしてまとめてみると、思っていたよりも色々ありますね。

特に Windows に certutil コマンドがあって、エンコードとハッシュ計算ができるのには驚きました。

それと、暗号化ファイルを元に戻す時には(大抵の場合)同じソフトが必要になります。 渡す相手には何のソフトで暗号化したか伝えておきましょう。