# Oracle 异常映射:ORA 码、约束名、固定对外文案。 from __future__ import annotations import re _ORA_CODE_RE = re.compile(r"ORA-(\d+)", re.I) _CONSTRAINT_RE = re.compile( r"unique constraint \((?:[\w$#]+\.)?([\w$#]+)\)", re.I, ) SALES_OMS_ID_CONSTRAINT = "UK_RPA_SGMD_OMS_ID" CONTRACT_FID_CONSTRAINTS = frozenset({"PK_RPA_PCD"}) # 数据库连不上、未配置或 thick client 初始化失败。 # # 对外消息固定为「数据库不可用」,不带 DSN、库路径或 ORA 原文。 class RepoUnavailable(Exception): # 记下对外文案。默认「数据库不可用」,不要把 ORA 原文传进来。 def __init__(self, message: str = "数据库不可用"): self.message = message super().__init__(message) # 取出异常上的 Oracle 错误号,没有则返回 None。 def ora_code(exc: BaseException) -> int | None: if exc.args: info = exc.args[0] code = getattr(info, "code", None) if code is not None: return int(code) code = getattr(exc, "code", None) if code is not None: return int(code) match = _ORA_CODE_RE.search(str(exc)) if match: return int(match.group(1)) return None # 从 ORA-00001 报文里取出约束名(不含 schema),没有则返回 None。 def ora_constraint(exc: BaseException) -> str | None: chunks: list[str] = [str(exc)] if exc.args: info = exc.args[0] message = getattr(info, "message", None) if message: chunks.append(str(message)) for text in chunks: match = _CONSTRAINT_RE.search(text) if match: return match.group(1) return None # 是否为表 1 oms_id 唯一约束冲突(接口 1 DUPLICATE)。 # # 只有约束名是 uk_rpa_sgmd_oms_id 才算。其它唯一约束即使是 ORA-00001 也返回 False。 def is_sales_oms_id_duplicate(exc: BaseException) -> bool: if ora_code(exc) != 1: return False name = ora_constraint(exc) return bool(name) and name.upper() == SALES_OMS_ID_CONSTRAINT # 是否为表 3 fid 主键冲突(接口 3 DUPLICATE)。 # # 目前对应 pk_rpa_pcd。未知唯一约束返回 False。 def is_contract_fid_duplicate(exc: BaseException) -> bool: if ora_code(exc) != 1: return False name = ora_constraint(exc) return bool(name) and name.upper() in CONTRACT_FID_CONSTRAINTS