errors.go 2.8 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  1. package vrtxsql
  2. // 驱动错误: 在 database/sql 边界给错误挂上 SQLSTATE (5 字符), 让调用方可以
  3. // errors.As 提取状态码做分支 (例如锁冲突重试、约束冲突提示), 而不必解析中文文本。
  4. //
  5. // database/sql 本身没有强制的 SQLState 接口; 这里沿用 PostgreSQL/ODBC 约定提供
  6. // SQLState() string。Unwrap 穿透到被包装的引擎哨兵错误, errors.Is/As 仍可用。
  7. import (
  8. "errors"
  9. "fmt"
  10. "git.ycl.pub/yl32940/TsDB2/DB/core"
  11. "git.ycl.pub/yl32940/TsDB2/DB/core/types"
  12. )
  13. // SQLError 携带 SQLSTATE 的错误。
  14. type SQLError struct {
  15. State string // 5 字符 SQLSTATE
  16. Message string
  17. cause error
  18. }
  19. func (e *SQLError) Error() string { return e.Message }
  20. func (e *SQLError) SQLState() string { return e.State }
  21. func (e *SQLError) Unwrap() error { return e.cause }
  22. // sqlError 直接构造一个带状态的错误。
  23. func sqlError(state, format string, args ...any) error {
  24. return &SQLError{State: state, Message: fmt.Sprintf(format, args...)}
  25. }
  26. // withState 给已有错误挂上状态 (保留 cause 链)。
  27. func withState(err error, state string) error {
  28. if err == nil {
  29. return nil
  30. }
  31. return &SQLError{State: state, Message: err.Error(), cause: err}
  32. }
  33. // classifyError 按引擎哨兵错误映射 SQLSTATE; 已是 *SQLError 的原样返回。
  34. func classifyError(err error) error {
  35. if err == nil {
  36. return nil
  37. }
  38. var se *SQLError
  39. if errors.As(err, &se) {
  40. return err
  41. }
  42. switch {
  43. // 08/55 — 连接 / 锁
  44. case errors.Is(err, core.ErrDatabaseLocked):
  45. return withState(err, "55006") // 库被占用 (object in use)
  46. // 23 — 完整性约束冲突
  47. case errors.Is(err, core.ErrDuplicatedKey), errors.Is(err, core.ErrDuplicatePK):
  48. return withState(err, "23000")
  49. // 25 — 事务状态
  50. case errors.Is(err, core.ErrReadOnly):
  51. return withState(err, "25008") // 只读连接/事务中不能执行
  52. case errors.Is(err, core.ErrTxnActive):
  53. return withState(err, "25001") // 活跃事务中
  54. // 42 — 语法 / 权限相关对象定义
  55. case errors.Is(err, core.ErrTableNotFound):
  56. return withState(err, "42S02") // 表不存在
  57. case errors.Is(err, core.ErrFieldNotFound):
  58. return withState(err, "42S22") // 列不存在
  59. case errors.Is(err, core.ErrIndexNotFound):
  60. return withState(err, "42S12") // 索引不存在
  61. case errors.Is(err, core.ErrTableExists):
  62. return withState(err, "42S01") // 表已存在
  63. case errors.Is(err, core.ErrIndexExists):
  64. return withState(err, "42S11") // 索引已存在
  65. case errors.Is(err, core.ErrFieldExists):
  66. return withState(err, "42S21") // 列已存在
  67. // 22 — 数据异常 (类型不匹配 / 超范围 / 编码)
  68. case errors.Is(err, types.ErrValueType), errors.Is(err, types.ErrValueRange),
  69. errors.Is(err, types.ErrColumnScale), errors.Is(err, types.ErrDecimalRange),
  70. errors.Is(err, types.ErrEncodeBufSize):
  71. return withState(err, "22000")
  72. }
  73. return err
  74. }