Gorpを使っていて以下のようなqueryを実行したい時がある。
select * from table where id in (1, 2, 4, 8);
"1,2,4,8"は動的に変えたいのでプレースホルダーにしたい。
select * from table where id in ($1, $2, $3, $4);
今回指定したidは4つだったけど、いつもそうとは限らないので渡す数も動的にしたい。
select * from table where id in ($1);
このqueryで以下のように実行してみるとエラーになる。
query := "select * from table where id in ($1);" dbmap := &gorp.DbMap{ Db: db, // コネクション Dialect: gorp.PostgresDialect{}, } _, err := dbmap.Select(mapper, query, []int{1,2,4,8}) // エラーが出る // sql: converting argument $1 type: unsupported type []int, a slice of int
方法:ExpandSliceArgsオプションを有効化してmap[string]interface{}型で値を渡す
以下のように書くと意図通りの挙動になる。
query := "select * from table where id in (:ids);" dbmap := &gorp.DbMap{ Db: db, Dialect: gorp.PostgresDialect{}, ExpandSliceArgs: true, //スライス引数展開オプションを有効化する } _, err := dbmap.Select(mapper, query, map[string]interface{}{"ids": []int{1,2,4,8}})
内部的には、query文字列を
select * from table where id in (:ids0, :ids1, :ids2, :ids3)
と展開して処理してくれている。
gorpのコードを読んでいてこの機能を知った。
この機能を知る前は、where in () の中を予めwhere in ($1, $2, $3, $4) となるように文字列をいじり、argsも[]interface{}型に変換してからdbMap.Select()に渡していたがめんどくさかった。。