読者です 読者をやめる 読者になる 読者になる

ささいなことですが。

Windowsアプリテスト自動化ライブラリFriendly開発者の日記です。

LambdicSql -主要DBゆるふわ対応-

LambdicSql_α0.0.63をリリースしました。β版間近です!
www.nuget.org

マルチDB対応

なんと主要6DBで動作確認しています。Surfaceに全部インストールしましたが、意外と入るものですね。(SQLiteはインストール不要)

DataBase type 動作確認
SQL Server
SQLite
PostgreSQL
Oracle
MySQL
DB2

とは言え、同じ書き方でOKなわけではないです。

この辺がゆるふわ。LambdicSqlは基本はそのままSQLのテキストになります。つまり、普通にSQL書く時と同じように使える句や関数だけ使うという方針です。

public void TestWindow()
{
    //SQLiteとMySqlはWindow関数使えないよ。
    if (_connection.GetType().FullName == "System.Data.SQLite.SQLiteConnection") return;
    if (_connection.GetType().FullName == "MySql.Data.MySqlClient.MySqlConnection") return;

    //make sql.
    var query = Db<DB>.Sql(db =>
        Select(new SelectData()
        {
            Avg = Window.Avg(db.tbl_remuneration.money).
                    Over<decimal>(new PartitionBy(db.tbl_staff.name, db.tbl_remuneration.payment_date),
                        new OrderBy(new Asc(db.tbl_remuneration.money), new Desc(db.tbl_remuneration.payment_date)),
                        new Rows(1, 5)),
            PaymentDate = db.tbl_remuneration.payment_date,
            Money = db.tbl_remuneration.money,
        }).
        From(db.tbl_remuneration).
        Join(db.tbl_staff, db.tbl_remuneration.staff_id == db.tbl_staff.id));

    //to string and params.
    var info = query.Build(_connection.GetType());
    Debug.Print(info.SqlText);

    //dapper
    var datas = _connection.Query<SelectData>(info.SqlText, info.Params).ToList();
}

オプションで、以下を切り替えれるようにしました。

じゃあ、何がマルチDB対応なんだよってことなのですが、以下の二つだけオプションで切り替えれるようにしています。こればっかりは書き分けられないので・・・。

  • 文字列の+演算
  • パラメータのプレフィックス
[TestMethod]
public void Test()
{
    var query = Db<DB>.Sql(db =>
        Select(new
        {
            Name = db.tbl_staff.name + "★",
            Money = db.tbl_remuneration.money,
        }).
        From(db.tbl_remuneration).
            Join(db.tbl_staff, db.tbl_staff.id == db.tbl_remuneration.staff_id).
        Where(1000000 < db.tbl_remuneration.money));

    //文字列化するときにオプションを指定する
    var info = query.Build(new SqlConvertOption() { ParameterPrefix = ":", StringAddOperator = "||" });
    Debug.Print(info.SqlText);
}
SELECT
	/*文字列結合の演算子に||を指定*/
	(tbl_staff.name) || (:p_0) AS Name,
	tbl_remuneration.money AS Money
FROM tbl_remuneration
	JOIN tbl_staff ON (tbl_staff.id) = (tbl_remuneration.staff_id)
/*オラクルは@使えない*/
WHERE (:p_1) < (tbl_remuneration.money)

なんで、こんなとこに差だすかなー。オラクルで@使ったらダメとか、わからなくて結構悩みました。

DataBase type 文字列結合 パラメータプレフィックス
SQL Server + @
SQLite || @
PostgreSQL || @
Oracle || :
MySQL + @
DB2 || @

これを毎回指定するのは面倒なんで、コネクション(SqlConnectionとか)のタイプを渡すと最適なオプションを選択するようにしています。

//コネクションタイプを渡すと、最適なオプションを選択します。
var info = query.ToSqlInfo(connection.GetType());

同一の記法でSQLテキストをカスタマイズする方法も提供しています。

長くなるので端折りますが、ToSqlInfoの第三引数にテキスト出力をカスタマイズするインターフェイスを渡せるようにしています。どうしてもやりたい人はこちらでできるように。また句や関数を自分で増やせる手段も提供しています。(拡張オレオレ句も作れる)

//第三引数でカスタマイズインターフェイスを渡せる仕様にしてます。
public static SqlInfo ToSqlInfo(this ISqlExpression exp, SqlConvertOption option, ISqlSyntaxCustomizer customizer)