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

メンチカツ

ロースカツが好きです

【メモ】Golang/dbrでreplace intoがしたかった。

※2016/12/16 修正しました

Go言語のO/R Mapper、dbrでreplace intoがしたかった。

のですが、dbrではreplace構文はサポートしてないらしい。

それで、delete-insertで対応することにしました。

type (
    //User ユーザー
    User struct {
        ID       int
        Contacts []*Contact
    }
    //Contact ユーザーの連絡先
    Contact struct {
        MailAddress string
    }
)

//replaceUserContacts ユーザーの連絡先を削除して登録する
func (u *UserContacts) replaceUserContacts(sess *dbr.Session) error {
    //削除して
    _, err := sess.DeleteFrom("user_contacts").
        Where("user_id", u.ID).
        Exec()
    if err != nil {
        return err
    }
    //登録
    for _, c := range u.Contacts {
        _, err := sess.InsertInto("user_contacts").
            Columns("user_id", "mail_address").
            Values(u.ID, c.MailAddress).
            Exec()
        if err != nil {
            return err
        }
    }

    return nil
}

よし超シンプルだぜと思って実行したら、なんとぜんぜん登録されない。

確認したら、deleteの返り値errに

dbr: wrong placeholder count

って入ってる。

処理してるところ

github.com

を確認すると、プレースホルダー( where id = ? に当たる部分)と

バインドする値(u.ID)の数が不一致だぞと言っている。なんでや。

なので、

//replaceUserContacts ユーザーの連絡先を削除して登録する
func (u *UserContacts) replaceUserContacts(sess *dbr.Session) error {
    //削除して
    _, err := sess.DeleteBySql(`delete from user_contacts where user_id = ` + strconv.Itoa(u.ID)).
        Exec()
    if err != nil {
        return err
    }
    //登録
    for _, c := range u.Contacts {
        _, err := sess.InsertInto("user_contacts").
            Columns("user_id", "mail_address").
            Values(u.ID, c.MailAddress).
            Exec()
        if err != nil {
            return err
        }
    }

    return nil
}

と、変数バインドしないようにしたところ、エラーなく動作するようになりました。