terraform/vendor/github.com/ziutek/mymysql/native/binding.go

151 lines
2.9 KiB
Go

package native
import (
"github.com/ziutek/mymysql/mysql"
"reflect"
"time"
)
var (
timeType = reflect.TypeOf(time.Time{})
timestampType = reflect.TypeOf(mysql.Timestamp{})
dateType = reflect.TypeOf(mysql.Date{})
durationType = reflect.TypeOf(time.Duration(0))
blobType = reflect.TypeOf(mysql.Blob{})
rawType = reflect.TypeOf(mysql.Raw{})
)
// val should be an addressable value
func bindValue(val reflect.Value) (out paramValue) {
if !val.IsValid() {
out.typ = MYSQL_TYPE_NULL
return
}
typ := val.Type()
if typ.Kind() == reflect.Ptr {
// We have addressable pointer
out.addr = val.Addr()
// Dereference pointer for next operation on its value
typ = typ.Elem()
val = val.Elem()
} else {
// We have addressable value. Create a pointer to it
pv := val.Addr()
// This pointer is unaddressable so copy it and return an address
out.addr = reflect.New(pv.Type())
out.addr.Elem().Set(pv)
}
// Obtain value type
switch typ.Kind() {
case reflect.String:
out.typ = MYSQL_TYPE_STRING
out.length = -1
return
case reflect.Int:
out.typ = _INT_TYPE
out.length = _SIZE_OF_INT
return
case reflect.Int8:
out.typ = MYSQL_TYPE_TINY
out.length = 1
return
case reflect.Int16:
out.typ = MYSQL_TYPE_SHORT
out.length = 2
return
case reflect.Int32:
out.typ = MYSQL_TYPE_LONG
out.length = 4
return
case reflect.Int64:
if typ == durationType {
out.typ = MYSQL_TYPE_TIME
out.length = -1
return
}
out.typ = MYSQL_TYPE_LONGLONG
out.length = 8
return
case reflect.Uint:
out.typ = _INT_TYPE | MYSQL_UNSIGNED_MASK
out.length = _SIZE_OF_INT
return
case reflect.Uint8:
out.typ = MYSQL_TYPE_TINY | MYSQL_UNSIGNED_MASK
out.length = 1
return
case reflect.Uint16:
out.typ = MYSQL_TYPE_SHORT | MYSQL_UNSIGNED_MASK
out.length = 2
return
case reflect.Uint32:
out.typ = MYSQL_TYPE_LONG | MYSQL_UNSIGNED_MASK
out.length = 4
return
case reflect.Uint64:
out.typ = MYSQL_TYPE_LONGLONG | MYSQL_UNSIGNED_MASK
out.length = 8
return
case reflect.Float32:
out.typ = MYSQL_TYPE_FLOAT
out.length = 4
return
case reflect.Float64:
out.typ = MYSQL_TYPE_DOUBLE
out.length = 8
return
case reflect.Slice:
out.length = -1
if typ == blobType {
out.typ = MYSQL_TYPE_BLOB
return
}
if typ.Elem().Kind() == reflect.Uint8 {
out.typ = MYSQL_TYPE_VAR_STRING
return
}
case reflect.Struct:
out.length = -1
if typ == timeType {
out.typ = MYSQL_TYPE_DATETIME
return
}
if typ == dateType {
out.typ = MYSQL_TYPE_DATE
return
}
if typ == timestampType {
out.typ = MYSQL_TYPE_TIMESTAMP
return
}
if typ == rawType {
out.typ = val.FieldByName("Typ").Interface().(uint16)
out.addr = val.FieldByName("Val").Addr()
out.raw = true
return
}
case reflect.Bool:
out.typ = MYSQL_TYPE_TINY
// bool implementation isn't documented so we treat it in special way
out.length = -1
return
}
panic(mysql.ErrBindUnkType)
}