package vrtxsql // 驱动错误: 在 database/sql 边界给错误挂上 SQLSTATE (5 字符), 让调用方可以 // errors.As 提取状态码做分支 (例如锁冲突重试、约束冲突提示), 而不必解析中文文本。 // // database/sql 本身没有强制的 SQLState 接口; 这里沿用 PostgreSQL/ODBC 约定提供 // SQLState() string。Unwrap 穿透到被包装的引擎哨兵错误, errors.Is/As 仍可用。 import ( "errors" "fmt" "git.ycl.pub/yl32940/TsDB2/DB/core" "git.ycl.pub/yl32940/TsDB2/DB/core/types" ) // SQLError 携带 SQLSTATE 的错误。 type SQLError struct { State string // 5 字符 SQLSTATE Message string cause error } func (e *SQLError) Error() string { return e.Message } func (e *SQLError) SQLState() string { return e.State } func (e *SQLError) Unwrap() error { return e.cause } // sqlError 直接构造一个带状态的错误。 func sqlError(state, format string, args ...any) error { return &SQLError{State: state, Message: fmt.Sprintf(format, args...)} } // withState 给已有错误挂上状态 (保留 cause 链)。 func withState(err error, state string) error { if err == nil { return nil } return &SQLError{State: state, Message: err.Error(), cause: err} } // classifyError 按引擎哨兵错误映射 SQLSTATE; 已是 *SQLError 的原样返回。 func classifyError(err error) error { if err == nil { return nil } var se *SQLError if errors.As(err, &se) { return err } switch { // 08/55 — 连接 / 锁 case errors.Is(err, core.ErrDatabaseLocked): return withState(err, "55006") // 库被占用 (object in use) // 23 — 完整性约束冲突 case errors.Is(err, core.ErrDuplicatedKey), errors.Is(err, core.ErrDuplicatePK): return withState(err, "23000") // 25 — 事务状态 case errors.Is(err, core.ErrReadOnly): return withState(err, "25008") // 只读连接/事务中不能执行 case errors.Is(err, core.ErrTxnActive): return withState(err, "25001") // 活跃事务中 // 42 — 语法 / 权限相关对象定义 case errors.Is(err, core.ErrTableNotFound): return withState(err, "42S02") // 表不存在 case errors.Is(err, core.ErrFieldNotFound): return withState(err, "42S22") // 列不存在 case errors.Is(err, core.ErrIndexNotFound): return withState(err, "42S12") // 索引不存在 case errors.Is(err, core.ErrTableExists): return withState(err, "42S01") // 表已存在 case errors.Is(err, core.ErrIndexExists): return withState(err, "42S11") // 索引已存在 case errors.Is(err, core.ErrFieldExists): return withState(err, "42S21") // 列已存在 // 22 — 数据异常 (类型不匹配 / 超范围 / 编码) case errors.Is(err, types.ErrValueType), errors.Is(err, types.ErrValueRange), errors.Is(err, types.ErrColumnScale), errors.Is(err, types.ErrDecimalRange), errors.Is(err, types.ErrEncodeBufSize): return withState(err, "22000") } return err }