mirror of
https://github.com/fnproject/fn.git
synced 2022-10-28 21:29:17 +03:00
* go modified fiddling with vendor got rid of the vendor directory revendored but with the exact same versions of things maybe better added mods for the images revendored using `GOFLAGS` instead of repeating my self vendor everything to the exact same commit hash as before and fixed ugorji Delete Deproxy.toml empty file cleaned up some file cleaned up some cruft get rid of some unused packages and exclude some Microsoft packages added flags to the variables that get pushed into docker in the makefile It works I suppose added noop excluded what we did not want even less hacky reverted to a version that has not been mangled * get rid of my experiment
212 lines
4.9 KiB
Go
212 lines
4.9 KiB
Go
// Go MySQL Driver - A MySQL-Driver for Go's database/sql package
|
|
//
|
|
// Copyright 2012 The Go-MySQL-Driver Authors. All rights reserved.
|
|
//
|
|
// This Source Code Form is subject to the terms of the Mozilla Public
|
|
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
|
// You can obtain one at http://mozilla.org/MPL/2.0/.
|
|
|
|
package mysql
|
|
|
|
import (
|
|
"database/sql/driver"
|
|
"fmt"
|
|
"io"
|
|
"reflect"
|
|
"strconv"
|
|
)
|
|
|
|
type mysqlStmt struct {
|
|
mc *mysqlConn
|
|
id uint32
|
|
paramCount int
|
|
}
|
|
|
|
func (stmt *mysqlStmt) Close() error {
|
|
if stmt.mc == nil || stmt.mc.closed.IsSet() {
|
|
// driver.Stmt.Close can be called more than once, thus this function
|
|
// has to be idempotent.
|
|
// See also Issue #450 and golang/go#16019.
|
|
//errLog.Print(ErrInvalidConn)
|
|
return driver.ErrBadConn
|
|
}
|
|
|
|
err := stmt.mc.writeCommandPacketUint32(comStmtClose, stmt.id)
|
|
stmt.mc = nil
|
|
return err
|
|
}
|
|
|
|
func (stmt *mysqlStmt) NumInput() int {
|
|
return stmt.paramCount
|
|
}
|
|
|
|
func (stmt *mysqlStmt) ColumnConverter(idx int) driver.ValueConverter {
|
|
return converter{}
|
|
}
|
|
|
|
func (stmt *mysqlStmt) Exec(args []driver.Value) (driver.Result, error) {
|
|
if stmt.mc.closed.IsSet() {
|
|
errLog.Print(ErrInvalidConn)
|
|
return nil, driver.ErrBadConn
|
|
}
|
|
// Send command
|
|
err := stmt.writeExecutePacket(args)
|
|
if err != nil {
|
|
return nil, stmt.mc.markBadConn(err)
|
|
}
|
|
|
|
mc := stmt.mc
|
|
|
|
mc.affectedRows = 0
|
|
mc.insertId = 0
|
|
|
|
// Read Result
|
|
resLen, err := mc.readResultSetHeaderPacket()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
if resLen > 0 {
|
|
// Columns
|
|
if err = mc.readUntilEOF(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
// Rows
|
|
if err := mc.readUntilEOF(); err != nil {
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
if err := mc.discardResults(); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &mysqlResult{
|
|
affectedRows: int64(mc.affectedRows),
|
|
insertId: int64(mc.insertId),
|
|
}, nil
|
|
}
|
|
|
|
func (stmt *mysqlStmt) Query(args []driver.Value) (driver.Rows, error) {
|
|
return stmt.query(args)
|
|
}
|
|
|
|
func (stmt *mysqlStmt) query(args []driver.Value) (*binaryRows, error) {
|
|
if stmt.mc.closed.IsSet() {
|
|
errLog.Print(ErrInvalidConn)
|
|
return nil, driver.ErrBadConn
|
|
}
|
|
// Send command
|
|
err := stmt.writeExecutePacket(args)
|
|
if err != nil {
|
|
return nil, stmt.mc.markBadConn(err)
|
|
}
|
|
|
|
mc := stmt.mc
|
|
|
|
// Read Result
|
|
resLen, err := mc.readResultSetHeaderPacket()
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
rows := new(binaryRows)
|
|
|
|
if resLen > 0 {
|
|
rows.mc = mc
|
|
rows.rs.columns, err = mc.readColumns(resLen)
|
|
} else {
|
|
rows.rs.done = true
|
|
|
|
switch err := rows.NextResultSet(); err {
|
|
case nil, io.EOF:
|
|
return rows, nil
|
|
default:
|
|
return nil, err
|
|
}
|
|
}
|
|
|
|
return rows, err
|
|
}
|
|
|
|
type converter struct{}
|
|
|
|
// ConvertValue mirrors the reference/default converter in database/sql/driver
|
|
// with _one_ exception. We support uint64 with their high bit and the default
|
|
// implementation does not. This function should be kept in sync with
|
|
// database/sql/driver defaultConverter.ConvertValue() except for that
|
|
// deliberate difference.
|
|
func (c converter) ConvertValue(v interface{}) (driver.Value, error) {
|
|
if driver.IsValue(v) {
|
|
return v, nil
|
|
}
|
|
|
|
if vr, ok := v.(driver.Valuer); ok {
|
|
sv, err := callValuerValue(vr)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
if !driver.IsValue(sv) {
|
|
return nil, fmt.Errorf("non-Value type %T returned from Value", sv)
|
|
}
|
|
return sv, nil
|
|
}
|
|
|
|
rv := reflect.ValueOf(v)
|
|
switch rv.Kind() {
|
|
case reflect.Ptr:
|
|
// indirect pointers
|
|
if rv.IsNil() {
|
|
return nil, nil
|
|
} else {
|
|
return c.ConvertValue(rv.Elem().Interface())
|
|
}
|
|
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
|
|
return rv.Int(), nil
|
|
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32:
|
|
return int64(rv.Uint()), nil
|
|
case reflect.Uint64:
|
|
u64 := rv.Uint()
|
|
if u64 >= 1<<63 {
|
|
return strconv.FormatUint(u64, 10), nil
|
|
}
|
|
return int64(u64), nil
|
|
case reflect.Float32, reflect.Float64:
|
|
return rv.Float(), nil
|
|
case reflect.Bool:
|
|
return rv.Bool(), nil
|
|
case reflect.Slice:
|
|
ek := rv.Type().Elem().Kind()
|
|
if ek == reflect.Uint8 {
|
|
return rv.Bytes(), nil
|
|
}
|
|
return nil, fmt.Errorf("unsupported type %T, a slice of %s", v, ek)
|
|
case reflect.String:
|
|
return rv.String(), nil
|
|
}
|
|
return nil, fmt.Errorf("unsupported type %T, a %s", v, rv.Kind())
|
|
}
|
|
|
|
var valuerReflectType = reflect.TypeOf((*driver.Valuer)(nil)).Elem()
|
|
|
|
// callValuerValue returns vr.Value(), with one exception:
|
|
// If vr.Value is an auto-generated method on a pointer type and the
|
|
// pointer is nil, it would panic at runtime in the panicwrap
|
|
// method. Treat it like nil instead.
|
|
//
|
|
// This is so people can implement driver.Value on value types and
|
|
// still use nil pointers to those types to mean nil/NULL, just like
|
|
// string/*string.
|
|
//
|
|
// This is an exact copy of the same-named unexported function from the
|
|
// database/sql package.
|
|
func callValuerValue(vr driver.Valuer) (v driver.Value, err error) {
|
|
if rv := reflect.ValueOf(vr); rv.Kind() == reflect.Ptr &&
|
|
rv.IsNil() &&
|
|
rv.Type().Elem().Implements(valuerReflectType) {
|
|
return nil, nil
|
|
}
|
|
return vr.Value()
|
|
}
|