|
@@ -19,14 +19,31 @@ type mysqlField struct {
|
|
|
flags fieldFlag
|
|
flags fieldFlag
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// mysqlRows is the driver-internal Rows struct that is never given to
|
|
|
|
|
+// the database/sql package. This struct is 40 bytes on 64-bit
|
|
|
|
|
+// machines and is recycled. Its size isn't very relevant, since we
|
|
|
|
|
+// recycle it.
|
|
|
|
|
+//
|
|
|
|
|
+// Allocate with newMysqlRows (from buffer.go) and return with
|
|
|
|
|
+// putMySQLRows. See also: mysqlRowsI.
|
|
|
type mysqlRows struct {
|
|
type mysqlRows struct {
|
|
|
mc *mysqlConn
|
|
mc *mysqlConn
|
|
|
- binary bool
|
|
|
|
|
columns []mysqlField
|
|
columns []mysqlField
|
|
|
|
|
+ binary bool // Note: packing small bool fields at the end
|
|
|
eof bool
|
|
eof bool
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
+// mysqlRowsI implements driver.Rows. Its wrapped *mysqlRows pointer
|
|
|
|
|
+// becomes nil and recycled on Close. This struct is kept small (8
|
|
|
|
|
+// bytes) to minimize garbage creation.
|
|
|
|
|
+type mysqlRowsI struct {
|
|
|
|
|
+ *mysqlRows
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
func (rows *mysqlRows) Columns() []string {
|
|
func (rows *mysqlRows) Columns() []string {
|
|
|
|
|
+ if rows == nil {
|
|
|
|
|
+ return nil
|
|
|
|
|
+ }
|
|
|
columns := make([]string, len(rows.columns))
|
|
columns := make([]string, len(rows.columns))
|
|
|
for i := range columns {
|
|
for i := range columns {
|
|
|
columns[i] = rows.columns[i].name
|
|
columns[i] = rows.columns[i].name
|
|
@@ -34,7 +51,18 @@ func (rows *mysqlRows) Columns() []string {
|
|
|
return columns
|
|
return columns
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-func (rows *mysqlRows) Close() (err error) {
|
|
|
|
|
|
|
+func (ri *mysqlRowsI) Close() error {
|
|
|
|
|
+ if ri.mysqlRows == nil {
|
|
|
|
|
+ return nil // make Close() idempotent
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ err := ri.mysqlRows.close()
|
|
|
|
|
+ putMysqlRows(ri.mysqlRows)
|
|
|
|
|
+ ri.mysqlRows = nil
|
|
|
|
|
+ return err
|
|
|
|
|
+}
|
|
|
|
|
+
|
|
|
|
|
+func (rows *mysqlRows) close() (err error) {
|
|
|
// Remove unread packets from stream
|
|
// Remove unread packets from stream
|
|
|
if !rows.eof {
|
|
if !rows.eof {
|
|
|
if rows.mc == nil || rows.mc.netConn == nil {
|
|
if rows.mc == nil || rows.mc.netConn == nil {
|
|
@@ -50,10 +78,19 @@ func (rows *mysqlRows) Close() (err error) {
|
|
|
|
|
|
|
|
rows.mc = nil
|
|
rows.mc = nil
|
|
|
|
|
|
|
|
|
|
+ if !rows.binary { // Binary rows use cached columns
|
|
|
|
|
+ putFields(rows.columns)
|
|
|
|
|
+ }
|
|
|
|
|
+ rows.columns = nil
|
|
|
|
|
+
|
|
|
return
|
|
return
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
func (rows *mysqlRows) Next(dest []driver.Value) (err error) {
|
|
func (rows *mysqlRows) Next(dest []driver.Value) (err error) {
|
|
|
|
|
+ if rows == nil {
|
|
|
|
|
+ return errInvalidConn
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
if rows.eof {
|
|
if rows.eof {
|
|
|
return io.EOF
|
|
return io.EOF
|
|
|
}
|
|
}
|