Ei kuvausta
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.

save_table_alias.go 8.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251
  1. package aliasmanagement
  2. import (
  3. "context"
  4. "fmt"
  5. "regexp"
  6. "git.x2erp.com/qdy/go-base/ctx"
  7. "git.x2erp.com/qdy/go-base/logger"
  8. "git.x2erp.com/qdy/go-base/model/response"
  9. "git.x2erp.com/qdy/go-base/util"
  10. "git.x2erp.com/qdy/go-db/factory/database"
  11. "git.x2erp.com/qdy/go-svc-configure/internal/tables"
  12. "github.com/google/uuid"
  13. "github.com/jmoiron/sqlx"
  14. )
  15. // SaveTableAlias 保存表别名字典(创建或更新)
  16. func SaveTableAlias(req *TableAliasRequest, ctx context.Context, dbFactory *database.DBFactory, reqCtx *ctx.RequestContext) *response.QueryResult[TableAliasDetail] {
  17. logger.Debug("SaveTableAlias-开始保存表别名字典")
  18. // 参数验证
  19. if err := validateTableAliasRequest(req); err != nil {
  20. logger.ErrorC(reqCtx, fmt.Sprintf("参数验证失败: %v", err))
  21. return util.CreateErrorResult[TableAliasDetail](fmt.Sprintf("参数验证失败: %v", err), reqCtx)
  22. }
  23. // 获取数据库连接并开始事务
  24. db := dbFactory.GetDB()
  25. tx, err := db.BeginTxx(ctx, nil)
  26. if err != nil {
  27. logger.ErrorC(reqCtx, fmt.Sprintf("开始事务失败: %v", err))
  28. return util.CreateErrorResult[TableAliasDetail](fmt.Sprintf("开始事务失败: %v", err), reqCtx)
  29. }
  30. defer func() {
  31. if p := recover(); p != nil {
  32. tx.Rollback()
  33. panic(p)
  34. }
  35. }()
  36. // 获取当前用户
  37. creator := reqCtx.UserID
  38. if creator == "" {
  39. creator = "system"
  40. }
  41. // 检查表别名是否已存在(基于table_alias字段的唯一索引)
  42. aliasExists, err := checkTableAliasExists(ctx, tx, req.TableAlias)
  43. if err != nil {
  44. tx.Rollback()
  45. logger.ErrorC(reqCtx, fmt.Sprintf("检查表别名存在性失败: %v", err))
  46. return util.CreateErrorResult[TableAliasDetail](fmt.Sprintf("检查表别名存在性失败: %v", err), reqCtx)
  47. }
  48. var tableAlias tables.DicTableAliasDB
  49. if aliasExists {
  50. // 更新表别名(根据ID或table_alias)
  51. tableAlias, err = updateTableAlias(ctx, tx, req)
  52. if err != nil {
  53. tx.Rollback()
  54. logger.ErrorC(reqCtx, fmt.Sprintf("更新表别名失败: %v", err))
  55. return util.CreateErrorResult[TableAliasDetail](fmt.Sprintf("更新表别名失败: %v", err), reqCtx)
  56. }
  57. logger.Debug(fmt.Sprintf("更新表别名成功: %s", req.TableAlias))
  58. } else {
  59. // 检查是否有软删除的记录
  60. softDeletedExists, err := checkSoftDeletedTableAliasExists(ctx, tx, req.TableAlias)
  61. if err != nil {
  62. tx.Rollback()
  63. logger.ErrorC(reqCtx, fmt.Sprintf("检查软删除表别名存在性失败: %v", err))
  64. return util.CreateErrorResult[TableAliasDetail](fmt.Sprintf("检查软删除表别名存在性失败: %v", err), reqCtx)
  65. }
  66. if softDeletedExists {
  67. // 恢复软删除的表别名
  68. tableAlias, err = restoreTableAlias(ctx, tx, req)
  69. if err != nil {
  70. tx.Rollback()
  71. logger.ErrorC(reqCtx, fmt.Sprintf("恢复软删除表别名失败: %v", err))
  72. return util.CreateErrorResult[TableAliasDetail](fmt.Sprintf("恢复软删除表别名失败: %v", err), reqCtx)
  73. }
  74. logger.Debug(fmt.Sprintf("恢复软删除表别名成功: %s", req.TableAlias))
  75. } else {
  76. // 插入新的表别名
  77. tableAlias, err = insertTableAlias(ctx, tx, req, creator)
  78. if err != nil {
  79. tx.Rollback()
  80. logger.ErrorC(reqCtx, fmt.Sprintf("插入表别名失败: %v", err))
  81. return util.CreateErrorResult[TableAliasDetail](fmt.Sprintf("插入表别名失败: %v", err), reqCtx)
  82. }
  83. logger.Debug(fmt.Sprintf("插入表别名成功: %s", req.TableAlias))
  84. }
  85. }
  86. // 提交事务
  87. if err := tx.Commit(); err != nil {
  88. logger.ErrorC(reqCtx, fmt.Sprintf("提交事务失败: %v", err))
  89. return util.CreateErrorResult[TableAliasDetail](fmt.Sprintf("提交事务失败: %v", err), reqCtx)
  90. }
  91. logger.Debug(fmt.Sprintf("成功保存表别名字典: %s", req.TableAlias))
  92. // 构建返回结果
  93. detail := TableAliasDetail{
  94. TableAlias: tableAlias,
  95. }
  96. return util.CreateSuccessResultData[TableAliasDetail](detail, reqCtx)
  97. }
  98. // validateTableAliasRequest 验证表别名字典请求
  99. func validateTableAliasRequest(req *TableAliasRequest) error {
  100. if req.TableID == "" {
  101. return fmt.Errorf("表ID不能为空")
  102. }
  103. // 验证表ID格式:仅允许字母、数字、下划线
  104. match, _ := regexp.MatchString("^[a-zA-Z0-9_]+$", req.TableID)
  105. if !match {
  106. return fmt.Errorf("表ID只能包含字母、数字、下划线")
  107. }
  108. if req.TableAlias == "" {
  109. return fmt.Errorf("别名不能为空")
  110. }
  111. // 验证别名格式:仅允许字母、数字、下划线
  112. match, _ = regexp.MatchString("^[a-zA-Z0-9_]+$", req.TableAlias)
  113. if !match {
  114. return fmt.Errorf("别名只能包含字母、数字、下划线")
  115. }
  116. return nil
  117. }
  118. // checkTableAliasExists 检查表别名是否存在(仅活跃记录,基于table_alias)
  119. func checkTableAliasExists(ctx context.Context, tx *sqlx.Tx, tableAlias string) (bool, error) {
  120. var count int
  121. query := "SELECT COUNT(*) FROM dic_table_alias WHERE table_alias = ? AND deleted_at IS NULL"
  122. err := tx.GetContext(ctx, &count, query, tableAlias)
  123. return count > 0, err
  124. }
  125. // checkSoftDeletedTableAliasExists 检查表别名是否被软删除(基于table_alias)
  126. func checkSoftDeletedTableAliasExists(ctx context.Context, tx *sqlx.Tx, tableAlias string) (bool, error) {
  127. var count int
  128. query := "SELECT COUNT(*) FROM dic_table_alias WHERE table_alias = ? AND deleted_at IS NOT NULL"
  129. err := tx.GetContext(ctx, &count, query, tableAlias)
  130. return count > 0, err
  131. }
  132. // restoreTableAlias 恢复软删除的表别名
  133. func restoreTableAlias(ctx context.Context, tx *sqlx.Tx, req *TableAliasRequest) (tables.DicTableAliasDB, error) {
  134. query := `
  135. UPDATE dic_table_alias
  136. SET deleted_at = NULL, table_id = ?, updated_at = CURRENT_TIMESTAMP
  137. WHERE table_alias = ? AND deleted_at IS NOT NULL
  138. `
  139. _, err := tx.ExecContext(ctx, query,
  140. req.TableID,
  141. req.TableAlias,
  142. )
  143. if err != nil {
  144. return tables.DicTableAliasDB{}, err
  145. }
  146. // 查询恢复后的记录
  147. var tableAlias tables.DicTableAliasDB
  148. selectQuery := `
  149. SELECT id, table_id, table_alias, created_at, updated_at, deleted_at
  150. FROM dic_table_alias
  151. WHERE table_alias = ? AND deleted_at IS NULL
  152. `
  153. err = tx.GetContext(ctx, &tableAlias, selectQuery, req.TableAlias)
  154. return tableAlias, err
  155. }
  156. // insertTableAlias 插入表别名
  157. func insertTableAlias(ctx context.Context, tx *sqlx.Tx, req *TableAliasRequest, creator string) (tables.DicTableAliasDB, error) {
  158. // 生成ID
  159. id := req.ID
  160. if id == "" {
  161. id = uuid.New().String()
  162. }
  163. query := `
  164. INSERT INTO dic_table_alias (id, table_id, table_alias, created_at, updated_at)
  165. VALUES (?, ?, ?, CURRENT_TIMESTAMP, CURRENT_TIMESTAMP)
  166. `
  167. logger.Debug(fmt.Sprintf("insertTableAlias - 执行插入: query=%s, id=%s, table_id=%s, table_alias=%s", query, id, req.TableID, req.TableAlias))
  168. _, err := tx.ExecContext(ctx, query,
  169. id,
  170. req.TableID,
  171. req.TableAlias,
  172. )
  173. if err != nil {
  174. logger.Error(fmt.Sprintf("insertTableAlias - 插入失败: %v", err))
  175. return tables.DicTableAliasDB{}, err
  176. }
  177. // 查询刚插入的记录
  178. var tableAlias tables.DicTableAliasDB
  179. selectQuery := `
  180. SELECT id, table_id, table_alias, created_at, updated_at, deleted_at
  181. FROM dic_table_alias
  182. WHERE table_alias = ? AND deleted_at IS NULL
  183. `
  184. err = tx.GetContext(ctx, &tableAlias, selectQuery, req.TableAlias)
  185. return tableAlias, err
  186. }
  187. // updateTableAlias 更新表别名
  188. func updateTableAlias(ctx context.Context, tx *sqlx.Tx, req *TableAliasRequest) (tables.DicTableAliasDB, error) {
  189. // 使用ID更新(如果提供ID),否则使用table_alias
  190. var query string
  191. var queryArgs []interface{}
  192. if req.ID != "" {
  193. query = `
  194. UPDATE dic_table_alias
  195. SET table_id = ?, updated_at = CURRENT_TIMESTAMP
  196. WHERE id = ? AND deleted_at IS NULL
  197. `
  198. queryArgs = []interface{}{req.TableID, req.ID}
  199. } else {
  200. query = `
  201. UPDATE dic_table_alias
  202. SET table_id = ?, updated_at = CURRENT_TIMESTAMP
  203. WHERE table_alias = ? AND deleted_at IS NULL
  204. `
  205. queryArgs = []interface{}{req.TableID, req.TableAlias}
  206. }
  207. _, err := tx.ExecContext(ctx, query, queryArgs...)
  208. if err != nil {
  209. return tables.DicTableAliasDB{}, err
  210. }
  211. // 查询更新后的记录
  212. var tableAlias tables.DicTableAliasDB
  213. selectQuery := `
  214. SELECT id, table_id, table_alias, created_at, updated_at, deleted_at
  215. FROM dic_table_alias
  216. WHERE table_alias = ? AND deleted_at IS NULL
  217. `
  218. err = tx.GetContext(ctx, &tableAlias, selectQuery, req.TableAlias)
  219. return tableAlias, err
  220. }