Nessuna descrizione
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.

doris.go 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188
  1. package generators
  2. import (
  3. "fmt"
  4. "strings"
  5. )
  6. // DorisGenerator Doris SQL生成器
  7. type DorisGenerator struct{}
  8. // NewDorisGenerator 创建Doris生成器实例
  9. func NewDorisGenerator() *DorisGenerator {
  10. return &DorisGenerator{}
  11. }
  12. func (dg *DorisGenerator) DBType() string {
  13. return "doris"
  14. }
  15. func (dg *DorisGenerator) TableExistsSQL(tableName string) string {
  16. return fmt.Sprintf(
  17. "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = DATABASE() AND table_name = '%s'",
  18. tableName,
  19. )
  20. }
  21. func (dg *DorisGenerator) DropTableSQL(tableName string) string {
  22. return fmt.Sprintf("DROP TABLE IF EXISTS %s", tableName)
  23. }
  24. func (dg *DorisGenerator) GenerateCreateTable(table TableDDL) string {
  25. if table.Schema == nil {
  26. return ""
  27. }
  28. var sql strings.Builder
  29. var primaryKeyColumns []string
  30. // 表头
  31. sql.WriteString(fmt.Sprintf("CREATE TABLE IF NOT EXISTS %s (\n", table.Name))
  32. // 列定义 - 第一遍收集主键列
  33. for _, col := range table.Schema.Columns {
  34. for _, opt := range col.Options {
  35. if strings.ToUpper(opt) == "PRIMARY KEY" {
  36. primaryKeyColumns = append(primaryKeyColumns, col.Name)
  37. break
  38. }
  39. }
  40. }
  41. // 列定义 - 第二遍生成列定义
  42. for i, col := range table.Schema.Columns {
  43. colDef := fmt.Sprintf(" %s %s", col.Name, dg.getDorisType(col))
  44. // 处理列选项,过滤掉 PRIMARY KEY(不在列级定义)
  45. for _, opt := range col.Options {
  46. upperOpt := strings.ToUpper(opt)
  47. if upperOpt != "PRIMARY KEY" && upperOpt != "UNIQUE" {
  48. colDef += " " + opt
  49. }
  50. }
  51. // 如果是主键列,确保有 NOT NULL
  52. isPrimaryKey := false
  53. for _, pk := range primaryKeyColumns {
  54. if pk == col.Name {
  55. isPrimaryKey = true
  56. break
  57. }
  58. }
  59. if isPrimaryKey {
  60. hasNotNull := false
  61. for _, opt := range col.Options {
  62. if strings.ToUpper(opt) == "NOT NULL" {
  63. hasNotNull = true
  64. break
  65. }
  66. }
  67. if !hasNotNull {
  68. colDef += " NOT NULL"
  69. }
  70. }
  71. // 添加默认值
  72. if col.Default != "" {
  73. upperDefault := strings.ToUpper(col.Default)
  74. if strings.Contains(upperDefault, "CURRENT_TIMESTAMP") ||
  75. strings.Contains(upperDefault, "NOW()") ||
  76. strings.Contains(upperDefault, "UUID()") ||
  77. strings.Contains(upperDefault, "NULL") {
  78. colDef += " DEFAULT " + col.Default
  79. } else {
  80. colDef += fmt.Sprintf(" DEFAULT '%s'", col.Default)
  81. }
  82. }
  83. // 添加注释
  84. if col.Comment != "" {
  85. colDef += fmt.Sprintf(` COMMENT "%s"`, col.Comment)
  86. }
  87. if i < len(table.Schema.Columns)-1 {
  88. sql.WriteString(colDef + ",\n")
  89. } else {
  90. sql.WriteString(colDef + "\n")
  91. }
  92. }
  93. // 关闭列定义括号
  94. sql.WriteString(")")
  95. // 添加 UNIQUE KEY(如果有主键列)
  96. if len(primaryKeyColumns) > 0 {
  97. sql.WriteString(fmt.Sprintf("\nUNIQUE KEY(%s)", strings.Join(primaryKeyColumns, ", ")))
  98. }
  99. // 分布式配置 - 使用第一个主键列,如果没有主键则使用第一个列
  100. distKey := ""
  101. if len(primaryKeyColumns) > 0 {
  102. distKey = primaryKeyColumns[0]
  103. } else if len(table.Schema.Columns) > 0 {
  104. distKey = table.Schema.Columns[0].Name
  105. }
  106. if distKey != "" {
  107. sql.WriteString(fmt.Sprintf("\nDISTRIBUTED BY HASH(%s) BUCKETS 10", distKey))
  108. }
  109. // 副本数配置
  110. sql.WriteString("\nPROPERTIES (\"replication_num\" = \"1\");")
  111. return sql.String()
  112. }
  113. // getDorisType 获取Doris数据类型
  114. func (dg *DorisGenerator) getDorisType(col ColumnSchema) string {
  115. switch col.Type {
  116. case "DECIMAL":
  117. if col.Precision > 0 && col.Scale > 0 {
  118. return fmt.Sprintf("DECIMAL(%d,%d)", col.Precision, col.Scale)
  119. }
  120. return "DECIMAL"
  121. case "VARCHAR":
  122. if col.Length > 0 {
  123. return fmt.Sprintf("VARCHAR(%d)", col.Length)
  124. }
  125. return "VARCHAR(255)"
  126. case "CHAR":
  127. if col.Length > 0 {
  128. return fmt.Sprintf("CHAR(%d)", col.Length)
  129. }
  130. return "CHAR(1)"
  131. case "INT":
  132. return "INT"
  133. case "BIGINT":
  134. return "BIGINT"
  135. case "TINYINT":
  136. return "TINYINT"
  137. case "BOOL":
  138. return "BOOLEAN"
  139. case "DATETIME":
  140. return "DATETIME"
  141. case "TIMESTAMP":
  142. return "DATETIME" // Doris 中通常用 DATETIME
  143. case "DATE":
  144. return "DATE"
  145. case "TIME":
  146. return "TIME"
  147. case "TEXT":
  148. return "STRING"
  149. case "JSON":
  150. return "STRING"
  151. case "BLOB":
  152. return "STRING"
  153. case "FLOAT":
  154. return "FLOAT"
  155. case "DOUBLE":
  156. return "DOUBLE"
  157. default:
  158. return col.Type
  159. }
  160. }
  161. func init() {
  162. RegisterGenerator(NewDorisGenerator())
  163. }