github.com/hellobchain/third_party@v0.0.0-20230331131523-deb0478a2e52/go-sql-driver/mysql/statement.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 "fmt" 14 "io" 15 "reflect" 16 ) 17 18 type mysqlStmt struct { 19 mc *mysqlConn 20 id uint32 21 paramCount int 22 } 23 24 func (stmt *mysqlStmt) Close() error { 25 if stmt.mc == nil || stmt.mc.closed.IsSet() { 26 // driver.Stmt.Close can be called more than once, thus this function 27 // has to be idempotent. 28 // See also Issue #450 and golang/go#16019. 29 //errLog.Print(ErrInvalidConn) 30 return driver.ErrBadConn 31 } 32 33 err := stmt.mc.writeCommandPacketUint32(comStmtClose, stmt.id) 34 stmt.mc = nil 35 return err 36 } 37 38 func (stmt *mysqlStmt) NumInput() int { 39 return stmt.paramCount 40 } 41 42 func (stmt *mysqlStmt) ColumnConverter(idx int) driver.ValueConverter { 43 return converter{} 44 } 45 46 func (stmt *mysqlStmt) Exec(args []driver.Value) (driver.Result, error) { 47 if stmt.mc.closed.IsSet() { 48 errLog.Print(ErrInvalidConn) 49 return nil, driver.ErrBadConn 50 } 51 // Send command 52 err := stmt.writeExecutePacket(args) 53 if err != nil { 54 return nil, stmt.mc.markBadConn(err) 55 } 56 57 mc := stmt.mc 58 59 mc.affectedRows = 0 60 mc.insertId = 0 61 62 // Read Result 63 resLen, err := mc.readResultSetHeaderPacket() 64 if err != nil { 65 return nil, err 66 } 67 68 if resLen > 0 { 69 // Columns 70 if err = mc.readUntilEOF(); err != nil { 71 return nil, err 72 } 73 74 // Rows 75 if err := mc.readUntilEOF(); err != nil { 76 return nil, err 77 } 78 } 79 80 if err := mc.discardResults(); err != nil { 81 return nil, err 82 } 83 84 return &mysqlResult{ 85 affectedRows: int64(mc.affectedRows), 86 insertId: int64(mc.insertId), 87 }, nil 88 } 89 90 func (stmt *mysqlStmt) Query(args []driver.Value) (driver.Rows, error) { 91 return stmt.query(args) 92 } 93 94 func (stmt *mysqlStmt) query(args []driver.Value) (*binaryRows, error) { 95 if stmt.mc.closed.IsSet() { 96 errLog.Print(ErrInvalidConn) 97 return nil, driver.ErrBadConn 98 } 99 // Send command 100 err := stmt.writeExecutePacket(args) 101 if err != nil { 102 return nil, stmt.mc.markBadConn(err) 103 } 104 105 mc := stmt.mc 106 107 // Read Result 108 resLen, err := mc.readResultSetHeaderPacket() 109 if err != nil { 110 return nil, err 111 } 112 113 rows := new(binaryRows) 114 115 if resLen > 0 { 116 rows.mc = mc 117 rows.rs.columns, err = mc.readColumns(resLen) 118 } else { 119 rows.rs.done = true 120 121 switch err := rows.NextResultSet(); err { 122 case nil, io.EOF: 123 return rows, nil 124 default: 125 return nil, err 126 } 127 } 128 129 return rows, err 130 } 131 132 type converter struct{} 133 134 // ConvertValue mirrors the reference/default converter in database/sql/driver 135 // with _one_ exception. We support uint64 with their high bit and the default 136 // implementation does not. This function should be kept in sync with 137 // database/sql/driver defaultConverter.ConvertValue() except for that 138 // deliberate difference. 139 func (c converter) ConvertValue(v interface{}) (driver.Value, error) { 140 if driver.IsValue(v) { 141 return v, nil 142 } 143 144 if vr, ok := v.(driver.Valuer); ok { 145 sv, err := callValuerValue(vr) 146 if err != nil { 147 return nil, err 148 } 149 if !driver.IsValue(sv) { 150 return nil, fmt.Errorf("non-Value type %T returned from Value", sv) 151 } 152 return sv, nil 153 } 154 155 rv := reflect.ValueOf(v) 156 switch rv.Kind() { 157 case reflect.Ptr: 158 // indirect pointers 159 if rv.IsNil() { 160 return nil, nil 161 } else { 162 return c.ConvertValue(rv.Elem().Interface()) 163 } 164 case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: 165 return rv.Int(), nil 166 case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64: 167 return rv.Uint(), nil 168 case reflect.Float32, reflect.Float64: 169 return rv.Float(), nil 170 case reflect.Bool: 171 return rv.Bool(), nil 172 case reflect.Slice: 173 ek := rv.Type().Elem().Kind() 174 if ek == reflect.Uint8 { 175 return rv.Bytes(), nil 176 } 177 return nil, fmt.Errorf("unsupported type %T, a slice of %s", v, ek) 178 case reflect.String: 179 return rv.String(), nil 180 } 181 return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind()) 182 } 183 184 var valuerReflectType = reflect.TypeOf((*driver.Valuer)(nil)).Elem() 185 186 // callValuerValue returns vr.Value(), with one exception: 187 // If vr.Value is an auto-generated method on a pointer type and the 188 // pointer is nil, it would panic at runtime in the panicwrap 189 // method. Treat it like nil instead. 190 // 191 // This is so people can implement driver.Value on value types and 192 // still use nil pointers to those types to mean nil/NULL, just like 193 // string/*string. 194 // 195 // This is an exact copy of the same-named unexported function from the 196 // database/sql package. 197 func callValuerValue(vr driver.Valuer) (v driver.Value, err error) { 198 if rv := reflect.ValueOf(vr); rv.Kind() == reflect.Ptr && 199 rv.IsNil() && 200 rv.Type().Elem().Implements(valuerReflectType) { 201 return nil, nil 202 } 203 return vr.Value() 204 }