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

ぱいぱいにっき

Pythonが好きすぎるけれど、今からPerlを好きになりますにっき

sqllaというSQLビルダーを書きました。

github.com

sqllaというSQLビルダーを書きました。特徴はある程度型安全であること、リフレクションを使用していないこと、既存のクエリビルダよりある程度高速であることです。

使い方

インストールはごく簡単で、goが入っている環境で以下のコマンドを打ちます。

$ go get github.com/mackee/go-sqlla/cmd/sqlla

まず以下の様なテーブル構造を表したstructを用意します。 そして、sqllaに必要なタグを付加していきます。 また後述のgo generateで必要なコメントも足しましょう。

user.go

//go:generate sqlla

//+table: user
type User struct {
    ID uint64 `db:"user"`
    Name string `db:"name"`
}

そしてこのファイルが置かれているディレクトリ内で以下のコマンドを実行します。

$ go generate

すると、user_auto.goというファイルが生成されます。

このファイルにSQLを組み立てるメソッドが生えています。以下のように使います。

q := NewUserSQL().Select().ID(uint64(1)) // SELECT id, name FROM user WHERE id = 1
query, args, err := q.ToSql()
row := db.QueryRow(query, args...)
var id uint64
var name string
err := row.Scan(&id, &name)

ID(uint64(1))のところはuint64の型以外のものを入れるとコンパイル時にコケるようになっているので安全ですし、補完も効くため大量のテーブルや複雑なカラムがあるアプリケーションを書くときに便利です。

またLIMIT句やOrderBy句も使うことが出来ます。

基本的なCRUDについてはサポートしています。

今後やりたいこと

READMEにTHIS IS A ALPHA QUALITY RELEASE. API MAY CHANGE WITHOUT NOTICE.と書かれているようにまだexperimentalな感じでちょっと常用には耐えない感じですが、いろいろ悩んでいるのでブログを書いてみました。

今後やりたいこととしては、

  • 文字列連結に+を使っているのをやめる。コレがかなり速度的に足を引っ張っていると思われる。
  • IN演算子のサポート。以下の様なものを考えている
NewUserSQL().Select().IDIn(1,2,3,4)

ちなみに演算子周りはちょっとまだ不格好

NewUserSQL().Select().ID(uint64(100), sqlla.OpGreater)

=のときは省略できるように可変長引数でやっているので、演算子が後置になっている。sqllaの演算子を覚えなくてはならないのでどうしようかなとなっている。

  • これ書いてて思ったけれどまだint系とstringしかサポートしていなかったのでfloat系とtime.Timeとかをサポートする。あと[]byteでblobぐらいかなあ。

  • JOIN句のサポート

NewUserSQL().Select().Name("hogehoge").Join(func (r *UserJoiner) {
    rj := NewUserItemJoiner()
    r.RelationId(rj.UserId)
    r.AddColumn(rj.ItemId, rj.Amount)
})
// SELECT user.id, user.name, user_item.item_id, user_item.amount FROM user JOIN user_item ON user.id = user_item.id WHERE user.name = "hogehoge";

出来るかどうかはやってみないとわからない。

とまあそんな感じでオレオレDSL的なものを覚えないといけないので、シンプルなやつでええわ〜ってのは、id:motemenさんのsqlfが良いと思います。

motemen.hatenablog.com

また、仕事ではsquirrelを使っており、sqllaのメソッドチェインとかもsquirrelを参考にしています。

github.com

そもそもの動機はsquirrelがリフレクションを使っており、goの型がキャンセルされるので型を使うようにしたかったというのがあります。

その他

go-genddlなるものも書いておりました。仕事でこれの改造版を使っております。 上で書いたようなタグ付きstructをCREATE TABLE ~といったDDLに変換してくれる君です。最近sqlite3もサポートしており、sqllaのテストでも使っております。 github.com

改造点は複合インデックスや複合ユニークキー、複合PKが貼れたり出来るところですが、ちょっと大雑把すぎるのでもっとちゃんとしたいのにしたいところ。

と思っていたらdrone.ioで似たようなのが出たっぽいです。

github.com

みんな似たようなこと考えているんですね、、、

また、仕事ではmigrationにGitDDLを使っております。ちなPerl metacpan.org

migrationスクリプト的なものを書かずに済むので非常に便利なのですが、いかんせん起動が遅いのでGoで書けないかなと思っていたけれど、SQLパーサーだったりDiffを出すところが非常に複雑というか僕の腕ではとても書けなかったのですが、最近id:soh335さんがschemalexというのを書いていた。

github.com

まだ試してはいない。

sqllaにある程度機能が入ったら次はORM(structでは?)だと思いますのでご期待ください。