You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
142 lines
5.5 KiB
142 lines
5.5 KiB
/*
|
|
* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The ASF licenses this file to You 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 zorm
|
|
|
|
import (
|
|
"context"
|
|
"database/sql"
|
|
"database/sql/driver"
|
|
"errors"
|
|
"reflect"
|
|
"strings"
|
|
)
|
|
|
|
// customDriverValueMap 用于配置数据库字段类型的处理关系,key是 Dialect.字段类型,例如 dm.TEXT
|
|
var customDriverValueMap = make(map[string]ICustomDriverValueConver)
|
|
|
|
// iscdvm 是否有自定义的DriverValueMap
|
|
var iscdvm bool
|
|
|
|
// ICustomDriverValueConver 自定义类型转化接口,用于解决 类似达梦 text --> dm.DmClob --> string类型接收的问题
|
|
type ICustomDriverValueConver interface {
|
|
// GetDriverValue 根据数据库列类型,返回driver.Value的实例,struct属性类型
|
|
// map接收或者字段不存在,无法获取到structFieldType,会传入nil
|
|
GetDriverValue(ctx context.Context, columnType *sql.ColumnType, structFieldType *reflect.Type) (driver.Value, error)
|
|
|
|
// ConverDriverValue 数据库列类型,GetDriverValue返回的driver.Value的临时接收值,struct属性类型
|
|
// map接收或者字段不存在,无法获取到structFieldType,会传入nil
|
|
// 返回符合接收类型值的指针,指针,指针!!!!
|
|
ConverDriverValue(ctx context.Context, columnType *sql.ColumnType, tempDriverValue driver.Value, structFieldType *reflect.Type) (interface{}, error)
|
|
}
|
|
|
|
// RegisterCustomDriverValueConver 注册自定义的字段处理逻辑,用于驱动无法直接转换的场景,例如达梦的 TEXT 无法直接转化成 string
|
|
// dialectColumnType 值是 Dialect.字段类型,例如: dm.TEXT
|
|
// 一般是放到init方法里进行注册
|
|
func RegisterCustomDriverValueConver(dialectColumnType string, customDriverValueConver ICustomDriverValueConver) error {
|
|
if len(dialectColumnType) < 1 {
|
|
return errors.New("->RegisterCustomDriverValueConver-->dialectColumnType为空")
|
|
}
|
|
dialectColumnTypes := strings.Split(dialectColumnType, ".")
|
|
if len(dialectColumnTypes) < 2 {
|
|
customDriverValueMap[strings.ToUpper(dialectColumnType)] = customDriverValueConver
|
|
err := errors.New("->RegisterCustomDriverValueConver-->dialectColumnType 值是 Dialect.字段类型,例如: dm.TEXT ,本次正常运行,请尽快修改")
|
|
FuncLogError(nil, err)
|
|
} else {
|
|
customDriverValueMap[strings.ToLower(dialectColumnTypes[0])+"."+strings.ToUpper(dialectColumnTypes[1])] = customDriverValueConver
|
|
}
|
|
iscdvm = true
|
|
return nil
|
|
}
|
|
|
|
type driverValueInfo struct {
|
|
customDriverValueConver ICustomDriverValueConver
|
|
columnType *sql.ColumnType
|
|
tempDriverValue interface{}
|
|
structFieldType *reflect.Type
|
|
}
|
|
|
|
/**
|
|
|
|
import (
|
|
// 00.引入数据库驱动
|
|
"gitee.com/chunanyong/dm"
|
|
"io"
|
|
)
|
|
|
|
// CustomDMText 实现ICustomDriverValueConver接口,扩展自定义类型,例如 达梦数据库TEXT类型,映射出来的是dm.DmClob类型,无法使用string类型直接接收
|
|
type CustomDMText struct{}
|
|
|
|
// GetDriverValue 根据数据库列类型,返回driver.Value的实例,struct属性类型
|
|
// map接收或者字段不存在,无法获取到structFieldType,会传入nil
|
|
func (dmtext CustomDMText) GetDriverValue(ctx context.Context, columnType *sql.ColumnType, structFieldType *reflect.Type) (driver.Value, error) {
|
|
// 如果需要使用structFieldType,需要先判断是否为nil
|
|
// if structFieldType != nil {
|
|
// }
|
|
|
|
return &dm.DmClob{}, nil
|
|
}
|
|
|
|
// ConverDriverValue 数据库列类型,GetDriverValue返回的driver.Value的临时接收值,struct属性类型
|
|
// map接收或者字段不存在,无法获取到structFieldType,会传入nil
|
|
// 返回符合接收类型值的指针,指针,指针!!!!
|
|
func (dmtext CustomDMText) ConverDriverValue(ctx context.Context, columnType *sql.ColumnType, tempDriverValue driver.Value, structFieldType *reflect.Type) (interface{}, error) {
|
|
// 如果需要使用structFieldType,需要先判断是否为nil
|
|
// if structFieldType != nil {
|
|
// }
|
|
|
|
// 类型转换
|
|
dmClob, isok := tempDriverValue.(*dm.DmClob)
|
|
if !isok {
|
|
return tempDriverValue, errors.New("->ConverDriverValue-->转换至*dm.DmClob类型失败")
|
|
}
|
|
if dmClob == nil || !dmClob.Valid {
|
|
return new(string), nil
|
|
}
|
|
// 获取长度
|
|
dmlen, errLength := dmClob.GetLength()
|
|
if errLength != nil {
|
|
return dmClob, errLength
|
|
}
|
|
|
|
// int64转成int类型
|
|
strInt64 := strconv.FormatInt(dmlen, 10)
|
|
dmlenInt, errAtoi := strconv.Atoi(strInt64)
|
|
if errAtoi != nil {
|
|
return dmClob, errAtoi
|
|
}
|
|
|
|
// 读取字符串
|
|
str, errReadString := dmClob.ReadString(1, dmlenInt)
|
|
|
|
// 处理空字符串或NULL造成的EOF错误
|
|
if errReadString == io.EOF {
|
|
return new(string), nil
|
|
}
|
|
|
|
return &str, errReadString
|
|
}
|
|
// RegisterCustomDriverValueConver 注册自定义的字段处理逻辑,用于驱动无法直接转换的场景,例如达梦的 TEXT 无法直接转化成 string
|
|
// 一般是放到init方法里进行注册
|
|
func init() {
|
|
// dialectColumnType 值是 Dialect.字段类型 ,例如 dm.TEXT
|
|
zorm.RegisterCustomDriverValueConver("dm.TEXT", CustomDMText{})
|
|
}
|
|
|
|
**/
|