OSDN Git Service

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