go 的ORM改造支持达梦数据库
达梦数据库语法兼容Oracle语法,达梦在语法解析的时候会把所有字段不带""的全部转换成大写,导致查询不到结果,或者字段不存在的问题。
改造原理
ORM的SQL语句产生本质是反射结构体信息,转换成SQL或者是SQL拼接:
- SQL执行的方式直接采用Oracle语法的解析规则;
- 对Oracle的语法解析规则进行修改,然后实现orm支持达梦数据库;
- beego,xorm,gorm语法底层规则大同小异。可以用相同的方式去实现语法解析接口,注册到ORM引擎中
XORM举例,进行改造
如图的xorm的执行流程,只要编译一个达梦的dialect注册放入map中。就可以兼容
项目go-xorm改造后的demo
https://github.com/sjm1327605995/dm-xorm.git
注册自定义的语法解析器,这里利用oracle语法改造
欢迎在github 留个issues
func init() {
core.RegisterDriver("dm", &gdmDriver{})
core.RegisterDialect("dm", func() core.Dialect {
return &dm{}
})
}
Quote是结构体转换成sql时解析器会添加响应的前后缀。
pg 是``
func (db *dm) Quote(name string) string {
return "\"" + name + "\""
}
类型映射
func (db *dm) SqlType(c *core.Column) string {
var res string
switch t := c.SQLType.Name; t {
case core.Bit, core.TinyInt, core.SmallInt, core.MediumInt, core.Int, core.Integer, core.BigInt, core.Bool, core.Serial, core.BigSerial:
res = "BIGINT"
case core.Binary, core.VarBinary, core.Blob, core.TinyBlob, core.MediumBlob, core.LongBlob, core.Bytea:
return core.Blob
case core.Time, core.DateTime, core.TimeStamp:
res = core.TimeStamp
case core.TimeStampz:
res = "TIMESTAMP WITH TIME ZONE"
case core.Float, core.Double, core.Numeric, core.Decimal:
res = "NUMBER"
case core.Text, core.MediumText, core.LongText, core.Json:
res = "CLOB"
case core.Char, core.Varchar, core.TinyText:
res = "VARCHAR2"
default:
res = t
}
hasLen1 := (c.Length > 0)
hasLen2 := (c.Length2 > 0)
if hasLen2 {
res += "(" + strconv.Itoa(c.Length) + "," + strconv.Itoa(c.Length2) + ")"
} else if hasLen1 {
res += "(" + strconv.Itoa(c.Length) + ")"
}
return res
}
达梦的字段类型可能无法与其他数据库映射
xorm枚举了一些类型,分别对应数据库中的字段类型。枚举的类型一般在结构体后tag后面添加。不添加就是默认的类型