github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/go-sql-driver/mysql/rows.go (about) 1 // Go MySQL Driver - A MySQL-Driver for Go's database/sql package 2 // 3 // Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved. 4 // 5 // This Source Code Form is subject to the terms of the Mozilla Public 6 // License, v. 2.0. If a copy of the MPL was not distributed with this file, 7 // You can obtain one at http://mozilla.org/MPL/2.0/. 8 9 package mysql 10 11 import ( 12 "database/sql/driver" 13 "io" 14 "math" 15 "reflect" 16 ) 17 18 type resultSet struct { 19 columns []mysqlField 20 columnNames []string 21 done bool 22 } 23 24 type mysqlRows struct { 25 mc *mysqlConn 26 rs resultSet 27 finish func() 28 } 29 30 type binaryRows struct { 31 mysqlRows 32 } 33 34 type textRows struct { 35 mysqlRows 36 } 37 38 func (rows *mysqlRows) Columns() []string { 39 if rows.rs.columnNames != nil { 40 return rows.rs.columnNames 41 } 42 43 columns := make([]string, len(rows.rs.columns)) 44 if rows.mc != nil && rows.mc.cfg.ColumnsWithAlias { 45 for i := range columns { 46 if tableName := rows.rs.columns[i].tableName; len(tableName) > 0 { 47 columns[i] = tableName + "." + rows.rs.columns[i].name 48 } else { 49 columns[i] = rows.rs.columns[i].name 50 } 51 } 52 } else { 53 for i := range columns { 54 columns[i] = rows.rs.columns[i].name 55 } 56 } 57 58 rows.rs.columnNames = columns 59 return columns 60 } 61 62 func (rows *mysqlRows) ColumnTypeDatabaseTypeName(i int) string { 63 return rows.rs.columns[i].typeDatabaseName() 64 } 65 66 // func (rows *mysqlRows) ColumnTypeLength(i int) (length int64, ok bool) { 67 // return int64(rows.rs.columns[i].length), true 68 // } 69 70 func (rows *mysqlRows) ColumnTypeNullable(i int) (nullable, ok bool) { 71 return rows.rs.columns[i].flags&flagNotNULL == 0, true 72 } 73 74 func (rows *mysqlRows) ColumnTypePrecisionScale(i int) (int64, int64, bool) { 75 column := rows.rs.columns[i] 76 decimals := int64(column.decimals) 77 78 switch column.fieldType { 79 case fieldTypeDecimal, fieldTypeNewDecimal: 80 if decimals > 0 { 81 return int64(column.length) - 2, decimals, true 82 } 83 return int64(column.length) - 1, decimals, true 84 case fieldTypeTimestamp, fieldTypeDateTime, fieldTypeTime: 85 return decimals, decimals, true 86 case fieldTypeFloat, fieldTypeDouble: 87 if decimals == 0x1f { 88 return math.MaxInt64, math.MaxInt64, true 89 } 90 return math.MaxInt64, decimals, true 91 } 92 93 return 0, 0, false 94 } 95 96 func (rows *mysqlRows) ColumnTypeScanType(i int) reflect.Type { 97 return rows.rs.columns[i].scanType() 98 } 99 100 func (rows *mysqlRows) Close() (err error) { 101 if f := rows.finish; f != nil { 102 f() 103 rows.finish = nil 104 } 105 106 mc := rows.mc 107 if mc == nil { 108 return nil 109 } 110 if err := mc.error(); err != nil { 111 return err 112 } 113 114 // flip the buffer for this connection if we need to drain it. 115 // note that for a successful query (i.e. one where rows.next() 116 // has been called until it returns false), `rows.mc` will be nil 117 // by the time the user calls `(*Rows).Close`, so we won't reach this 118 // see: https://github.com/golang/go/commit/651ddbdb5056ded455f47f9c494c67b389622a47 119 mc.buf.flip() 120 121 // Remove unread packets from stream 122 if !rows.rs.done { 123 err = mc.readUntilEOF() 124 } 125 if err == nil { 126 if err = mc.discardResults(); err != nil { 127 return err 128 } 129 } 130 131 rows.mc = nil 132 return err 133 } 134 135 func (rows *mysqlRows) HasNextResultSet() (b bool) { 136 if rows.mc == nil { 137 return false 138 } 139 return rows.mc.status&statusMoreResultsExists != 0 140 } 141 142 func (rows *mysqlRows) nextResultSet() (int, error) { 143 if rows.mc == nil { 144 return 0, io.EOF 145 } 146 if err := rows.mc.error(); err != nil { 147 return 0, err 148 } 149 150 // Remove unread packets from stream 151 if !rows.rs.done { 152 if err := rows.mc.readUntilEOF(); err != nil { 153 return 0, err 154 } 155 rows.rs.done = true 156 } 157 158 if !rows.HasNextResultSet() { 159 rows.mc = nil 160 return 0, io.EOF 161 } 162 rows.rs = resultSet{} 163 return rows.mc.readResultSetHeaderPacket() 164 } 165 166 func (rows *mysqlRows) nextNotEmptyResultSet() (int, error) { 167 for { 168 resLen, err := rows.nextResultSet() 169 if err != nil { 170 return 0, err 171 } 172 173 if resLen > 0 { 174 return resLen, nil 175 } 176 177 rows.rs.done = true 178 } 179 } 180 181 func (rows *binaryRows) NextResultSet() error { 182 resLen, err := rows.nextNotEmptyResultSet() 183 if err != nil { 184 return err 185 } 186 187 rows.rs.columns, err = rows.mc.readColumns(resLen) 188 return err 189 } 190 191 func (rows *binaryRows) Next(dest []driver.Value) error { 192 if mc := rows.mc; mc != nil { 193 if err := mc.error(); err != nil { 194 return err 195 } 196 197 // Fetch next row from stream 198 return rows.readRow(dest) 199 } 200 return io.EOF 201 } 202 203 func (rows *textRows) NextResultSet() (err error) { 204 resLen, err := rows.nextNotEmptyResultSet() 205 if err != nil { 206 return err 207 } 208 209 rows.rs.columns, err = rows.mc.readColumns(resLen) 210 return err 211 } 212 213 func (rows *textRows) Next(dest []driver.Value) error { 214 if mc := rows.mc; mc != nil { 215 if err := mc.error(); err != nil { 216 return err 217 } 218 219 // Fetch next row from stream 220 return rows.readRow(dest) 221 } 222 return io.EOF 223 }