Ch.11 SML#の拡張機能:SQLのシームレスな統合

§ 11.2. SML#へのSQL式の導入

SQLのSELECT文はFROM節に記述されたテーブルの集合から 一つのテーブルを作成する式です. SQL言語は,ある特定のデータベースへの接続の下でSQL式を評価する機 能を提供しますが,これをデータベース接続を受け取りテーブルを返す関数式に 一般化すれば,関数型言語の型システムに統合することができます. テーブルはレコードの構造をしているため,多相レコードの型付けがほ ぼそのまま使用できます. しかし我々SML#チームの研究によって,このデータベースを受 け取る関数の型付けには,多相レコード以外にさらに型理論的な機構が必要であ ることが示されています[13]. そこで,データベース接続を受け取る関数には特別の文法を用意します. SML#では,前節のSQL式の例は,以下のような式で表現されます.

_sql db => select #P.name as name, #P.age as age
      from #db.Persons as P
      where SQL.>(#P.salary, 10000)

_sql db => ...は,データベース接続を変数dbとして受 け取る問い合わせ関数であることを示しています. SQL.>はデータベース問い合わせを実現するライブラリモジュー ルSQLの中に定義されたSQLの値のための大小比較プリミティブです. #P.NameはタプルPNameフィールドの取り出し演算, #db.PersonsはデータベースdbからのPersonsテーブル取り 出し演算です. これらは,SML#式では#Name P#Persons dbと書か れるレコードからのフィールド取り出し式に相当します. _sql x => expr式では,SQLの文法に類似の構文を採用して います. この式に対して以下の型が推論されます.

val it = _
     : ['a#{Persons: 'b},
    'b#{age: 'f, name: 'd, Salary: int},
    'c,
    'd::{int, word, char, string, real, 'e option},
    'e::{int, word, char, bool, string, real},
    'f::{int, word, char, string, real, 'g option},
    'g::{int, word, char, bool, string, real}.
      ('a, 'c) SMLSharp_SQL_Prim.db
        -> {age: 'd, name: 'f} SMLSharp_SQL_Prim.query]

この型は,'aの構造を持つデータベース接続の型('a, 'c) dbから{age: 'd, name: 'f} query型への関数型です. 'aは,この問い合わせに必要なデータベース構造を表すレコード 多相型です. 型変数'cは,データベース接続の一貫性を保証するために導入さ れたものです. このようにSQL式は多相型を持つため,MLプログラミングの原理「式は 型が正しい限り自由に組み合わせることができる」に従って,第一級のデータ としてSML#の他の機能とともに自由にプログラムすることができます.