diff --git a/.gitignore b/.gitignore index ba8e0cb3a..08cc1b1b8 100644 --- a/.gitignore +++ b/.gitignore @@ -6,3 +6,28 @@ Icon? ehthumbs.db Thumbs.db + +# Compiled Object files, Static and Dynamic libs (Shared Objects) +*.o +*.a +*.so + +# Folders +_obj +_test + +# Architecture specific extensions/prefixes +*.[568vq] +[568vq].out + +*.cgo1.go +*.cgo2.c +_cgo_defun.c +_cgo_gotypes.go +_cgo_export.* + +_testmain.go + +*.exe +*.test +*.prof \ No newline at end of file diff --git a/AUTHORS b/AUTHORS index 4b65bf363..e6327792c 100644 --- a/AUTHORS +++ b/AUTHORS @@ -34,6 +34,7 @@ Runrioter Wung Soroush Pour Xiaobing Jiang Xiuming Chen +Kevin Geng # Organizations diff --git a/packets.go b/packets.go index 290a3887a..f29592c96 100644 --- a/packets.go +++ b/packets.go @@ -214,6 +214,8 @@ func (mc *mysqlConn) writeAuthPacket(cipher []byte) error { clientLongPassword | clientTransactions | clientLocalFiles | + clientMultiStatements | + clientMultiResults | mc.flags&clientLongFlag if mc.cfg.clientFoundRows { @@ -470,6 +472,10 @@ func (mc *mysqlConn) handleErrorPacket(data []byte) error { } } +func readStatus(b []byte) statusFlag { + return statusFlag(b[0]) | statusFlag(b[1])<<8 +} + // Ok Packet // http://dev.mysql.com/doc/internals/en/generic-response-packets.html#packet-OK_Packet func (mc *mysqlConn) handleOkPacket(data []byte) error { @@ -484,7 +490,8 @@ func (mc *mysqlConn) handleOkPacket(data []byte) error { mc.insertId, _, m = readLengthEncodedInteger(data[1+n:]) // server_status [2 bytes] - mc.status = statusFlag(data[1+n+m]) | statusFlag(data[1+n+m+1])<<8 + //mc.status = statusFlag(data[1+n+m]) | statusFlag(data[1+n+m+1])<<8 + mc.status = readStatus(data[1+n+m : 1+n+m+2]) // warning count [2 bytes] if !mc.strict { @@ -603,6 +610,11 @@ func (rows *textRows) readRow(dest []driver.Value) error { // EOF Packet if data[0] == iEOF && len(data) == 5 { + // server_status [2 bytes] + rows.mc.status = readStatus(data[3:]) + if err := rows.mc.discardMoreResultsIfExists(); err != nil { + return err + } rows.mc = nil return io.EOF } @@ -660,6 +672,10 @@ func (mc *mysqlConn) readUntilEOF() error { if err == nil && data[0] != iEOF { continue } + if err == nil && data[0] == iEOF && len(data) == 5 { + mc.status = readStatus(data[3:]) + } + return err // Err or EOF } } @@ -964,6 +980,28 @@ func (stmt *mysqlStmt) writeExecutePacket(args []driver.Value) error { return mc.writePacket(data) } +func (mc *mysqlConn) discardMoreResultsIfExists() error { + for mc.status&statusMoreResultsExists != 0 { + resLen, err := mc.readResultSetHeaderPacket() + if err != nil { + return err + } + if resLen > 0 { + // columns + if err := mc.readUntilEOF(); err != nil { + return err + } + // rows + if err := mc.readUntilEOF(); err != nil { + return err + } + } else { + mc.status &^= statusMoreResultsExists + } + } + return nil +} + // http://dev.mysql.com/doc/internals/en/binary-protocol-resultset-row.html func (rows *binaryRows) readRow(dest []driver.Value) error { data, err := rows.mc.readPacket() @@ -973,11 +1011,16 @@ func (rows *binaryRows) readRow(dest []driver.Value) error { // packet indicator [1 byte] if data[0] != iOK { - rows.mc = nil // EOF Packet if data[0] == iEOF && len(data) == 5 { + rows.mc.status = readStatus(data[3:]) + if err := rows.mc.discardMoreResultsIfExists(); err != nil { + return err + } + rows.mc = nil return io.EOF } + rows.mc = nil // Error otherwise return rows.mc.handleErrorPacket(data) diff --git a/rows.go b/rows.go index 9d97d6d4f..7f281e8c0 100644 --- a/rows.go +++ b/rows.go @@ -38,7 +38,7 @@ type emptyRows struct{} func (rows *mysqlRows) Columns() []string { columns := make([]string, len(rows.columns)) - if rows.mc.cfg.columnsWithAlias { + if rows.mc != nil && rows.mc.cfg.columnsWithAlias { for i := range columns { columns[i] = rows.columns[i].tableName + "." + rows.columns[i].name } @@ -61,6 +61,12 @@ func (rows *mysqlRows) Close() error { // Remove unread packets from stream err := mc.readUntilEOF() + if err == nil { + if err = mc.discardMoreResultsIfExists(); err != nil { + return err + } + } + rows.mc = nil return err } diff --git a/statement.go b/statement.go index f9dae03fa..3622f346d 100644 --- a/statement.go +++ b/statement.go @@ -100,9 +100,9 @@ func (stmt *mysqlStmt) Query(args []driver.Value) (driver.Rows, error) { } rows := new(binaryRows) - rows.mc = mc if resLen > 0 { + rows.mc = mc // Columns // If not cached, read them and cache them if stmt.columns == nil {