Caveman2でMySQL利用

##１．はじめに##
ちょっと間が空きましたが，相変わらずCaveman2をいじってます。
今回はDB，MySQLを使おうと思います。

##２．準備##
###２．１．環境###
Max OS X 10.10.1，Clozure Common Lisp 1.10，MySQL 5.6.21でやっていきます。
###２．１．MySQL###
適当にデータベースを作ります。

```sql:myappdb.sql
CREATE SCHEMA IF NOT EXISTS `myappdb` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci ;

GRANT ALL PRIVILEGES ON `myappdb`.* TO `yazc`@`localhost` IDENTIFIED BY 'pass';
GRANT ALL PRIVILEGES ON `myappdb`.* TO `yazc`@`127.0.0.1` IDENTIFIED BY 'pass';

CREATE TABLE IF NOT EXISTS `myappdb`.`books` (
  `BookID` VARCHAR(45) NOT NULL,
  `ISBN13` VARCHAR(17) NULL,
  `ISBN10` VARCHAR(13) NULL,
  `Title` VARCHAR(45) NULL,
  `Words` double NULL,
  PRIMARY KEY (`BookID`))
ENGINE = InnoDB DEFAULT CHARSET=utf8;

CREATE TABLE IF NOT EXISTS `myappdb`.`user` (
  `UserID` VARCHAR(45) NOT NULL,
  `Name` VARCHAR(45) NULL,
  `Password` VARCHAR(128) NULL,
  `Mail` VARCHAR(45) NULL,
  `Phone` VARCHAR(45) NULL,
  PRIMARY KEY (`UserID`))
ENGINE = InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `myappdb`.`books` (`BookID`, `ISBN13`, `ISBN10`, `Title`) VALUES
(1, '9784798119410', '4798119415', '初めての人のためのLISP[増補改訂版]'),
(2, '9784320122543', '4320122542', 'Common Lisp オブジェクトシステム');
```

##３．Caveman2からMySQLへ##
###３．１．config.lisp###
`config.lisp`の中身が今ひとつ理解出来てません…
共通の設定は`:common`と`|default|`のどっちに書けばいいんだろう？
とりあえず`:common`の方に適当に書きました。後でちゃんと調べます。

```cl:config.lisp
(defconfig :common
    `(:error-log ,(merge-pathnames #P"log/common_error.log" myapp.config::*application-root*)
      :databases ((:maindb :mysql :database-name "myappdb" :username "yazc" :password "pass"))))
```

###３．２．db.lisp###
データベースに接続出来るか確認します。

```cl:
(defun test01 ()
  (with-connection (db)
    (datafly:retrieve-all
     (sxql:select :*
       (sxql:from :books)))))
```

```cl:
CL-USER> (in-package :myapp.db)
#<Package "MYAPP.DB">
DB> (connection-settings)
(:MYSQL :DATABASE-NAME "myappdb" :USERNAME "yazc" :PASSWORD "pass")
DB> (db)
To load "dbd-mysql":
  Load 1 ASDF system:
    dbd-mysql
; Loading "dbd-mysql"

#<DBD.MYSQL:<DBD-MYSQL-CONNECTION> #x302003B6EF1D>
DB> (test01)
((:BOOKID 1 :ISBN13 "9784798119410" :ISBN10 "4798119415" :TITLE "?????????LISP[?????]" :WORDS NIL) (:BOOKID 2 :ISBN13 "9784320122543" :ISBN10 "4320122542" :TITLE "Common Lisp ??????????" :WORDS NIL))
```
『??』を見ると嫌な記憶が蘇ります。
ちょっと前にも管理者不在になったPHPのソースいじってて文字コードではまりましたし…(~_~;
とりあえず深町さんの[ブログ](http://blog.8arrow.org/entry/20120323/1332516342)を参考に処理系側の文字コード確認しました。
（何か見たことある記事だなと思って，後で`ccl-init.lisp`見たら記事そのままのUTF-8の設定書いてありました。）

```cl:
DB> ccl:*default-external-format*
#<EXTERNAL-FORMAT :UTF-8/:UNIX #x3020003952FD>
DB> ccl:*default-file-character-encoding*
:UTF-8
DB> ccl:*default-socket-character-encoding*
:UTF-8
```
あれ…UTF-8だよなあ…何で文字化けするんだろ…

と
暫く悩んだ末にMacで`my.conf`いじった覚えないのを思い出しました…
LAMPだと最初に設定するので完全に忘れてました(-_-;
念のため文字コード確認。

```
mysql> show variables like 'character_set%';
+--------------------------+--------------------------------------------------------+
| Variable_name            | Value                                                  |
+--------------------------+--------------------------------------------------------+
| character_set_client     | utf8                                                   |
| character_set_connection | utf8                                                   |
| character_set_database   | latin1                                                 |
| character_set_filesystem | binary                                                 |
| character_set_results    | utf8                                                   |
| character_set_server     | latin1                                                 |
| character_set_system     | utf8                                                   |
| character_sets_dir       | /usr/local/mysql-5.6.21-osx10.8-x86_64/share/charsets/ |
+--------------------------+--------------------------------------------------------+
```
だめですね。
`$ mysql -help`で`my.cnf`の位置を確認します。

```
Default options are read from the following files in the given order:
/etc/my.cnf /etc/mysql/my.cnf /usr/local/mysql/etc/my.cnf /usr/local/mysql/bin/my.cnf ~/.my.cnf
```
`/usr/local/mysql/my.cnf`はあるので`/usr/local/mysql/bin/my.cnf`にシンボリックリンクを張ります。
`$ sudo ln -fs my.cnf bin/my.cnf`
`my.cnf``に以下の記述を追加。

