| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213 |
- package sqldef
-
- import (
- "fmt"
- "strings"
- "time"
- "unicode/utf8"
-
- "git.x2erp.com/qdy/go-db/sqldef/generators"
- )
-
- // DictSQLGenerator 字典表SQL生成器
- type DictSQLGenerator struct {
- TableIDPrefix string // 表ID前缀,如 "TBL"
- ColumnIDPrefix string // 字段ID前缀,如 "COL"
- }
-
- // NewDictSQLGenerator 创建生成器
- func NewDictSQLGenerator() *DictSQLGenerator {
- return &DictSQLGenerator{
- TableIDPrefix: "TBL",
- ColumnIDPrefix: "COL",
- }
- }
-
- // DictSQLs 字典表SQL集合
- type DictSQLs struct {
- TableSQL string // 主表SQL
- ColumnSQLs map[string]string // 字段名 -> SQL映射
- }
-
- // GenerateDictSQLsFromTable 从TableDDL生成字典表SQL
- func (gen *DictSQLGenerator) GenerateDictSQLsFromTable(table generators.TableDDL) (*DictSQLs, error) {
- if table.Schema == nil {
- return nil, fmt.Errorf("表 %s 没有Schema信息", table.Name)
- }
-
- // 生成表ID
- tableID := gen.generateTableID(table.Name)
-
- // 1. 生成主表SQL
- tableSQL := gen.generateMainTableSQL(tableID, table)
-
- // 2. 生成子表SQL映射
- columnSQLs := gen.generateColumnSQLs(tableID, table.Schema.Columns)
-
- return &DictSQLs{
- TableSQL: tableSQL,
- ColumnSQLs: columnSQLs,
- }, nil
- }
-
- // GenerateDictSQLsFromRegistry 从注册表中获取所有表的字典SQL
- func (gen *DictSQLGenerator) GenerateDictSQLsFromRegistry() (map[string]*DictSQLs, error) {
- globalRegistry.ensureInit()
-
- globalRegistry.mu.RLock()
- defer globalRegistry.mu.RUnlock()
-
- result := make(map[string]*DictSQLs)
-
- for tableName, tableDDL := range globalRegistry.tables {
- sqls, err := gen.GenerateDictSQLsFromTable(tableDDL)
- if err != nil {
- return nil, fmt.Errorf("生成表 %s 的字典SQL失败: %w", tableName, err)
- }
- result[tableName] = sqls
- }
-
- return result, nil
- }
-
- // generateTableID 生成表ID
- func (gen *DictSQLGenerator) generateTableID(tableName string) string {
- // 使用表名首字母大写 + 时间戳
- timestamp := time.Now().UnixNano() / 1000000 // 毫秒
- firstChar, _ := utf8.DecodeRuneInString(tableName)
- if firstChar == utf8.RuneError {
- firstChar = 'T'
- }
-
- return fmt.Sprintf("%s%c%06d", gen.TableIDPrefix, firstChar, timestamp%1000000)
- }
-
- // generateMainTableSQL 生成主表SQL
- func (gen *DictSQLGenerator) generateMainTableSQL(tableID string, table generators.TableDDL) string {
- // 转义表注释中的单引号
- comment := strings.ReplaceAll(table.Comment, "'", "''")
-
- sql := fmt.Sprintf("INSERT INTO dict_table (table_id, table_name, table_comment, created_at) VALUES ('%s', '%s', '%s', NOW());",
- tableID, table.Name, comment)
-
- return sql
- }
-
- // generateColumnSQLs 生成子表SQL映射
- func (gen *DictSQLGenerator) generateColumnSQLs(tableID string, columns []generators.ColumnSchema) map[string]string {
- sqlMap := make(map[string]string)
-
- for i, column := range columns {
- // 生成字段ID
- columnID := gen.generateColumnID(tableID, column.Name, i)
-
- // 转义字段注释中的单引号
- comment := strings.ReplaceAll(column.Comment, "'", "''")
-
- // 生成字段类型字符串
- columnType := gen.generateColumnTypeString(column)
-
- // 判断是否可为空
- isNullable := "1" // true
- if gen.isNotNullColumn(column.Options) {
- isNullable = "0" // false
- }
-
- // 处理默认值
- defaultValue := gen.formatDefaultValue(column.Default)
-
- // 判断是否为主键
- isPrimaryKey := "0" // false
- if gen.isPrimaryKeyColumn(column.Options) {
- isPrimaryKey = "1" // true
- }
-
- sql := fmt.Sprintf("INSERT INTO dict_column (column_id, table_id, column_name, column_type, column_comment, is_nullable, column_default, sort_order, created_at, is_primary_key) VALUES ('%s', '%s', '%s', '%s', '%s', %s, %s, %d, NOW(), %s);",
- columnID, tableID, column.Name, columnType, comment, isNullable, defaultValue, i, isPrimaryKey)
-
- sqlMap[column.Name] = sql
- }
-
- return sqlMap
- }
-
- // generateColumnID 生成字段ID
- func (gen *DictSQLGenerator) generateColumnID(tableID string, columnName string, index int) string {
- // 使用表ID + 字段名首字母 + 序号
- firstChar, _ := utf8.DecodeRuneInString(columnName)
- if firstChar == utf8.RuneError {
- firstChar = 'C'
- }
-
- return fmt.Sprintf("%s%c%02d", gen.ColumnIDPrefix, firstChar, index)
- }
-
- // generateColumnTypeString 生成字段类型字符串
- func (gen *DictSQLGenerator) generateColumnTypeString(column generators.ColumnSchema) string {
- switch column.Type {
- case TypeVarchar:
- return fmt.Sprintf("VARCHAR(%d)", column.Length)
- case TypeChar:
- return fmt.Sprintf("CHAR(%d)", column.Length)
- case TypeDecimal:
- return fmt.Sprintf("DECIMAL(%d,%d)", column.Precision, column.Scale)
- case TypeInt, TypeBigInt, TypeTinyInt:
- return column.Type
- case TypeDateTime, TypeTimestamp, TypeDate, TypeTime:
- return column.Type
- case TypeText:
- return "TEXT"
- case TypeBool:
- return "BOOL"
- case TypeJson:
- return "JSON"
- case TypeBlob:
- return "BLOB"
- case TypeFloat:
- return "FLOAT"
- case TypeDouble:
- return "DOUBLE"
- default:
- return column.Type
- }
- }
-
- // isNotNullColumn 判断是否为NOT NULL列
- func (gen *DictSQLGenerator) isNotNullColumn(options []string) bool {
- for _, opt := range options {
- if strings.EqualFold(opt, "NOT NULL") {
- return true
- }
- }
- return false
- }
-
- // isPrimaryKeyColumn 判断是否为主键列
- func (gen *DictSQLGenerator) isPrimaryKeyColumn(options []string) bool {
- for _, opt := range options {
- if strings.EqualFold(opt, "PRIMARY KEY") {
- return true
- }
- }
- return false
- }
-
- // formatDefaultValue 格式化默认值
- func (gen *DictSQLGenerator) formatDefaultValue(defaultValue string) string {
- if defaultValue == "" {
- return "NULL"
- }
-
- // 如果是 CURRENT_TIMESTAMP 等函数,直接使用
- upperValue := strings.ToUpper(defaultValue)
- if strings.Contains(upperValue, "CURRENT_TIMESTAMP") ||
- strings.Contains(upperValue, "NULL") ||
- strings.Contains(upperValue, "TRUE") ||
- strings.Contains(upperValue, "FALSE") {
- return fmt.Sprintf("'%s'", defaultValue)
- }
-
- // 其他情况需要转义单引号
- escapedValue := strings.ReplaceAll(defaultValue, "'", "''")
- return fmt.Sprintf("'%s'", escapedValue)
- }
|