2012年12月16日日曜日

Haskellの遅延処理はすごいぞ

Haskellの遅延処理の素晴らしいところを1つ紹介、MySQLへ保存されているデータを取得する
以下のように、MySQLへデータが登録されているとする

mysql> SELECT * FROM test;
+----+----------+
| id | name     |
+----+----------+
|  1 | Osamu    |
|  2 | Taketomo |
|  3 | Masaru   |
+----+----------+
3 rows in set (0.00 sec)

MySQLへghciから接続しデータを取得する

ghciを起動しMySQLへ接続、コネクションの作成
cuomo@karky7 ~ $ ghci
GHCi, version 7.4.1: http://www.haskell.org/ghc/  :? for help
Loading package ghc-prim ... linking ... done.
Loading package integer-gmp ... linking ... done.
Loading package base ... linking ... done.
Prelude> :m +Database.HDBC
Prelude Database.HDBC> :m +Database.HDBC.MySQL
Prelude Database.HDBC Database.HDBC.MySQL> conn <- connectMySQL defaultMySQLConnectInfo {mysqlHost = "127.0.0.1",mysqlUser = "karky7",mysqlPassword = "",mysqlDatabase = "SAMPLEDB",mysqlPor\
t = 3306,mysqlUnixSocket = ""}
Loading package bytestring-0.9.2.1 ... linking ... done.
Loading package utf8-string-0.3.7 ... linking ... done.
...
...
Loading package HDBC-2.3.1.1 ... linking ... done.
Loading package HDBC-mysql-0.6.6.0 ... linking ... done.
Prelude Database.HDBC Database.HDBC.MySQL>

<!---<span class="deco" style="font-weight:bold;">
---!> ステートメントの作成とexecute、ここでSELECTはすべてのレコードを取得ように書かれている<!---</span>---!>
Prelude Database.HDBC Database.HDBC.MySQL> stm <- prepare conn "SELECT name FROM test"
Prelude Database.HDBC Database.HDBC.MySQL> execute stm []
0


レコードの実際の取得

Prelude Database.HDBC Database.HDBC.MySQL> row <- fetchRowMap stm


1レコード分の情報を確認

Prelude Database.HDBC Database.HDBC.MySQL> row
Just (fromList [("name",SqlByteString "Osamu")])
Prelude Database.HDBC Database.HDBC.MySQL>

以下同様に1レコードづつ取得

Prelude Database.HDBC Database.HDBC.MySQL> row <- fetchRowMap stm
Prelude Database.HDBC Database.HDBC.MySQL> row
Just (fromList [("name",SqlByteString "Taketomo")])
Prelude Database.HDBC Database.HDBC.MySQL> row <- fetchRowMap stm
Prelude Database.HDBC Database.HDBC.MySQL> row
Just (fromList [("name",SqlByteString "Masaru")])
Prelude Database.HDBC Database.HDBC.MySQL> row <- fetchRowMap stm
Prelude Database.HDBC Database.HDBC.MySQL> row
Nothing
Prelude Database.HDBC Database.HDBC.MySQL>

何がすごいって、SELECTはすべてのレコードを取得するように書いてあるのに、実際はfetchRowMapの1回の実行で1行分の情報しか取ってこないところ。これならデカいテーブルをうまい具合に処理することができる、この辺を自前で実装したりすると結構面倒だし、LIMIT入れたりとかいろいろとイケない。でも、単純な読み込みならHaskellがバッファリングを面倒を見てくれる、なんて素晴らしいことか、そう思うのは俺だけか?

0 件のコメント:

コメントを投稿