open-vault/vendor/github.com/SAP/go-hdb/driver/converter.go

336 lines
7.0 KiB
Go

/*
Copyright 2014 SAP SE
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
*/
package driver
import (
"database/sql/driver"
"errors"
"fmt"
"math"
"reflect"
"time"
p "github.com/SAP/go-hdb/internal/protocol"
)
const (
minTinyint = 0
maxTinyint = math.MaxUint8
minSmallint = math.MinInt16
maxSmallint = math.MaxInt16
minInteger = math.MinInt32
maxInteger = math.MaxInt32
minBigint = math.MinInt64
maxBigint = math.MaxInt64
maxReal = math.MaxFloat32
maxDouble = math.MaxFloat64
)
// ErrorIntegerOutOfRange means that an integer exceeds the size of the hdb integer field.
var ErrIntegerOutOfRange = errors.New("integer out of range error")
// ErrorIntegerOutOfRange means that a float exceeds the size of the hdb float field.
var ErrFloatOutOfRange = errors.New("float out of range error")
var typeOfTime = reflect.TypeOf((*time.Time)(nil)).Elem()
var typeOfBytes = reflect.TypeOf((*[]byte)(nil)).Elem()
func columnConverter(dt p.DataType) driver.ValueConverter {
switch dt {
default:
return dbUnknownType{}
case p.DtTinyint:
return dbTinyint
case p.DtSmallint:
return dbSmallint
case p.DtInt:
return dbInt
case p.DtBigint:
return dbBigint
case p.DtReal:
return dbReal
case p.DtDouble:
return dbDouble
case p.DtTime:
return dbTime
case p.DtDecimal:
return dbDecimal
case p.DtString:
return dbString
case p.DtBytes:
return dbBytes
case p.DtLob:
return dbLob
}
}
// unknown type
type dbUnknownType struct{}
var _ driver.ValueConverter = dbUnknownType{} //check that type implements interface
func (t dbUnknownType) ConvertValue(v interface{}) (driver.Value, error) {
return nil, fmt.Errorf("column converter for data %v type %T is not implemented", v, v)
}
// int types
var dbTinyint = dbIntType{min: minTinyint, max: maxTinyint}
var dbSmallint = dbIntType{min: minSmallint, max: maxSmallint}
var dbInt = dbIntType{min: minInteger, max: maxInteger}
var dbBigint = dbIntType{min: minBigint, max: maxBigint}
type dbIntType struct {
min int64
max int64
}
var _ driver.ValueConverter = dbIntType{} //check that type implements interface
func (i dbIntType) ConvertValue(v interface{}) (driver.Value, error) {
if v == nil {
return v, nil
}
rv := reflect.ValueOf(v)
switch rv.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
i64 := rv.Int()
if i64 > i.max || i64 < i.min {
return nil, ErrIntegerOutOfRange
}
return i64, nil
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64:
u64 := rv.Uint()
if u64 > uint64(i.max) {
return nil, ErrIntegerOutOfRange
}
return int64(u64), nil
case reflect.Ptr:
// indirect pointers
if rv.IsNil() {
return nil, nil
}
return i.ConvertValue(rv.Elem().Interface())
}
return nil, fmt.Errorf("unsupported integer conversion type error %T %v", v, v)
}
//float types
var dbReal = dbFloatType{max: maxReal}
var dbDouble = dbFloatType{max: maxDouble}
type dbFloatType struct {
max float64
}
var _ driver.ValueConverter = dbFloatType{} //check that type implements interface
func (f dbFloatType) ConvertValue(v interface{}) (driver.Value, error) {
if v == nil {
return v, nil
}
rv := reflect.ValueOf(v)
switch rv.Kind() {
case reflect.Float32, reflect.Float64:
f64 := rv.Float()
if math.Abs(f64) > f.max {
return nil, ErrFloatOutOfRange
}
return f64, nil
case reflect.Ptr:
// indirect pointers
if rv.IsNil() {
return nil, nil
}
return f.ConvertValue(rv.Elem().Interface())
}
return nil, fmt.Errorf("unsupported float conversion type error %T %v", v, v)
}
//time
var dbTime = dbTimeType{}
type dbTimeType struct{}
var _ driver.ValueConverter = dbTimeType{} //check that type implements interface
func (t dbTimeType) ConvertValue(v interface{}) (driver.Value, error) {
if v == nil {
return nil, nil
}
switch v := v.(type) {
case time.Time:
return v, nil
}
rv := reflect.ValueOf(v)
switch rv.Kind() {
case reflect.Ptr:
// indirect pointers
if rv.IsNil() {
return nil, nil
}
return t.ConvertValue(rv.Elem().Interface())
}
if rv.Type().ConvertibleTo(typeOfTime) {
tv := rv.Convert(typeOfTime)
return tv.Interface().(time.Time), nil
}
return nil, fmt.Errorf("unsupported time conversion type error %T %v", v, v)
}
//decimal
var dbDecimal = dbDecimalType{}
type dbDecimalType struct{}
var _ driver.ValueConverter = dbDecimalType{} //check that type implements interface
func (d dbDecimalType) ConvertValue(v interface{}) (driver.Value, error) {
if v == nil {
return nil, nil
}
if v, ok := v.([]byte); ok {
return v, nil
}
return nil, fmt.Errorf("unsupported decimal conversion type error %T %v", v, v)
}
//string
var dbString = dbStringType{}
type dbStringType struct{}
var _ driver.ValueConverter = dbStringType{} //check that type implements interface
func (d dbStringType) ConvertValue(v interface{}) (driver.Value, error) {
if v == nil {
return v, nil
}
switch v := v.(type) {
case string, []byte:
return v, nil
}
rv := reflect.ValueOf(v)
switch rv.Kind() {
case reflect.String:
return rv.String(), nil
case reflect.Slice:
if rv.Type() == typeOfBytes {
return rv.Bytes(), nil
}
case reflect.Ptr:
// indirect pointers
if rv.IsNil() {
return nil, nil
}
return d.ConvertValue(rv.Elem().Interface())
}
if rv.Type().ConvertibleTo(typeOfBytes) {
bv := rv.Convert(typeOfBytes)
return bv.Interface().([]byte), nil
}
return nil, fmt.Errorf("unsupported character conversion type error %T %v", v, v)
}
//bytes
var dbBytes = dbBytesType{}
type dbBytesType struct{}
var _ driver.ValueConverter = dbBytesType{} //check that type implements interface
func (d dbBytesType) ConvertValue(v interface{}) (driver.Value, error) {
if v == nil {
return v, nil
}
if v, ok := v.([]byte); ok {
return v, nil
}
rv := reflect.ValueOf(v)
switch rv.Kind() {
case reflect.Slice:
if rv.Type() == typeOfBytes {
return rv.Bytes(), nil
}
case reflect.Ptr:
// indirect pointers
if rv.IsNil() {
return nil, nil
}
return d.ConvertValue(rv.Elem().Interface())
}
if rv.Type().ConvertibleTo(typeOfBytes) {
bv := rv.Convert(typeOfBytes)
return bv.Interface().([]byte), nil
}
return nil, fmt.Errorf("unsupported bytes conversion type error %T %v", v, v)
}
//lob
var dbLob = dbLobType{}
type dbLobType struct{}
var _ driver.ValueConverter = dbLobType{} //check that type implements interface
func (d dbLobType) ConvertValue(v interface{}) (driver.Value, error) {
if v, ok := v.(int64); ok {
return v, nil
}
return nil, fmt.Errorf("unsupported lob conversion type error %T %v", v, v)
}