1 Star 0 Fork 0

ichub / gomini

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
克隆/下载
factroy_postgres.go 18.13 KB
一键复制 编辑 原始数据 按行查看 历史
leijmdas 提交于 2024-05-16 14:34 . add
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655
package metafactroy
import (
"container/list"
"encoding/json"
"fmt"
"gitee.com/ichub/goconfig/common/base/baseconfig"
"gitee.com/ichub/goconfig/common/base/baseconsts"
"gitee.com/ichub/goconfig/common/base/baseutils/stringutils"
"gitee.com/ichub/goconfig/common/dbcontent/database"
"gitee.com/ichub/goconfig/common/ichublog"
"gitee.com/ichub/gomini/mini/meta/db/metacontext"
"gitee.com/ichub/gomini/mini/meta/db/metadb"
"github.com/jinzhu/gorm"
jsoniter "github.com/json-iterator/go"
"github.com/sirupsen/logrus"
"log"
)
/*
@Title 文件名称: db_factroy.go
@Description 描述: 础数据库工厂
@Author 作者: leijianming@163.com 时间(2024-01-31 22:38:21)
@Update 作者: leijianming@163.com 时间(2024-01-31 22:38:21)
*/
type FactroyPostgres struct {
DbClientDto *baseconfig.DbClientDto
funcGetDb database.FuncGetDb `json:"-"`
Table string
TableComment *string
Pkey string
PkeyType string
StringFieldName string `json:"-"`
StringFieldLen string `json:"-"`
}
func NewFactroyPostgres() *FactroyPostgres {
return &FactroyPostgres{}
}
func (this *FactroyPostgres) IsMysql() bool {
return this.DbClientDto.Dbtype == baseconsts.DB_TYPE_MYSQL
}
func (this *FactroyPostgres) IniDb(conn string) (dbinst *gorm.DB) {
if this.IsMysql() {
dbinst, _ = database.NewIchubDbClient().InitDbMysql(conn)
} else {
dbinst, _ = database.NewIchubDbClient().InitDbPostgres(conn)
}
return
}
func (this *FactroyPostgres) makeBase(structName string) string {
s := `type %sBase struct{
}`
return fmt.Sprintf(s, structName)
}
func (this *FactroyPostgres) printList(lst *list.List) {
logrus.Println()
for i := lst.Front(); i != nil; i = i.Next() {
logrus.Println(i.Value)
}
}
func (this *FactroyPostgres) findPGTableComment() *metadb.MetadataTable {
sql := `SELECT
relname as table_name,
obj_description(oid) as table_comment
FROM pg_class
WHERE relkind = 'r' and relname='%s'
`
sql = fmt.Sprintf(sql, this.Table)
var tables metadb.MetadataTable
e := this.funcGetDb().Model(&metadb.MetadataPkinfo{}).Raw(sql).Find(&tables).Error
if e != nil {
fmt.Println("***=" + e.Error())
}
return &tables
}
func (this *FactroyPostgres) findPGColumnComment() []metadb.MetadataColumn {
s := `SELECT
c.relname as TableName,
col_description ( a.attrelid, a.attnum ) AS ColumnComment,
format_type ( a.atttypid, a.atttypmod ) AS ColumnType,
a.attname AS ColumnName
FROM pg_class AS c, pg_attribute AS a
WHERE a.attrelid = c.oid AND a.attnum >0
and c.relname = '%s' `
s = fmt.Sprintf(s, this.Table)
var cs []metadb.MetadataColumn
e := this.funcGetDb().Model(&metadb.MetadataPkinfo{}).Raw(s).Find(&cs).Error
if e != nil {
fmt.Println("***=" + e.Error())
}
return cs
}
func (this *FactroyPostgres) String() string {
s, _ := jsoniter.Marshal(this)
return string(s)
}
func (this *FactroyPostgres) ToString() string {
s, _ := json.MarshalIndent(this, "", " ")
return string(s)
}
/*double double double
float float float
int32 int int32 使用可变长编码方式。编码负数时不够高效——如果你的字段可能含有负数,那么请使用sint32。
int64 long int64 使用可变长编码方式。编码负数时不够高效——如果你的字段可能含有负数,那么请使用sint64。
unit32 int[1] unit32 总是4个字节。如果数值总是比总是比228大的话,这个类型会比uint32高效。
unit64 long[1] unit64 总是8个字节。如果数值总是比总是比256大的话,这个类型会比uint64高效。
sint32 int int32 使用可变长编码方式。有符号的整型值。编码时比通常的int32高效。
sint64 long int64 使用可变长编码方式。有符号的整型值。编码时比通常的int64高效。
fixed32 int[1] unit32
fixed64 long[1] unit64 总是8个字节。如果数值总是比总是比256大的话,这个类型会比uint64高效。
sfixed32 int int32 总是4个字节。
sfixed64 long int64 总是8个字节。
bool boolean bool
string String string 一个字符串必须是UTF-8编码或者7-bit ASCII编码的文本。
bytes
*/
//dbcontent type->go type
func (this *FactroyPostgres) makeModelColNewLst(columns *[]metadb.MetadataColumn, ifnil bool) *list.List {
s := `
entity.{{.colname}} = new({{.goType}})
`
lst := list.New()
for _, v := range *columns {
colname := stringutils.Case2Camel(v.ColumnName)
goType := v.FindGoType(v.DataType)
if v.ColumnName != this.Pkey {
vars := make(map[string]interface{})
vars["goType"] = goType
vars["colname"] = colname
lst.PushBack(stringutils.ParseTemplateString(s, vars))
}
}
this.printList(lst)
return lst
}
func (this *FactroyPostgres) makeModelGo(columns *[]metadb.MetadataColumn) *list.List {
sn := fmt.Sprintf(stringutils.Case2Camel(this.Table))
snbase := this.makeBase(sn)
lst := list.New()
lst.PushBack("/* 指定扩展结结构,单独存文件。生成时不会覆盖: */")
lst.PushBack(fmt.Sprintf("//type %sBase struct {ModelBase}", sn))
comment := fmt.Sprintf("/* %s */", *this.TableComment)
lst.PushBack(comment)
lst.PushBack(fmt.Sprintf("type %s%s struct {", "", stringutils.UcfirstCase2Camel(this.Table)))
//lst.PushBack(fmt.Sprintf("\tmodel.ParamBase" ))
lst.PushBack(fmt.Sprintf("//\t%sBase", sn))
lst.PushBack(fmt.Sprintf("//\tModelBase"))
for _, v := range *columns {
col_comment := fmt.Sprintf("\t/* %s */", v.ColumnComment)
lst.PushBack(col_comment)
//timeStr :=v.Birthday.Format("2006-01-02 15:04:05")
dt := v.FindGoType(v.DataType)
col_def := v.ColumnName + ";type:" + v.ColumnType
if v.ColumnName == this.Pkey {
col_def = col_def + ";PRIMARY_KEY"
}
if this.IsMysql() {
col_def = col_def + fmt.Sprintf(";comment:'%s'", v.ColumnComment)
}
//if true || this.Dbtype_mysql {
if len(v.ColumnDefault) > 0 {
if v.IfNumeric() {
col_def = col_def + fmt.Sprintf(";default:%s", v.ColumnDefault)
}
if v.IfString() {
col_def = col_def + fmt.Sprintf(";default:\\'%s\\'", v.ColumnDefault)
}
}
//}
json_def := v.ColumnName //utils.Lcfirst(utils.Case2Camel(v.ColumnName))
if dt == "int64" { //&& v.ColumnName == this.Pkey
json_def = json_def + ",string"
}
lst.PushBack(fmt.Sprintf("\t%s *%s `gorm:\"column:%s\" json:\"%s\"`", stringutils.Case2Camel(v.ColumnName), dt, col_def, json_def))
}
lst.PushBack("}")
fmt.Println(snbase)
for i := lst.Front(); i != nil; i = i.Next() {
fmt.Println(i.Value)
}
return lst
}
func (this *FactroyPostgres) makeModelBodyGo(columns *[]*metadb.MetadataColumn) *list.List {
lines := list.New()
for _, c := range *columns {
col_comment := fmt.Sprintf("\t/* %s */", c.ColumnComment)
lines.PushBack(col_comment)
dt := c.FindGoType(c.DataType)
col_def := c.ColumnName + ";type:" + c.ColumnType
if c.ColumnName == this.Pkey {
col_def = col_def + ";PRIMARY_KEY"
}
if this.IsMysql() {
col_def = col_def + fmt.Sprintf(";comment:'%s'", c.ColumnComment)
}
//if true || this.Dbtype_mysql {
if len(c.ColumnDefault) > 0 {
if c.IfNumeric() {
col_def = col_def + fmt.Sprintf(";default:%s", c.ColumnDefault)
}
if c.IfString() {
col_def = col_def + fmt.Sprintf(";default:\\'%s\\'", c.ColumnDefault)
}
}
json_def := c.ColumnName
if this.IsMysql() {
//json_def = baseutils.Lcfirst(stringutils.Case2Camel(c.ColumnName))
}
if dt == "int64" { //&& c.ColumnName == this.Pkey
json_def = json_def + ",string"
}
lines.PushBack(fmt.Sprintf("\t%s %s `gorm:\"column:%s\" json:\"%s\"`", stringutils.Case2Camel(c.ColumnName), dt, col_def, json_def))
}
for i := lines.Front(); i != nil; i = i.Next() {
log.Println(i.Value)
}
return lines
}
func (this *FactroyPostgres) makeModelDtoGo(columns *[]metadb.MetadataColumn) *list.List {
lines := list.New()
for _, c := range *columns {
col_comment := fmt.Sprintf("\t/* %s */", c.ColumnComment)
lines.PushBack(col_comment)
dt := c.FindGoType(c.DataType)
col_def := c.ColumnName + ";type:" + c.ColumnType
if c.ColumnName == this.Pkey {
col_def = col_def + ";PRIMARY_KEY"
}
if this.IsMysql() {
col_def = col_def + fmt.Sprintf(";comment:'%s'", c.ColumnComment)
}
if len(c.ColumnDefault) > 0 {
if c.IfNumeric() {
col_def = col_def + fmt.Sprintf(";default:%s", c.ColumnDefault)
}
if c.IfString() {
col_def = col_def + fmt.Sprintf(";default:\\'%s\\'", c.ColumnDefault)
}
}
json_def := c.ColumnName
if dt == "int64" { //&& c.ColumnName == this.Pkey
json_def = json_def + ",string"
}
if dt == "bool" {
dt = "string"
lines.PushBack(fmt.Sprintf("\t%s %s `gorm:\"column:%s\" json:\"%s\"`", stringutils.Case2Camel(c.ColumnName), dt, col_def, json_def))
} else {
lines.PushBack(fmt.Sprintf("\t%s %s `gorm:\"column:%s\" json:\"%s\"`", stringutils.Case2Camel(c.ColumnName), dt, col_def, json_def))
}
}
for i := lines.Front(); i != nil; i = i.Next() {
log.Println(i.Value)
}
return lines
}
func (this *FactroyPostgres) makeModelParamsGo(columns *[]metadb.MetadataColumn) *list.List {
lines := list.New()
for _, c := range *columns {
col_comment := fmt.Sprintf("\t/* %s */", c.ColumnComment)
lines.PushBack(col_comment)
dt := c.FindGoType(c.DataType)
col_def := c.ColumnName + ";type:" + c.ColumnType
if c.ColumnName == this.Pkey {
col_def = col_def + ";PRIMARY_KEY"
}
if this.IsMysql() {
col_def = col_def + fmt.Sprintf(";comment:'%s'", c.ColumnComment)
}
if len(c.ColumnDefault) > 0 {
if c.IfNumeric() {
col_def = col_def + fmt.Sprintf(";default:%s", c.ColumnDefault)
}
if c.IfString() {
col_def = col_def + fmt.Sprintf(";default:\\'%s\\'", c.ColumnDefault)
}
}
json_def := c.ColumnName
if dt == "int64" { //&& c.ColumnName == this.Pkey
json_def = json_def + ",string"
}
if dt == "bool" {
dt = "string"
lines.PushBack(fmt.Sprintf("\t%s *%s `gorm:\"column:%s\" json:\"%s\"`", stringutils.Case2Camel(c.ColumnName), dt, col_def, json_def))
} else {
lines.PushBack(fmt.Sprintf("\t%s *%s `gorm:\"column:%s\" json:\"%s\"`", stringutils.Case2Camel(c.ColumnName), dt, col_def, json_def))
}
}
for i := lines.Front(); i != nil; i = i.Next() {
logrus.Info(i.Value)
}
return lines
}
func (this *FactroyPostgres) BuildModel() *DefineFactors {
var columns = this.FindColumns()
var models = this.makeModelBodyGo(columns) // ms = this.makeModelGo(cs)
return &DefineFactors{
Columns: columns,
Models: models,
}
}
func (this *FactroyPostgres) MakeModelProto() *list.List {
cs := this.FindColumns()
lst := this.makeModelProto(cs)
return lst
}
func (this *FactroyPostgres) MakeModelProtoBody(columns *[]metadb.MetadataColumn) *list.List {
sn := fmt.Sprintf(stringutils.Case2Camel(this.Table))
snbase := this.makeBase(sn)
lst := list.New()
i := 5
for _, v := range *columns {
log.Println(v.String())
dt := this.FindProtoType(v.DataType)
if dt == "" {
dt = "string"
}
lst.PushBack(fmt.Sprintf("\t%s %s = %d;", dt, stringutils.Lcfirst(stringutils.Case2Camel(v.ColumnName)), i))
i++
}
log.Println(snbase)
for i := lst.Front(); i != nil; i = i.Next() {
log.Println(i.Value)
}
return lst
}
func (this *FactroyPostgres) makeModelProto(columns *[]*metadb.MetadataColumn) *list.List {
sn := fmt.Sprintf(stringutils.Case2Camel(this.Table))
snbase := this.makeBase(sn)
lst := list.New()
//lst.PushBack(fmt.Sprintf("type %s%s struct {", Capitalize(tmp.Dbname), Capitalize(tmp.Table)))
lst.PushBack(fmt.Sprintf("message %sProto {", stringutils.UcfirstCase2Camel(stringutils.Capitalize(this.Table))))
i := 1
for _, v := range *columns {
//timeStr :=cd v.Birthday.Format("2006-01-02 15:04:05")
fmt.Println(v.String())
dt := this.FindProtoType(v.DataType)
if dt == "" {
log.Println("")
dt = "string"
}
lst.PushBack(fmt.Sprintf("\t%s %s = %d;", dt, stringutils.Case2Camel(v.ColumnName), i))
i = i + 1
}
lst.PushBack("}")
fmt.Println(snbase)
fmt.Println()
for i := lst.Front(); i != nil; i = i.Next() {
fmt.Println(i.Value)
}
return lst
}
func (this *FactroyPostgres) FindPgPkey(table string) []metadb.MetadataPkinfo {
s := `SELECT
pg_constraint.conname AS pkname,
pg_attribute.attname AS colname,
pg_type.typname AS typename
FROM pg_constraint
INNER JOIN pg_class ON pg_constraint.conrelid = pg_class.oid
INNER JOIN pg_attribute ON pg_attribute.attrelid = pg_class.oid
AND pg_attribute.attnum = pg_constraint.conkey [ 1 ]
INNER JOIN pg_type ON pg_type.oid = pg_attribute.atttypid
WHERE pg_class.relname = '%s'
AND pg_constraint.contype = 'p' `
var pkInfos []metadb.MetadataPkinfo
s = fmt.Sprintf(s, table)
log.Println("Find PKey: " + s)
e := this.funcGetDb().Model(&metadb.MetadataPkinfo{}).Raw(s).Find(&pkInfos).Error
if e != nil {
fmt.Println(e.Error())
}
log.Println("FindPgPkey: \n" + s)
if len(pkInfos) == 0 {
fmt.Println(fmt.Sprintf("pkInfos len=0 无主键(可能表%s不存在!) ", table))
}
log.Println(fmt.Sprintf("pkInfos: %d", len(pkInfos)))
return pkInfos
}
func (this *FactroyPostgres) buildIf(columns *[]metadb.MetadataColumn) *list.List {
lst := list.New()
s := `
if param.Param.%s != nil {
dbc = dbc.Where("%s=?", *param.Param.%s)
}`
for _, v := range *columns {
cc := stringutils.Case2Camel(v.ColumnName)
//timeStr := v.Birthday.Format("2006-01-02 15:04:05")
if v.IfString() {
s = `
if param.Param.%s != nil || *param.Param.%s != "" {
dbc = dbc.Where("%s = ?", *param.Param.%s)
}`
s = fmt.Sprintf(s, cc, cc, v.ColumnName, cc)
} else if v.IfNumeric() {
s = `
if param.Param.%s != nil || *param.Param.%s != 0 {
dbc = dbc.Where("%s=?", *param.Param.%s)
}`
s = fmt.Sprintf(s, cc, cc, v.ColumnName, cc)
} else {
s = `
if param.Param.%s != nil {
dbc = dbc.Where("%s=?", *param.Param.%s)
}`
s = fmt.Sprintf(s, cc, v.ColumnName, cc)
}
lst.PushBack(s)
}
return lst
}
func (this *FactroyPostgres) FindFields(table string, fields string) string {
var metatable = this.FindMetadata(table)
ichublog.Log(metatable.ToPrettyString())
if len(fields) != 0 && fields != "*" {
return fields
}
return metatable.ToFieldsString()
}
func (this *FactroyPostgres) iniDb() {
if this.DbClientDto != nil {
return
}
this.DbClientDto = Cfg.ReadIchubDb()
metacontext.FindBeanMetadataContext().DbType = this.DbClientDto.Dbtype
}
func (this *FactroyPostgres) FindMetadata(table string) *metadb.MetadataTable {
var c, found = metadb.InstMetadataCache.CacheGet(table)
if found {
return c
}
var DbFindMeta = func() *metadb.MetadataTable {
this.iniDb()
this.Table = table
var metadataTable = metadb.NewMetadataTable()
metadataTable.Columns = *this.FindColumns()
metadataTable.TableSchema = this.DbClientDto.Dbname
metadataTable.TableName = table
metadataTable.BuildGoFields()
return metadataTable
}
var meta = DbFindMeta()
//设置cache
metadb.InstMetadataCache.CacheSet(table, meta)
return meta
}
const sql_postgres = `select TABLE_NAME as table_name,
table_catalog as table_schema,
Column_Name as column_name,
udt_name as data_type,
crdb_sql_type as column_type,
character_maximum_length as char_max_len,
'' as column_key ,
column_default as column_default
from information_schema.Columns
where table_catalog ='%s' and table_name='%s'`
func (this *FactroyPostgres) FindColumns() *[]*metadb.MetadataColumn {
var columns []*metadb.MetadataColumn
var sql string
if this.IsMysql() {
sql = fmt.Sprintf(sql_mysql, this.DbClientDto.Dbname, this.Table)
} else {
sql = fmt.Sprintf(sql_postgres, this.DbClientDto.Dbname, this.Table)
}
e := this.funcGetDb().Raw(sql).Find(&columns).Error
if e != nil {
logrus.Error(e.Error())
return &columns
}
if len(columns) == 0 {
logrus.Error(this.Table + " MetadataColumn len =0 (表不存在!)")
return &columns
}
if this.IsMysql() {
for _, v := range columns { //timeStr := v.Birthday.Format("2006-01-02 15:04:05")
if v.ColumnKey == "PRI" || v.ColumnName == "id" {
this.Pkey = v.ColumnName
this.PkeyType = v.DataType
}
if v.IfString() {
this.StringFieldName = v.ColumnName
this.StringFieldLen = v.CharMaxLen
}
}
} else { // pgsql
pks := this.FindPgPkey(this.Table)
log.Println(fmt.Sprintf("pkInfos: %d", len(pks)))
this.Pkey = "id"
this.PkeyType = "int64"
if len(pks) > 0 {
this.Pkey = pks[0].ColName
this.PkeyType = pks[0].TypeName
}
cscomment := this.findPGColumnComment()
for index := range columns { //timeStr := v.Birthday.Format("2006-01-02 15:04:05")
for _, c := range cscomment {
if columns[index].ColumnName == c.ColumnName {
columns[index].ColumnComment = c.ColumnComment
}
}
if columns[index].IfString() {
this.StringFieldName = columns[index].ColumnName
this.StringFieldLen = columns[index].CharMaxLen
}
}
}
return &columns
}
func (this *FactroyPostgres) FindTableComment() {
if this.IsMysql() { //this.TableComment == nil &&
tbls := this.FindTables()
for _, v := range tbls {
if this.Table == v.TableName {
this.TableComment = &v.TableComment
return
}
}
}
if !this.IsMysql() {
tc := this.findPGTableComment()
this.TableComment = &tc.TableComment
}
}
//func (this *FacatroyMysql) CheckTableExist() bool {
// if len(this.MetadataTables) == 0 {
// this.MetadataTables = this.FindTables()
// }
// for _, table := range this.MetadataTables {
// if table.TableName == this.Table {
// return true
// }
// }
// return false
//}
const postgres_findTable = `SELECT table_name as table_name,
table_catalog as table_schema
FROM INFORMATION_SCHEMA.tables
WHERE table_schema='common' AND table_type IN ('BASE TABLE','VIEW')
`
func (this *FactroyPostgres) FindTables() []metadb.MetadataTable {
var tables []metadb.MetadataTable
if this.IsMysql() {
sql := fmt.Sprintf(mysql_findTable, this.DbClientDto.Dbname)
err := this.funcGetDb().Raw(sql).Find(&tables).Error
if err != nil {
panic(err.Error() + " :" + sql)
return []metadb.MetadataTable{}
}
} else {
sql := postgres_findTable
err := this.funcGetDb().Raw(sql).Find(&tables).Error
if err != nil {
panic(err.Error() + " :" + sql)
}
}
return tables
}
func (this *FactroyPostgres) FindGoType(fieldType string) (goType string) {
goType = metacontext.FindBeanMetadataContext().FindGoType(fieldType)
return
}
func (this *FactroyPostgres) FindProtoType(fieldType string) (pbType string) {
pbType = metacontext.FindBeanMetadataContext().FindProtoType(fieldType)
return
}
1
https://gitee.com/ichub/gomini.git
git@gitee.com:ichub/gomini.git
ichub
gomini
gomini
36220ecd33b4

搜索帮助