暫無描述
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.

table_definition.go 10KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446
  1. package sqldef
  2. import (
  3. "fmt"
  4. "strings"
  5. "sync"
  6. "git.x2erp.com/qdy/go-db/sqldef/generators"
  7. )
  8. // 数据类型常量
  9. const (
  10. TypeVarchar = "VARCHAR"
  11. TypeChar = "CHAR"
  12. TypeText = "TEXT"
  13. TypeInt = "INT"
  14. TypeBigInt = "BIGINT"
  15. TypeTinyInt = "TINYINT"
  16. TypeDecimal = "DECIMAL"
  17. TypeFloat = "FLOAT"
  18. TypeDouble = "DOUBLE"
  19. TypeBool = "BOOL"
  20. TypeDateTime = "DATETIME"
  21. TypeTimestamp = "TIMESTAMP"
  22. TypeDate = "DATE"
  23. TypeTime = "TIME"
  24. TypeBlob = "BLOB"
  25. TypeJson = "JSON"
  26. )
  27. // Column 列定义
  28. type Column struct {
  29. name string
  30. chineseName string // 新增:字段中文名称
  31. aliases []string // 新增:字段别名列表
  32. sqlType string
  33. comment string
  34. options []string
  35. defaultValue string // 新增:默认值
  36. }
  37. // ColumnBuilder 列构建器
  38. type ColumnBuilder struct {
  39. table *TableBuilder
  40. column Column
  41. }
  42. // TableBuilder 表构建器
  43. type TableBuilder struct {
  44. name string
  45. chineseName string // 新增:表中文名称
  46. aliases []string // 新增:表别名列表
  47. comment string
  48. columns []Column
  49. indexes []string
  50. }
  51. // Registry 注册表(懒加载)
  52. type Registry struct {
  53. tables map[string]generators.TableDDL
  54. mu sync.RWMutex
  55. once sync.Once
  56. regFns []func(*Registry)
  57. }
  58. var globalRegistry = &Registry{
  59. tables: make(map[string]generators.TableDDL),
  60. }
  61. // AddRegistration 添加注册函数
  62. func AddRegistration(fn func(*Registry)) {
  63. globalRegistry.regFns = append(globalRegistry.regFns, fn)
  64. }
  65. func (r *Registry) lazyInit() {
  66. r.mu.Lock()
  67. defer r.mu.Unlock()
  68. for _, fn := range r.regFns {
  69. fn(r)
  70. }
  71. }
  72. func (r *Registry) ensureInit() {
  73. r.once.Do(r.lazyInit)
  74. }
  75. // RegisterTable 注册表
  76. func (r *Registry) RegisterTable(table generators.TableDDL) {
  77. if table.Name != "" {
  78. r.tables[table.Name] = table
  79. }
  80. }
  81. // GetAll 获取所有表定义
  82. func GetAll() []generators.TableDDL {
  83. globalRegistry.ensureInit()
  84. globalRegistry.mu.RLock()
  85. defer globalRegistry.mu.RUnlock()
  86. result := make([]generators.TableDDL, 0, len(globalRegistry.tables))
  87. for _, table := range globalRegistry.tables {
  88. result = append(result, table)
  89. }
  90. return result
  91. }
  92. // Get 获取表定义
  93. func Get(tableName string) (generators.TableDDL, bool) {
  94. globalRegistry.ensureInit()
  95. globalRegistry.mu.RLock()
  96. defer globalRegistry.mu.RUnlock()
  97. table, exists := globalRegistry.tables[tableName]
  98. return table, exists
  99. }
  100. // ================== TableBuilder 表构建器 ==================
  101. // NewTable 创建新表
  102. func NewTable(name string, comment ...string) *TableBuilder {
  103. tb := &TableBuilder{name: name}
  104. if len(comment) > 0 {
  105. tb.comment = comment[0]
  106. }
  107. return tb
  108. }
  109. // ================== TableBuilder 扩展方法 ==================
  110. func (t *TableBuilder) ChineseName(name string) *TableBuilder {
  111. t.chineseName = name
  112. return t
  113. }
  114. func (t *TableBuilder) Aliases(aliases ...string) *TableBuilder {
  115. t.aliases = aliases
  116. return t
  117. }
  118. func (t *TableBuilder) Alias(alias string) *TableBuilder {
  119. t.aliases = append(t.aliases, alias)
  120. return t
  121. }
  122. // ================== 列定义方法 ==================
  123. // 默认64位长度
  124. func (t *TableBuilder) ID(name string, length ...int) *ColumnBuilder {
  125. size := 64
  126. if len(length) > 0 {
  127. size = length[0]
  128. }
  129. return t.column(name, TypeVarchar, size).PrimaryKey()
  130. }
  131. func (t *TableBuilder) String(name string, length int) *ColumnBuilder {
  132. return t.column(name, TypeVarchar, length)
  133. }
  134. func (t *TableBuilder) Char(name string, length int) *ColumnBuilder {
  135. return t.column(name, TypeChar, length)
  136. }
  137. func (t *TableBuilder) Text(name string) *ColumnBuilder {
  138. return t.column(name, TypeText, 0)
  139. }
  140. func (t *TableBuilder) Int(name string) *ColumnBuilder {
  141. return t.column(name, TypeInt, 0)
  142. }
  143. func (t *TableBuilder) TinyInt(name string) *ColumnBuilder {
  144. return t.column(name, TypeTinyInt, 0)
  145. }
  146. func (t *TableBuilder) BigInt(name string) *ColumnBuilder {
  147. return t.column(name, TypeBigInt, 0)
  148. }
  149. func (t *TableBuilder) Bool(name string) *ColumnBuilder {
  150. return t.column(name, TypeBool, 0)
  151. }
  152. func (t *TableBuilder) JSON(name string) *ColumnBuilder {
  153. return t.column(name, TypeJson, 0)
  154. }
  155. func (t *TableBuilder) Decimal(name string, precision, scale int) *ColumnBuilder {
  156. col := &ColumnBuilder{
  157. table: t,
  158. column: Column{
  159. name: name,
  160. sqlType: fmt.Sprintf("%s(%d,%d)", TypeDecimal, precision, scale),
  161. },
  162. }
  163. return col
  164. }
  165. func (t *TableBuilder) Float(name string) *ColumnBuilder {
  166. return t.column(name, TypeFloat, 0)
  167. }
  168. func (t *TableBuilder) Double(name string) *ColumnBuilder {
  169. return t.column(name, TypeDouble, 0)
  170. }
  171. func (t *TableBuilder) DateTime(name string) *ColumnBuilder {
  172. return t.column(name, TypeDateTime, 0)
  173. }
  174. func (t *TableBuilder) Timestamp(name string) *ColumnBuilder {
  175. return t.column(name, TypeTimestamp, 0)
  176. }
  177. func (t *TableBuilder) Time(name string) *ColumnBuilder {
  178. return t.column(name, TypeTime, 0)
  179. }
  180. func (t *TableBuilder) Date(name string) *ColumnBuilder {
  181. return t.column(name, TypeDate, 0)
  182. }
  183. func (t *TableBuilder) Blob(name string) *ColumnBuilder {
  184. return t.column(name, TypeBlob, 0)
  185. }
  186. // 私有辅助方法
  187. func (t *TableBuilder) column(name string, dataType string, length int) *ColumnBuilder {
  188. sqlType := dataType
  189. if length > 0 {
  190. sqlType = fmt.Sprintf("%s(%d)", dataType, length)
  191. }
  192. col := &ColumnBuilder{
  193. table: t,
  194. column: Column{
  195. name: name,
  196. sqlType: sqlType,
  197. },
  198. }
  199. return col
  200. }
  201. // ================== 列构建器方法 ==================
  202. func (c *ColumnBuilder) NotNull() *ColumnBuilder {
  203. c.column.options = append(c.column.options, "NOT NULL")
  204. return c
  205. }
  206. func (c *ColumnBuilder) Default(value string) *ColumnBuilder {
  207. c.column.defaultValue = value
  208. return c
  209. }
  210. func (c *ColumnBuilder) PrimaryKey() *ColumnBuilder {
  211. c.column.options = append(c.column.options, "PRIMARY KEY")
  212. return c
  213. }
  214. func (c *ColumnBuilder) AutoIncrement() *ColumnBuilder {
  215. c.column.options = append(c.column.options, "AUTO_INCREMENT")
  216. return c
  217. }
  218. func (c *ColumnBuilder) Unique() *ColumnBuilder {
  219. c.column.options = append(c.column.options, "UNIQUE")
  220. return c
  221. }
  222. func (c *ColumnBuilder) Comment(comment string) *ColumnBuilder {
  223. c.column.comment = comment
  224. return c
  225. }
  226. func (c *ColumnBuilder) ChineseName(name string) *ColumnBuilder {
  227. c.column.chineseName = name
  228. return c
  229. }
  230. func (c *ColumnBuilder) Aliases(aliases ...string) *ColumnBuilder {
  231. c.column.aliases = aliases
  232. return c
  233. }
  234. func (c *ColumnBuilder) Alias(alias string) *ColumnBuilder {
  235. c.column.aliases = append(c.column.aliases, alias)
  236. return c
  237. }
  238. // End 结束列定义,返回TableBuilder继续定义其他列
  239. func (c *ColumnBuilder) End() *TableBuilder {
  240. c.table.columns = append(c.table.columns, c.column)
  241. return c.table
  242. }
  243. // ================== 索引方法 ==================
  244. func (t *TableBuilder) AddIndex(name string, columns ...string) *TableBuilder {
  245. idx := fmt.Sprintf("INDEX %s (%s)", name, strings.Join(columns, ", "))
  246. t.indexes = append(t.indexes, idx)
  247. return t
  248. }
  249. func (t *TableBuilder) AddUniqueIndex(name string, columns ...string) *TableBuilder {
  250. idx := fmt.Sprintf("UNIQUE INDEX %s (%s)", name, strings.Join(columns, ", "))
  251. t.indexes = append(t.indexes, idx)
  252. return t
  253. }
  254. // Build 构建表定义,包含完整的Schema信息
  255. func (t *TableBuilder) Build() generators.TableDDL {
  256. // 构建列Schema
  257. columns := make([]generators.ColumnSchema, 0, len(t.columns))
  258. for _, col := range t.columns {
  259. // 解析列类型
  260. colType, length, precision, scale := parseColumnType(col.sqlType)
  261. // 提取默认值
  262. var defaultValue string
  263. var options []string
  264. for _, opt := range col.options {
  265. if strings.HasPrefix(opt, "DEFAULT ") {
  266. defaultValue = strings.TrimPrefix(opt, "DEFAULT ")
  267. } else {
  268. options = append(options, opt)
  269. }
  270. }
  271. columns = append(columns, generators.ColumnSchema{
  272. Name: col.name,
  273. ChineseName: col.chineseName,
  274. Aliases: col.aliases,
  275. Type: colType,
  276. Length: length,
  277. Precision: precision,
  278. Scale: scale,
  279. Comment: col.comment,
  280. Options: options,
  281. Default: defaultValue,
  282. })
  283. }
  284. // 构建索引Schema
  285. indexes := make([]generators.IndexSchema, 0, len(t.indexes))
  286. for _, idx := range t.indexes {
  287. // 解析索引字符串,例如: "INDEX idx_name (col1, col2)" 或 "UNIQUE INDEX idx_name (col1, col2)"
  288. indexName, isUnique, columns := parseIndex(idx)
  289. if indexName != "" && len(columns) > 0 {
  290. indexes = append(indexes, generators.IndexSchema{
  291. Name: indexName,
  292. Columns: columns,
  293. Unique: isUnique,
  294. })
  295. }
  296. }
  297. return generators.TableDDL{
  298. Name: t.name,
  299. Comment: t.comment,
  300. Schema: &generators.TableSchema{
  301. Name: t.name,
  302. ChineseName: t.chineseName,
  303. Aliases: t.aliases,
  304. Comment: t.comment,
  305. Columns: columns,
  306. Indexes: indexes,
  307. },
  308. }
  309. }
  310. // parseColumnType 解析列类型字符串
  311. func parseColumnType(sqlType string) (colType string, length, precision, scale int) {
  312. sqlType = strings.ToUpper(strings.TrimSpace(sqlType))
  313. // 处理带括号的类型,如 VARCHAR(255), DECIMAL(10,2)
  314. if strings.Contains(sqlType, "(") {
  315. openParen := strings.Index(sqlType, "(")
  316. closeParen := strings.Index(sqlType, ")")
  317. colType = sqlType[:openParen]
  318. params := strings.TrimSpace(sqlType[openParen+1 : closeParen])
  319. switch colType {
  320. case "DECIMAL":
  321. if strings.Contains(params, ",") {
  322. parts := strings.Split(params, ",")
  323. if len(parts) == 2 {
  324. fmt.Sscanf(parts[0], "%d", &precision)
  325. fmt.Sscanf(parts[1], "%d", &scale)
  326. }
  327. }
  328. case "VARCHAR", "CHAR":
  329. fmt.Sscanf(params, "%d", &length)
  330. default:
  331. fmt.Sscanf(params, "%d", &length)
  332. }
  333. } else {
  334. colType = sqlType
  335. }
  336. return
  337. }
  338. // parseIndex 解析索引字符串
  339. func parseIndex(indexStr string) (name string, isUnique bool, columns []string) {
  340. indexStr = strings.TrimSpace(indexStr)
  341. // 检查是否是唯一索引
  342. if strings.HasPrefix(indexStr, "UNIQUE INDEX") {
  343. isUnique = true
  344. indexStr = strings.TrimPrefix(indexStr, "UNIQUE INDEX ")
  345. } else if strings.HasPrefix(indexStr, "INDEX") {
  346. indexStr = strings.TrimPrefix(indexStr, "INDEX ")
  347. } else {
  348. return "", false, nil
  349. }
  350. // 分割索引名和列
  351. parts := strings.Split(indexStr, " ")
  352. if len(parts) < 2 {
  353. return "", false, nil
  354. }
  355. name = parts[0]
  356. // 提取列,如 (col1, col2)
  357. colsPart := strings.Join(parts[1:], " ")
  358. colsPart = strings.Trim(colsPart, "()")
  359. columns = strings.Split(colsPart, ", ")
  360. return
  361. }
  362. // Register 快捷方法:直接注册表
  363. func (t *TableBuilder) Register() {
  364. table := t.Build()
  365. AddRegistration(func(r *Registry) {
  366. r.RegisterTable(table)
  367. })
  368. }