mysql.exeでUTF-8を使う

拙著『Webアプリケーション』では、Windowsのコマンドプロンプトでmysql.exeを対話的に使うときは、「mysql -uユーザ名 -pパスワード --default-character-set=cp932」のようにして、文字コードをcp932にすることを推奨しています。理由は2つあります。

  1. コマンドプロンプトでUTF-8を利用するのが面倒(特にWindows XPで)
  2. MySQL 5.5以前のmysql.exeにはUTF-8に関するバグがある

第1の問題は完全には解決されていません。日本語環境のコマンドプロンプトのデフォルトの文字コードはcp932ですが、プロパティでフォントをMS ゴシックに変更してから「chcp 65001」とすると、UTF-8で日本語を利用できます(変更してからプロパティを開いてはいけません)。面倒です。Windows XPではさらに作業が必要だったのですが、XP自体がそろそろ終わりなのでまあいいでしょう。(MS ゴシック以外のフォントを使いたい場合は先に一手間必要です。「コマンドプロンプト フォント 変更」などで探してください。)

第2の問題はMySQL 5.6で解決されました(XAMPPなら1.8.3以降)。

というわけで、前準備(フォントの変更)がバッドノウハウではありますが、p.100の脚註11とp.188の「WindowsのコマンドプロンプトではCP932(Windows-31J)しか使えない」という記述は昔話になりました。

コマンドプロンプトでUTF-8を使っている様子を以下に掲載します(設定ファイルはデフォルトのまま、「--default-character-set=utf8」や「SET NAMES utf8;」は無くても大丈夫です)。

C:\>chcp 65001
Active code page: 65001

C:\>mysql -uroot test
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 77
Server version: 5.6.14 MySQL Community Server (GPL)

Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

mysql> SHOW VARIABLES LIKE 'char%';
+--------------------------+--------------------------------+
| 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       | C:\xampp\mysql\share\charsets\ |
+--------------------------+--------------------------------+
8 rows in set (0.00 sec)

mysql> CREATE TABLE t (name TEXT) CHARSET=utf8;
Query OK, 0 rows affected (0.08 sec)

mysql> INSERT t(name) VALUES ('안녕하세요');
Query OK, 1 row affected (0.01 sec)

mysql> SELECT * FROM t;
+-----------------+
| name            |
+-----------------+
| 안녕하세요      |
+-----------------+
1 row in set (0.00 sec)

きれいに表示されないという問題が残っていますね。

ソーシャルコンピューティング入門

4781913210チューリングマシンで表現できるものは原理的には計算可能である。しかし、その計算が現実的かどうかは別問題だ。たとえば社会を理解したいなら、社会全体をチューリングマシンで表現するのではなく、実際に計算できるようなモデル化が必要である。そのモデルは、「インプットとアウトプット」という伝統的な形式にはおそらくならない。増永良文先生の『ソーシャルコンピューティング入門』は、このようなアカデミックな視点から、今日のウェブ社会を理解しようとしている。

集合知の具体的な手法なども紹介して、アカデミックであると同時に実践的でもあるようにしているのはさすが。

(参考文献リストあり。索引あり。)

『Webアプリケーション構築入門』の郵便番号検索システムをAppFog上で動かす方法

ウェブアプリ構築の入門書である拙著『Webアプリケーション構築入門 第2版』のゴールは、Google Mapsを活用する郵便番号検索システムです。サーバ・サイドのプログラミング言語はJavaとPHPのうち、好きな方を選んで読み進められるようになっています。

ウェブアプリを構築できるようになると、こんどはそれを公開したくなるわけですが、本書の想定読者には学生も入っているので、「まずサーバを用意して・・・」のようなコストのかかる方法ではなく、基本無料の公開方法が必要です。

Java版をHerokuで公開する方法と、PHP版をPHP Fogで公開する方法を以前紹介したのですが、PHP Fogが今年いっぱいでサービスを終了し、AppFogに移行するらしいので、それにあわせてAppFogを試します。

