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.
 
 
 
 
 
 

44 lines
2.2 KiB

# -*- coding: utf-8 -*-
"""D-07 修复前置:sys_dept.ancestors 数据完整性校验(前缀查询口径 vs 递归口径一致才可上)。
py -X utf8 .scratch/customer-defectfix/check-ancestors.py
"""
import pymysql
def dbq(sql, args=None):
with pymysql.connect(host='8.129.84.155', port=3306, user='root', password='Itc@123456',
database='crm', charset='utf8mb4', autocommit=True,
connect_timeout=10, cursorclass=pymysql.cursors.DictCursor) as conn, \
conn.cursor() as cur:
cur.execute(sql, args)
return cur.fetchall()
rows = dbq("SELECT COUNT(*) total, "
"SUM(CASE WHEN ancestors IS NULL OR ancestors='' THEN 1 ELSE 0 END) blank "
"FROM sys_dept")
print(f"sys_dept 总数={rows[0]['total']} ancestors空={rows[0]['blank']}")
# 以「广东保伦」根部门(罗伟健所在)为样本:递归子树 vs 前缀查询 必须同数
root = dbq("SELECT dept_id FROM crm_auth_user WHERE id=739564171091247104")[0]['dept_id']
drow = dbq("SELECT id, dept_name, ancestors, parent_id FROM sys_dept WHERE id=%s", (root,))[0]
print(f"样本根部门 id={drow['id']} name={drow['dept_name']} ancestors={drow['ancestors']} "
f"parent_id={drow['parent_id']}")
chain = f"{drow['ancestors']},{drow['id']}"
rec = dbq("WITH RECURSIVE t AS (SELECT id FROM sys_dept WHERE id=%s "
"UNION ALL SELECT d.id FROM sys_dept d JOIN t ON d.parent_id=t.id) "
"SELECT COUNT(*) c FROM t", (root,))[0]['c']
pfx = dbq("SELECT COUNT(*) c FROM sys_dept WHERE ancestors=%s OR ancestors LIKE %s",
(chain, chain + ',%'))[0]['c'] + 1 # +1 = 自身
print(f"递归口径子树={rec} 前缀口径(含自身)={pfx} {'✅ 一致' if rec == pfx else '❌ 不一致——禁止用前缀查询'}")
# 逐部门抽查:每个部门的 ancestors 末段必须等于其 parent_id(链未断)
bad = dbq("SELECT COUNT(*) c FROM sys_dept WHERE parent_id<>0 AND "
"ancestors NOT LIKE CONCAT('%', parent_id)")
print(f"ancestors 末段≠parent_id 的断链行={bad[0]['c']}")
# 顶层行(parent_id=0)ancestors 必须为 '0'
badroot = dbq("SELECT COUNT(*) c FROM sys_dept WHERE parent_id=0 AND ancestors<>'0'")
print(f"顶层 ancestors≠'0' 的行={badroot[0]['c']}")