node-mysqlをざくっと使う

MySQLにNode.jsからつないでみた。データベースtestにユーザーnodejs、パスワードhogeでつなぎます。MySQLはMacにコミュニティ版をインスコしてlocalhostに立ててます。DDLは手で書くの面倒なので、Sequel Pro(http://www.sequelpro.com/) を見つけて利用。これはProという名前なのにドネーションウェアMySQL管理のGUIフロントエンドです。すばらしい。

MySQL接続ドライバは、npmで一発インストール。

$ npm install mysql

識別はmysqlなのになぜかモノの名前はnode-mysql。require文字列も'mysql'。

//唯一のJSファイル。これだけで動くのはNode.jsならでは。すばらしい

var mysql = require('mysql');

var connStr = 'mysql://nodejs:hoge@localhost/test';

var queryStr = 'select product, price from orders where delivery_date > ?';

var connection = mysql.createConnection(connStr + '?debug=true');

try{

    connection.query(queryStr, [ new Date() ], function(err, rows) {

        if(err) {

            console.log(err);

        } else {

            for(i in rows) {

                console.log(i + ': ' + rows[i].product + ' (' + rows[i].price + '円)');

            }

        }

    });

} finally { connection.end(); } 

 ものすごくJDBCライクですね。接続文字列でConnectionを取ってますが、接続文字列は結局一度JSONにパースされるので以下の書き方がスタンダードみたい。

var connection = mysql.createConnection({

    host: 'localhost',

    database: 'test',

    user: 'nodejs',

    password: 'hoge',

    debug: true

});

debugフラグをtrueにすると面白い。MySQLとNode.jsアプリの間で送受信する内容がJSONで表現されてコンソールにダンプされます。クエリ文字列に?プレースホルダを用いることも可能。これは日付型とかを文字列にフォーマットしたり、文字列をブレースで囲ったりするようなクエリ組み立てが楽になるのと、SQLインジェクションを避けるためのクリーニングもドライバでやってくれる(via 添付ドキュメント)というのが便利。

結果はコールバック関数で取りますが、DB例外が発生してなければerrはnull、DB例外が発生すると結果セットたるrowsがundefinedです。結果セットはJSONままで、下記の感じ(上記でforループ回す変わりに、console.log(rows);でこの結果)。

[ { product: '特のりタル弁当', price: 370 },

  { product: 'カルビ焼き肉弁当', price: 580 },

  { product: '回鍋肉と油淋鶏弁当', price: 490 } ]

 AJAXのサーバとしては結果セットをそのままレスポンスに書き出せばよいってことで楽チンでしょう。最後にconnection.end();を呼び出して終了。これを呼ばないと処理が終わっても接続を維持するので、JavaScriptでこういう書き方をすべきなのかはよくわかりませんが、確実に接続を閉じるようにtry〜finallyで囲ってみました。

ちょっと引っかかってるのは、JSの仕様なのかMySQLなのか、はたまたnode-mysqlか。ミリ秒が無い。console.log(new Date()); をすると、結果が「Sun Sep 08 2013 20:21:33 GMT+0900 (JST)」。node-mysqlのドキュメントも...

* Date objects are converted to 'YYYY-mm-dd HH:ii:ss' strings

 ...ですって。私の書きグセですが、DBにミリ秒でアクセス時刻を書き込むような作りをしてたのですが、まあなんか考えるかな。