title | emoji | type | topics | published | |||
---|---|---|---|---|---|---|---|
SQLBuilderの仕様を考える INSERT仕様検討編 |
🖋 |
tech |
|
false |
GolangのSQLBuilerを作ってみたくて、仕様を考える。 今回はINSERT文の仕様を考えるが、SELECT+INSERTまで考えると複雑になるので 一旦保留にする
ここではusersというTableに対応したUserというTableモデル構造体がある場合とする。 宣言としては、
CREATE TABLE users (
id int,
name varchar(10)
)
CREATE TABLE tokens (
id int,
user_id int REFERENCES users.id,
token varchar(10)
)
を想定する
パッケージ名は仮でpkとして
pk.Insert().Into(pk.Table("users")).Value(1, "test")
// INSERT INTO users VALUES(1, 'test')
とすることを考えている。
カラムを限定する場合は
pk.Insert("id").Into(pk.Table("users")).Value(1)
// INSERT INTO users(id) VALUES(1)
バルクインサートのためにValuesを何で受け取るべきかを考える。 現在、モデルを定義していないので構造体では難しい問題がある。 またSliceで受け取る場合もデータ型の問題でユーザに難しい作成を強いることになる。
Valueメソッドを連結するパターンとして
pk.Insert("id").Into(pk.Table("users")).Value(1).Value(2)
// INSERT INTO users(id) VALUES(1), (2)
をあげられる。ユーザにfor文を強制してしまうが手法の1つしてはありだと考えているので 一応採用する。
pk.TableのSliceで受け取るパターン 手間は必要になるが、案1との違いが重要になる。
まずはテーブルに対してのカラム宣言
user := pk.Table("users")
user.SetValue("id", 1)
user.SetValue("name", "test")
ここから
pk.Insert().Into(pk.Table("users")).Value(user)
// INSERT INTO users VALUES(1, 'name')
といった感じ・・・・ 使わない気がするな。 なぜなら、サービスでの利用を考えたときになにかしら構造体でもっていることが一般的。 これはその構造体からの変換処理を求めているので、 こんな面倒なことをせずに案1を使えばいいだけな感覚。 それだったら構造体にタグ設定したほうが扱いが簡単なので、 案2に関しては現時点では保留とする。モデルの対応自体を保留にしている状況でここで定義してしまうと全体適応時に弊害になる懸念があるため。