8.0.22のprepared statementの調査続き1
↑についてリノベ8.0.22で話した。
このとき、MTG中にそれぞれが試してみるとgoだと動く、rubyだと応答がなくなるという話をしていた。
tmtmさんがRuby, Cで追実験した結果をブログにしてくれていたので、僕もgoの結果を書いておこうと思う。
結果を先に書くと、dockerで公式イメージの8.0.22に対して実行するとドキュメント通りsortはされないが結果は帰ってきた。 goのdriverの実装を見てからブログを書こうと思って放置していたが、ここまでの結果だけをとりあえず書きます。
go実験コード
// main.go package main import ( "database/sql" "fmt" _ "github.com/go-sql-driver/mysql" "log" ) type Tbl struct { id int64 c1 int64 } func main() { // db, err := sql.Open("mysql", "root:root@tcp(127.0.0.1:33061)/sample") db, err := sql.Open("mysql", "root:root@tcp(127.0.0.1:33068)/sample") if err != nil { log.Fatal("db error.") fmt.Println(err.Error()) } defer db.Close() q := "select id,c1 from t1 order by ?" stmt, err := db.Prepare(q) if err != nil { log.Fatal("prepare error.") fmt.Println(err.Error()) } defer stmt.Close() rows, err := stmt.Query(2) if err != nil { log.Fatal("prepare exec error.") fmt.Println(err.Error()) } // rows, err := db.Query("select id,c1 from t1 order by ?", 2) // if err != nil { // log.Fatal(err) // } for rows.Next() { t := Tbl{} if err := rows.Scan(&t.id, &t.c1); err != nil { log.Fatal(err) } fmt.Println(t) } }
ここでは明示的にdb.Prepare()を使ったが、sql.Open()のオプションで ?interpolateParams=true
を指定しないとdefaultではdb.Query()も内部的にprepared statementとして実行される。
cf: https://github.com/go-sql-driver/mysql#interpolateparams
MTG中はコメントアウトしてる部分の方で実行してwiresharkでもprepared statementになっていることを確認した。
結果
どちらも手元のdockerで確認(go version go1.15.2 darwin/amd64
)
- 8.0.21
% go run main.go {5 12} {3 25} {1 62} {4 77} {2 82}
- 8.0.22
% go run main.go {1 85} {2 41} {3 52} {4 37} {5 30}
8.0.22ではorder by
は効いていないが結果は返ってくる