2013-12-08 7 views
5

goの組み込みデータベース/ sqlパッケージで名前付きパラメータを使用するためのパターンを理解しようとしています。私はoracleドライバを調べましたが、Cライブラリのラッパーのように思えます。人々はこれを優雅な方法で解決しましたか?これまでのところ、私はちょうど{0}{1}をユニットテストのパラメータとして入力することで問題を回避しましたが、通常はmap[string]interface{}などのように通常使うことができればいいと思います。誰でもアイデアやイディオムのような実装がありますか?参考のため、ここではテストdatabase/sqlとdatabase/sql/driverの名前付きパラメータ

されています:

db := testConn() 
stmt, err := db.Prepare("return {0} as int1, {1} as int2") 
if err != nil { 
    t.Fatal(err) 
} 
rows, err := stmt.Query(123, 456) 
if err != nil { 
    t.Fatal(err) 
} 
rows.Next() 

var test int 
var test2 int 
err = rows.Scan(&test, &test2) 
if err != nil { 
    t.Fatal(err) 
} 
if test != 123 { 
    t.Fatal("test != 123;", test) 
} 
if test2 != 456 { 
    t.Fatal("test2 != 456;", test2) 
} 

そして私はQueryでやっては以下のとおりです。

func (stmt *cypherStmt) Query(args []driver.Value) (driver.Rows, error) { 
    cyphReq := cypherRequest{ 
     Query: stmt.query, 
    } 
    if len(args) > 0 { 
     cyphReq.Params = make(map[string]interface{}) 
    } 
    for idx, e := range args { 
     cyphReq.Params[strconv.Itoa(idx)] = e 
    } 
... 
+0

既存の回答は、あなたがクライアントを書いていると仮定しているようですが、ドライバを書いているように見えます。そうですか? – andybalholm

+0

はい:https://github.com/wfreeman/cq –

+0

データベース/ sqlパッケージは、名前付きパラメータではなく、位置パラメータを中心に構築されています。ですから、名前付きパラメータを使用するための回避策は、定義によってはほぼ独立したものになります。 – andybalholm

答えて

1

[]byteとしてそれをシリアル化するためにdriver.Valuer{}を実装map[string]interface{}タイプを作成することが可能であろうと私は個人的にあなたが構造体またはマップからのクエリをバインドすることを可能にするgorpを使用しますそれをドライバに戻してください。

しかし、これは非効率的で一元的です。とにかくあなたのドライバは非標準的な方法で使用されるので、おそらくデータベース/ SQLを忘れて、完全にカスタムのインターフェースを持つパッケージを書くほうがよいでしょう。

8

私は SQLXと呼ばれるデータベース/ SQLの上にラッパーを使用していますhttps://github.com/jmoiron/sqlx ここで彼がどのようにしたのかを確認することができます。

dude := Person{ 
    FirstName:"Jason", 
    LastName:"Moiron", 
    Email:"[email protected]" 
} 
_, err = db.NamedExec(`INSERT INTO person (first_name,last_name,email) VALUES (:first,:last,:email)`, dude) 
+0

私の質問は逆のようなものです - どのようにマップとしてパラメータを入れるか。 –

+0

タプルの挿入方法に関する質問を編集しました – Goranek

+0

クール - ネイティブのデータベース/ SQLパッケージを使用した方法を誰かに見せたいと思っています。 –

4

タプルを挿入する方法でタプル

type Person struct { 
    FirstName string `db:"first_name"` 
    LastName string `db:"last_name"` 
    Email  string 
} 
jason = Person{} 
err = db.Get(&jason, "SELECT * FROM person WHERE first_name=$1", "Jason") 
fmt.Printf("%#v\n", jason) 
// Person{FirstName:"Jason", LastName:"Moiron", Email:"[email protected]"} 

例に選択する方法について

例は、私の知る限りでは、何のドライバがネイティブに名前付きパラメータのために提供されません。

_, err = dbm.Select(&users, 
    "select * from PersistentUser where mykey = :Key", 
    map[string]interface{}{ 
     "Key": 43, 
    } 
) 

または

_, err = dbm.Select(&users, 
    "select * from PersistentUser where mykey = :Key", 
    User{Key: 43}, 
) 
+0

言い訳ありがとう - それはかなり滑らかです。私は、ネイティブのデータベース/ SQLパッケージの方法を望んでいます。 –

+3

ネイティブデータベース/ sqlでは実行できません。 – Goranek