```
[client]
default-character-set=utf8
[mysqld]
skip-character-set-client-handshake
character-set-server = utf8
collation-server = utf8_general_ci
[mysqldump]
default-character-set = utf8
[mysql]
default-character-set = utf8
```
もう一回文字コードの確認。

```
mysql> show variables like 'character_set%';
+--------------------------+--------------------------------------------------------+
| Variable_name            | Value                                                  |
+--------------------------+--------------------------------------------------------+
| character_set_client     | utf8                                                   |
| character_set_connection | utf8                                                   |
| character_set_database   | utf8                                                   |
| character_set_filesystem | binary                                                 |
| character_set_results    | utf8                                                   |
| character_set_server     | utf8                                                   |
| character_set_system     | utf8                                                   |
| character_sets_dir       | /usr/local/mysql-5.6.21-osx10.8-x86_64/share/charsets/ |
+--------------------------+--------------------------------------------------------+
```
これでどうだろう？

```cl:
DB> (connection-settings)
(:MYSQL :DATABASE-NAME "myappdb" :USERNAME "yazc" :PASSWORD "pass")
DB> (db)
#<DBD.MYSQL:<DBD-MYSQL-CONNECTION> #x302003C1E1DD>
DB> (test01)
((:BOOKID 1 :ISBN13 "9784798119410" :ISBN10 "4798119415" :TITLE "初めての人のためのLISP[増補改訂版]" :WORDS NIL) (:BOOKID 2 :ISBN13 "9784320122543" :ISBN10 "4320122542" :TITLE "Common Lisp オブジェクトシステム" :WORDS NIL))
```
やったー^^

##４．わかってないこと##
ユーザ認証とアクセス制御周りをCaveman2でどうするか良くわかってません。
Clackのソースとかちゃんと読めば良いのだろうと思うのですが，まだ学習が追いついてません。
（[clack.middleware.auth.basic](https://github.com/fukamachi/clack/blob/master/src/contrib/middleware/auth/basic.lisp)あたり？）

基礎知識が足らないような感じがしてきたので[この辺](https://www.ipa.go.jp/security/awareness/vendor/programmingv2/web.html)とか見ながら勉強中。

パスワードの保存にはSHA512使いたいです。日本語が入って問題ないようにもしたい。

```cl:sha512
(defun strings->sha512-hex-strings (strings)
  (ironclad:byte-array-to-hex-string
   (ironclad:digest-sequence
    :sha512
    (flexi-streams:string-to-octets strings :external-format :utf8))))
```
```cl:
DB> (strings->sha512-hex-strings "")
"cf83e1357eefb8bdf1542850d66d8007d620e4050b5715dc83f4a921d36ce9ce47d0d13c5d85f2b0ff8318d2877eec2f63b931bd47417a81a538327af927da3e"
DB> (strings->sha512-hex-strings "本日ハ晴天ナリ")
"fb1edff0663cb087d4a079ee9b4149b71e4a0965d61cdffe976158f7178c51003cc3a51ca47cf5c803409d88e4f68f16e538783e753794bd6c2b74160f239ca3"
```
こんな感じで。

上手く行くだろうか…