ScalaQuery の作成者として、Stilgar の説明に追加することはあまりありません。Scala に欠けている LINQ の部分は、実際には式ツリーです。これが、ScalaQuery がエンティティの基本型ではなく、列型とテーブル型ですべての計算を実行する理由です。
テーブルをその列のプロジェクション (タプル) を持つ Table オブジェクトとして宣言します。次に例を示します。
class User extends Table[(Int, String)] {
def id = column[Int]("id", O.PrimaryKey, O.AutoInc)
def name = column[String]("name")
def * = id ~ name
}
User.id と User.name は、それぞれ Column[Int] と Column[String] 型になりました。すべての計算は Query モナドで実行されます (これは、データベース クエリから作成する必要のある SQL ステートメントよりも自然なデータベース クエリの表現です)。次のクエリを実行します。
val q = for(u <- User if u.id < 5) yield u.name
いくつかの暗黙的な変換と脱糖の後、これは次のように変換されます。
val q:Query[String] =
Query[User.type](User).filter(u => u.id < ConstColumn[Int](5)).map(u => u.name)
filter メソッドと map メソッドは、クエリを作成するために引数を式ツリーとして検査する必要はなく、実行するだけです。型からわかるように、表面的には「u.id:Int < 5:Int」に見えますが、実は「u.id:Column[Int] < u.id:Column[Int]」です。この式を実行すると、Operator.Relational("<", NamedColumn("user", "id"), ConstColumn(5)) のようなクエリ AST が生成されます。同様に、Query モナドの「filter」および「map」メソッドは、実際にはフィルタリングとマッピングを実行しませんが、代わりにこれらの操作を記述する AST を構築します。
次に、QueryBuilder はこの AST を使用して、データベースの実際の SQL ステートメントを (DBMS 固有の構文で) 構築します。
ScalaQLでは、コンパイラ プラグインを使用して式ツリーを直接操作し、データベース クエリで許可されている言語サブセットのみが含まれていることを確認し、クエリを静的に構築する代替アプローチが採用されています。