feat 调整 mysql 、pgsql 初始化数据; 完善pgsql 兼容性,适配代码生成逻辑

This commit is contained in:
孟帅
2025-11-08 12:40:03 +08:00
parent 3989996448
commit a7234bc330
49 changed files with 5360 additions and 5201 deletions

View File

@@ -9,6 +9,7 @@ import (
"context"
"errors"
"fmt"
"hotgo/internal/consts"
"hotgo/internal/dao"
"math"
"strings"
@@ -35,6 +36,23 @@ CREATE TABLE IF NOT EXISTS %s (
PRIMARY KEY (id) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8 COLLATE = utf8_general_ci COMMENT = '管理员_casbin权限表' ROW_FORMAT = Dynamic;
`
createPolicyTablePgSql = `CREATE TABLE IF NOT EXISTS "public"."%s" (
"id" int8 NOT NULL DEFAULT nextval('hg_admin_role_casbin_id_seq'::regclass),
"p_type" varchar(64) COLLATE "pg_catalog"."default",
"v0" varchar(256) COLLATE "pg_catalog"."default",
"v1" varchar(256) COLLATE "pg_catalog"."default",
"v2" varchar(256) COLLATE "pg_catalog"."default",
"v3" varchar(256) COLLATE "pg_catalog"."default",
"v4" varchar(256) COLLATE "pg_catalog"."default",
"v5" varchar(256) COLLATE "pg_catalog"."default",
CONSTRAINT "hg_admin_role_casbin_pkey" PRIMARY KEY ("id")
)
;
ALTER TABLE "public"."%s"
OWNER TO "postgres";
COMMENT ON TABLE "public"."%s" IS '管理员_casbin权限表';`
)
type (
@@ -106,6 +124,10 @@ func (a *adapter) model() *gdb.Model {
// create a policy table when it's not exists.
func (a *adapter) createPolicyTable() (err error) {
if a.db.GetConfig().Type == consts.DBPgsql {
_, err = a.db.Exec(context.TODO(), fmt.Sprintf(createPolicyTablePgSql, a.table, a.table, a.table))
return
}
_, err = a.db.Exec(context.TODO(), fmt.Sprintf(createPolicyTableSql, a.table))
return
}
@@ -154,7 +176,7 @@ func (a *adapter) SavePolicy(model model.Model) (err error) {
}
if count := len(policyRules); count > 0 {
if _, err = a.model().OmitEmptyData().Insert(policyRules); err != nil {
if _, err = a.model().OmitEmptyData().FieldsEx(policyColumnsName.ID).Insert(policyRules); err != nil {
return
}
}
@@ -163,7 +185,7 @@ func (a *adapter) SavePolicy(model model.Model) (err error) {
// AddPolicy adds a policy rule to the storage.
func (a *adapter) AddPolicy(sec string, ptype string, rule []string) (err error) {
_, err = a.model().OmitEmptyData().Insert(a.buildPolicyRule(ptype, rule))
_, err = a.model().OmitEmptyData().FieldsEx(policyColumnsName.ID).Insert(a.buildPolicyRule(ptype, rule))
return
}
@@ -179,7 +201,7 @@ func (a *adapter) AddPolicies(sec string, ptype string, rules [][]string) (err e
policyRules = append(policyRules, a.buildPolicyRule(ptype, rule))
}
_, err = a.model().OmitEmptyData().Insert(policyRules)
_, err = a.model().OmitEmptyData().FieldsEx(policyColumnsName.ID).Insert(policyRules)
return
}

View File

@@ -11,7 +11,7 @@ import (
//_ "github.com/gogf/gf/contrib/drivers/mssql/v2"
_ "github.com/gogf/gf/contrib/drivers/mysql/v2"
//_ "github.com/gogf/gf/contrib/drivers/oracle/v2"
//_ "github.com/gogf/gf/contrib/drivers/pgsql/v2"
_ "github.com/gogf/gf/contrib/drivers/pgsql/v2"
//_ "github.com/gogf/gf/contrib/drivers/sqlite/v2"
// do not add dm in cli pre-compilation,

View File

@@ -8,24 +8,72 @@ package views
import (
"context"
"fmt"
"strings"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gconv"
"hotgo/internal/consts"
"hotgo/internal/library/hggen/internal/cmd/gendao"
"hotgo/internal/model/input/sysin"
"strings"
)
// DoTableColumns 获取指定表生成字段列表
func DoTableColumns(ctx context.Context, in *sysin.GenCodesColumnListInp, config gendao.CGenDaoInput) (fields []*sysin.GenCodesColumnListModel, err error) {
var (
sql = "select ORDINAL_POSITION as `id`, COLUMN_NAME as `name`, COLUMN_COMMENT as `dc`, DATA_TYPE as `dataType`, COLUMN_TYPE as `sqlType`, CHARACTER_MAXIMUM_LENGTH as `length`, IS_NULLABLE as `isAllowNull`, COLUMN_DEFAULT as `defaultValue`, COLUMN_KEY as `index`, EXTRA as `extra` from information_schema.COLUMNS where TABLE_SCHEMA = '%s' and TABLE_NAME = '%s' ORDER BY `id` ASC"
sql string
conf = g.DB(in.Name).GetConfig()
)
err = g.DB(in.Name).Ctx(ctx).Raw(fmt.Sprintf(sql, conf.Name, in.Table)).Scan(&fields)
// 根据数据库类型使用不同的SQL
if conf.Type == consts.DBPgsql {
// PostgreSQL: 使用pg_catalog查询列详细信息
sql = `
SELECT
a.attnum as id,
a.attname as name,
COALESCE(col_description(a.attrelid, a.attnum), '') as dc,
t.typname as dataType,
CASE
WHEN a.atttypmod > 0 THEN t.typname || '(' || (a.atttypmod - 4) || ')'
ELSE t.typname
END as sqlType,
CASE
WHEN a.atttypmod > 0 THEN a.atttypmod - 4
ELSE NULL
END as length,
CASE WHEN a.attnotnull THEN 'NO' ELSE 'YES' END as isAllowNull,
pg_get_expr(ad.adbin, ad.adrelid) as defaultValue,
CASE
WHEN pk.contype = 'p' THEN 'PRI'
WHEN uk.contype = 'u' THEN 'UNI'
ELSE ''
END as "index",
CASE
WHEN ad.adbin IS NOT NULL AND ad.adbin LIKE '%nextval%' THEN 'auto_increment'
ELSE ''
END as extra
FROM pg_attribute a
JOIN pg_class c ON a.attrelid = c.oid
JOIN pg_namespace n ON c.relnamespace = n.oid
JOIN pg_type t ON a.atttypid = t.oid
LEFT JOIN pg_attrdef ad ON a.attrelid = ad.adrelid AND a.attnum = ad.adnum
LEFT JOIN pg_constraint pk ON pk.conrelid = c.oid AND pk.contype = 'p' AND a.attnum = ANY(pk.conkey)
LEFT JOIN pg_constraint uk ON uk.conrelid = c.oid AND uk.contype = 'u' AND a.attnum = ANY(uk.conkey)
WHERE n.nspname = 'public'
AND c.relname = '%s'
AND a.attnum > 0
AND NOT a.attisdropped
ORDER BY a.attnum`
sql = fmt.Sprintf(sql, in.Table)
} else {
// MySQL: 使用information_schema.COLUMNS
sql = fmt.Sprintf("SELECT ORDINAL_POSITION as id, COLUMN_NAME as name, COLUMN_COMMENT as dc, DATA_TYPE as dataType, COLUMN_TYPE as sqlType, CHARACTER_MAXIMUM_LENGTH as length, IS_NULLABLE as isAllowNull, COLUMN_DEFAULT as defaultValue, COLUMN_KEY as `index`, EXTRA as extra FROM information_schema.COLUMNS WHERE TABLE_SCHEMA = '%s' AND TABLE_NAME = '%s' ORDER BY id ASC", conf.Name, in.Table)
}
err = g.DB(in.Name).Ctx(ctx).Raw(sql).Scan(&fields)
if err != nil {
return nil, err
}

View File

@@ -9,12 +9,15 @@ package hgorm
import (
"context"
"fmt"
"strings"
"hotgo/utility/convert"
"hotgo/utility/db"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/text/gstr"
"hotgo/utility/convert"
"strings"
)
type daoInstance interface {
@@ -35,7 +38,8 @@ func LeftJoin(m *gdb.Model, masterTable, masterField, joinTable, alias, onField
// GenJoinOnRelation 生成关联表关联条件
func GenJoinOnRelation(masterTable, masterField, joinTable, alias, onField string) []string {
relation := fmt.Sprintf("`%s`.`%s` = `%s`.`%s`", alias, onField, masterTable, masterField)
q := db.GetQuoteChar()
relation := fmt.Sprintf("%s%s%s.%s%s%s = %s%s%s.%s%s%s", q, alias, q, q, onField, q, q, masterTable, q, q, masterField, q)
return []string{joinTable, alias, relation}
}
@@ -62,7 +66,7 @@ func JoinFields(ctx context.Context, entity interface{}, dao daoInstance, as str
field := gstr.CaseSnakeFirstUpper(gstr.StrEx(v, as))
if _, ok := fields[field]; ok {
columns = append(columns, fmt.Sprintf("`%s`.`%s` as `%s`", dao.Table(), field, v))
columns = append(columns, db.QuoteFieldAs(dao.Table(), field, v))
}
}
@@ -117,7 +121,7 @@ func GenJoinSelect(ctx context.Context, entity interface{}, dao daoInstance, joi
jd, joinField := getJoinAttribute(field)
if jd != nil {
if _, ok := jd.fields[joinField]; ok {
tmpFields = append(tmpFields, fmt.Sprintf("`%s`.`%s` as `%s`", jd.Alias, joinField, field))
tmpFields = append(tmpFields, db.QuoteFieldAs(jd.Alias, joinField, field))
continue
}
}
@@ -125,7 +129,7 @@ func GenJoinSelect(ctx context.Context, entity interface{}, dao daoInstance, joi
// 主表
originalField := gstr.CaseSnakeFirstUpper(field)
if _, ok := masterFields[originalField]; ok {
tmpFields = append(tmpFields, fmt.Sprintf("`%s`.`%s`", dao.Table(), originalField))
tmpFields = append(tmpFields, db.QuoteField(dao.Table(), originalField))
continue
}
}
@@ -143,7 +147,7 @@ func GetPkField(ctx context.Context, dao daoInstance) (string, error) {
}
for _, field := range fields {
if strings.ToUpper(field.Key) == "PRI" {
if strings.ToUpper(field.Key) == "PRI" {
return field.Name, nil
}
}

View File

@@ -6,16 +6,18 @@
package handler
import (
"fmt"
"regexp"
"hotgo/internal/consts"
"hotgo/internal/model/input/form"
"hotgo/utility/convert"
"hotgo/utility/db"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/text/gregex"
"github.com/gogf/gf/v2/text/gstr"
"github.com/gogf/gf/v2/util/gutil"
"hotgo/internal/consts"
"hotgo/internal/model/input/form"
"hotgo/utility/convert"
"regexp"
)
// ISorter 排序器接口实现该接口即可使用Handler匹配排序支持多字段排序
@@ -62,7 +64,7 @@ func Sorter(in ISorter) func(m *gdb.Model) *gdb.Model {
if len(sorter2) > 0 {
sorter2 = mappingAndFilterToTableFields(fds, sorter2)
for _, v := range sorter2 {
v.ColumnKey = fmt.Sprintf("`%v`.`%v`", as, v.ColumnKey)
v.ColumnKey = db.QuoteField(as, v.ColumnKey)
}
newSorters = append(newSorters, sorter2...)
}
@@ -71,7 +73,7 @@ func Sorter(in ISorter) func(m *gdb.Model) *gdb.Model {
// 移除关联表字段
sorters = mappingAndFilterToTableFields(fields, removeSorterIndexes(sorters, removeIndex))
for _, v := range sorters {
v.ColumnKey = fmt.Sprintf("`%v`.`%v`", masterTable, v.ColumnKey)
v.ColumnKey = db.QuoteField(masterTable, v.ColumnKey)
}
sorters = append(newSorters, sorters...)
@@ -79,7 +81,7 @@ func Sorter(in ISorter) func(m *gdb.Model) *gdb.Model {
// 单表
sorters = mappingAndFilterToTableFields(fields, sorters)
for _, v := range sorters {
v.ColumnKey = fmt.Sprintf("`%v`.`%v`", masterTable, v.ColumnKey)
v.ColumnKey = db.QuoteField(masterTable, v.ColumnKey)
}
}
@@ -123,11 +125,11 @@ func Sorter(in ISorter) func(m *gdb.Model) *gdb.Model {
if len(aliases) > 0 {
for as, table := range aliases {
if table == masterTable {
return m.OrderDesc(fmt.Sprintf("`%v`.`%v`", as, pk))
return m.OrderDesc(db.QuoteField(as, pk))
}
}
}
return m.OrderDesc(fmt.Sprintf("`%v`.`%v`", masterTable, pk))
return m.OrderDesc(db.QuoteField(masterTable, pk))
}
}