PHP Fogでは、無料では機能が不十分なMySQLを避けてSQLiteを使いましたが、AppFogのMySQLは容量が100MBあるので、郵便番号検索のためには十分です(逆にSQLiteは使えなくなりました。使えれば、移植作業は楽だったのですが)。(参考:AppFog Pricing

作業は以下の通りです。(Ubuntu 12.10 Desktopで動作を確認しました。)

1. AppFogのアカウントを作る。

2. コマンドラインツールをインストールする。(参考:AF Command Line Tool)

sudo apt-get install ruby
sudo gem install af

3. ログインする。

af login

4. アプリを作成し、そこにMySQLサービスを追加、バインドする(ここ、かなり説明を端折っています)。

af bind-service {サービス名} {アプリ名}

5. データベースを準備する。

sudo apt-get install ruby-dev g++ mysql-client libssl-dev
sudo gem install caldecott
sudo gem install eventmachine -- --with-openssl-dir=/usr/lib/ssl
af tunnel

指示に従うとmysqlコマンドで接続できるようになります。あらかじめmysqldumpでデータベースをバックアップしておいて、以下のようなコマンドで復元します。

mysql> source {ファイル名}

6. ソースコードをアップロードする。

cd {コードのあるディレクトリ}
af update {アプリ名}

AppFogの流儀にあわせて、MySQLに接続する部分のコードを次のように書き換えておく必要があります(PHPのバージョンが比較的新しいので、接続時に文字コードを設定できます)。(参考:AppFog Docs MySQL)

//データベースに接続
$services_json = json_decode(getenv("VCAP_SERVICES"),true);
$mysql_config = $services_json["mysql-5.1"][0]["credentials"];
$user = $mysql_config["username"];
$pass = $mysql_config["password"];
$host = $mysql_config["hostname"];
$port = $mysql_config["port"];
$dbname = $mysql_config["name"];
$db = new PDO("mysql:host=$host;port=$port;dbname=$dbname;charset=utf8", $user, $pass);

実行結果は下のようになります。

『Webアプリケーション構築入門』の郵便番号検索システムをPHP Fog上で動かす方法

追記:PHP Fogは2012年12月にサービスを終了するそうなので、後継サービスであるAppFogを試しました。→『Webアプリケーション構築入門』の郵便番号検索システムをAppFog上で動かす方法

ウェブアプリ構築の入門書である拙著『Webアプリケーション構築入門 第2版』のゴールは、Google Mapsを活用する郵便番号検索システムです。サーバ・サイドのプログラミング言語はJavaとPHPのうち、好きな方を選んで読み進められるようになっています。

作成したウェブアプリを公開する方法は人によってさまざまでしょうが、PaaSの無料プランを使うのは魅力的な選択肢です。

Javaで作成したウェブアプリをHerokuというPaaSの上で動かす方法を以前紹介しました。(参照:『Webアプリケーション構築入門』のデータベースアプリケーションをHeroku上で動かす方法

ここでは、PHPで作成したウェブアプリをPHP FogというPaaSの上で動かす方法を紹介します。

手順は次のようになります(1と2は、PHP Fogを使い始めるときに1回だけやればOKです)。詳しくは、Jumpstartsあたりを参照してください。

  1. PHP Fogのアカウントを作る
  2. SSH鍵ファイルを登録する
  3. アプリを作る
  4. データベースを作る
  5. git clone URL
  6. アプリを作る
  7. git add .
  8. git commit -m 'コメント'
  9. git push

PHP FogではMySQLが使えますが、そのアクセス方法は、拙著で説明したのとは少し違っています。データベースへの接続情報は、環境変数に格納されているので、それを参照しながら接続します。参考までに、データベースに接続するためのコードを書くと、次のようになります。p. 149に掲載されているコードと比較してください。

//データベースに接続
$server = getenv('MYSQL_DB_HOST');
$username = getenv('MYSQL_USERNAME');
$password = getenv('MYSQL_PASSWORD');
$dbname=getenv('MYSQL_DB_NAME');

$db = new PDO("mysql:host=$server;dbname=$dbname", $username, $password,
                array(PDO::MYSQL_ATTR_INIT_COMMAND => 'SET NAMES utf8'));

しかし、ここではこのコードは使いません。郵便番号データベースを構築するのが面倒だからです。拙著で紹介したように、テーブルを作成して郵便番号データのCSVファイルをインポートすれば郵便番号データベースを構築できるのですが、郵便番号データベースのためのCSVファイルは比較的大きいため、phpMyAdminでインポートしようとするとタイムアウトしてしまうのです。無料で利用できるデータベースサイズが5MBというのもいまいちです。Herokuのときもそうでしたが、無料の範囲内で遊ぼうとすると、データベース周りがいろいろ面倒です。

タイムアウトしてしまうという問題は、「split -C 500K /tmp/zip.csv」などとして分割し、「for f in x*; do mv $f $f.csv; done」として拡張子.csvを付けて、一つずつインポートすれば回避できますが、とても面倒です(Railsに行くのはここではがまんしましょう)。

こんなところで苦労するのはいやなので、Herokuの場合と同様に、SQLiteを組み込んで使うことにします。

ローカルでの実験のために、PHPからSQLiteを使えるようにしておきましょう。

sudo apt-get install php5-sqlite
sudo service apache2 restart

データベースファイル(mydb.sqlite)の作り方はHerokuの場合と同じなので省略します(完成したファイルはここにあります)。このファイルを、zips.phpと同じディレクトリに保存します(接続時にパスを指定するなら、別のディレクトリでもかまいません)。

zips.php内のデータベースに接続する部分を次のように修正します。

//データベースに接続
$db = new PDO('sqlite:mydb.sqlite');

Ajaxによって1文字入力するごとに検索結果を更新するようにしたものは、拙著の中では割愛しましたが(Java版とほとんど同じため)、サポートサイトでは掲載しているので参考にしてください。

実行結果は下のようになります。

SQLite for Java on Heroku

拙著『Webアプリケーション構築入門 第2版』は、ウェブアプリ構築の入門書です。サーバ・サイドプログラムは、JavaとPHPで作成しており、読者は自分の好きな方を選んで読み進められるようになっています。

PHPで作ったウェブアプリはレンタルサーバとかで簡単に公開できるけど、Javaで作ったウェブアプリはちょっと面倒でした。

しかし、HerokuならJavaが動くので、これを使えば簡単です。このことについて、かつて書きました。

しかし、確かにJavaは動きますが、データベース管理システムは拙著で採用したMySQLではなくPostgreSQLなので、PostgreSQLへの対応が必要です。このことについて、かつて書きました。

しかし、拙著のサンプルアプリである郵便番号検索システムのためのデータベースは比較的大きく、ウェブアプリをPostgreSQLに対応させただけでは、データのインポートが面倒で使えません。この問題は、Postgres dev planという無料のアドオンで解決するのが簡単です。このことについて、かつて書きました。

しかし、これだけ書いた後で、「Postgres dev planでは、1つのテーブルに1万行までしか入れられないようにする予定です」というアナウンスがありました。郵便番号データベースには、14万行以上のデータがあるので、Postgres dev planではダメになるわけです。

月9ドルのBasic planに移行すれば問題は解決するのですが、そんなものを学生に勧められるわけもなく、もう面倒くさいのでSQLiteを組み込んで使うことにします。さらばPostgreSQL。

必要な作業は3つです。

  1. データベースファイルの作成
  2. SQLiteのためのライブラリの導入
  3. データベースへの接続方法の修正

データベースファイルの作成

FirefoxのアドオンであるSQLite Managerを使うのが簡単です。

  • アドオンをインストールする
  • ツール→SQLite Manager
  • pom.xmlがあるのと同じディレクトリにmydb.sqliteを作成する
  • デーブルを作る
  • 郵便番号データをインポートする

テーブルは次のようなSQL文を実行して作成します。

CREATE TABLE zip (
  code CHAR(7) NOT NULL,
  address1 VARCHAR(10) DEFAULT '' NOT NULL,
  address2 TEXT NOT NULL,
  address3 TEXT NOT NULL,
  address4 TEXT NOT NULL,
  office TEXT NOT NULL
);

CREATE INDEX code_idx ON zip (code)

データのインポートには、以前作成した/tmp/zip.csvを使えばいいでしょう。

SQLiteのためのライブラリの導入

pom.xmlに、次のような要素を追記します。

<dependency>
  <groupId>org.xerial</groupId>
  <artifactId>sqlite-jdbc</artifactId>
  <version>3.7.2</version>
</dependency>

データベースへの接続方法の修正

zips.jspを次のように修正します。

//データベースに接続
Class.forName("org.sqlite.JDBC");
Connection conn=DriverManager.getConnection("jdbc:sqlite:mydb.sqlite");

あとは『Webアプリケーション構築入門』のウェブアプリをHeroku上で動かす方法と同じです。


動作例