新增修改

This commit is contained in:
2026-04-23 12:48:59 +08:00
parent df46812eff
commit 92b856b622
60 changed files with 18623 additions and 398 deletions

View File

@@ -0,0 +1,241 @@
#!/usr/bin/env python3
"""
在达梦数据库机器上运行,查看各表结构,用于编写 config 中的 db.query
用法: python scripts/inspect_dm_tables.py
密码获取顺序:环境变量 DM_PASS > 下方 LOCAL_PASSWORD
若使用 LOCAL_PASSWORD切勿提交到 git可执行git update-index --assume-unchanged scripts/inspect_dm_tables.py
"""
import os
import sys
# 可选:在此直接填写密码(仅限本机调试,切勿提交到版本库!)
LOCAL_PASSWORD = None # 例如: "你的密码"
# 支持从项目根或 scripts 目录运行
_script_dir = os.path.dirname(os.path.abspath(__file__))
_project_root = os.path.dirname(_script_dir)
XLSX_PATH = os.path.join(_project_root, "1125暂时属性需求(1).xlsx")
if _project_root not in sys.path:
sys.path.insert(0, _project_root)
try:
import dmPython
except ImportError:
print("请先安装: pip install dmPython")
sys.exit(1)
CONFIG = {
"user": os.getenv("DM_USER", "SYSDBA"),
"password": os.getenv("DM_PASS") or LOCAL_PASSWORD,
"server": os.getenv("DM_HOST", "127.0.0.1"),
"port": int(os.getenv("DM_PORT", "9080")),
"schema": "SYSDBA",
}
TABLES = [
"OBJECTIVE_INSTANCE",
"METRIC_VALUE_INSTANCE",
"METRIC_PROFILE",
"ROLE_PROFILE",
"TASK_PROFILE",
"RELATION_INSTANCE",
"RES_FORMAL_ANALYSIS",
]
def _load_required_attrs(xlsx_path: str) -> list:
"""从 1125暂时属性需求(1).xlsx 解析需求属性列表(一条=一个属性)"""
if not os.path.exists(xlsx_path):
print(f" (未找到 {xlsx_path},使用内置属性列表)")
return _DEFAULT_REQ_ATTRS
try:
import pandas as pd
df = pd.read_excel(xlsx_path, header=None)
attrs = []
for _, row in df.iterrows():
v0 = row[0]
v2 = str(row[2]) if len(row) > 2 and pd.notna(row[2]) else ""
if pd.notna(v0) and str(v0).strip() and str(v0) != "属性代码名称":
attrs.append(str(v0).strip())
if ":" in v2:
sub = v2.split(":")[0].strip()
if sub and sub not in attrs:
attrs.append(sub)
return attrs if attrs else _DEFAULT_REQ_ATTRS
except Exception as e:
print(f" (解析 xlsx 失败: {e},使用内置属性列表)")
return _DEFAULT_REQ_ATTRS
# xlsx 解析失败时的兜底属性列表(来自 1125暂时属性需求
_DEFAULT_REQ_ATTRS = [
"f_IC", "f_IA", "f_CS", "f_IT", "f_DP", "f_CPS", "f_CC",
"position", "effective_radius",
"response_time", "cycle_time", "data_age", "time_window",
"core_performance", "survivability", "mtbf",
"protocol_list", "format_list", "interface_list",
"security_level", "org_unit", "nation", "history_success",
]
def main():
if not CONFIG["password"]:
print("请设置环境变量 DM_PASS 或在脚本中填写 LOCAL_PASSWORD")
sys.exit(1)
try:
conn = dmPython.connect(
user=CONFIG["user"],
password=CONFIG["password"],
server=CONFIG["server"],
port=CONFIG["port"],
schema=CONFIG["schema"],
)
except Exception as e:
print(f"连接失败: {e}")
sys.exit(1)
cursor = conn.cursor()
print("=" * 60)
print("达梦表结构(用于编写 config/db.query")
print("=" * 60)
for table in TABLES:
try:
cursor.execute(f'SELECT * FROM "{CONFIG["schema"]}"."{table}" WHERE 1=0')
cols = [d[0] for d in cursor.description]
print(f"\n{table}】 列: {cols}")
except Exception as e:
print(f"\n{table}】 查询失败: {e}")
# 专门查询 METRIC_VALUE_INSTANCE 的字段详情(含完整属性)
mvi_table = "METRIC_VALUE_INSTANCE"
print("\n" + "=" * 80)
print(f"{mvi_table}】 字段详情(完整属性)")
print("=" * 80)
try:
# 查询 DBA_TAB_COLUMNS 全部常用属性(达梦兼容)
cursor.execute(
"""
SELECT COLUMN_NAME, DATA_TYPE, DATA_LENGTH, DATA_PRECISION, DATA_SCALE,
NULLABLE, DATA_DEFAULT, COLUMN_ID
FROM DBA_TAB_COLUMNS
WHERE OWNER = ? AND TABLE_NAME = ?
ORDER BY COLUMN_ID
""",
(CONFIG["schema"], mvi_table),
)
mvi_cols = cursor.fetchall()
# 表头
fmt = " {:<18} {:<16} {:<10} {:<10} {:<8} {:<10} {:<20}"
print(fmt.format("列名", "数据类型", "长度", "精度", "标度", "可空", "默认值"))
print(" " + "-" * 90)
for row in mvi_cols:
col_name, data_type, data_length, data_precision, data_scale, nullable, data_default, col_id = row
# 类型显示:数值型用 类型(精度,标度),字符型用 类型(长度)
if data_precision is not None:
type_str = f"{data_type}({data_precision},{data_scale or 0})"
elif data_length and data_type.upper() in ("VARCHAR", "CHAR", "VARCHAR2"):
type_str = f"{data_type}({data_length})"
elif data_length:
type_str = f"{data_type}({data_length})"
else:
type_str = data_type or ""
len_val = str(data_length) if data_length is not None else "-"
prec_val = str(data_precision) if data_precision is not None else "-"
scale_val = str(data_scale) if data_scale is not None else "-"
null_str = "NULL" if nullable == "Y" else "NOT NULL"
default_str = (str(data_default).strip() if data_default else "-")[:18]
print(fmt.format(col_name, type_str, len_val, prec_val, scale_val, null_str, default_str))
# 查询样本数据(若有)
cursor.execute(f'SELECT * FROM "{CONFIG["schema"]}"."{mvi_table}" WHERE ROWNUM <= 3')
sample_rows = cursor.fetchall()
if sample_rows:
col_names = [d[0] for d in cursor.description]
print(f"\n 样本数据 (最多 3 行):")
for i, row in enumerate(sample_rows, 1):
print(f"{i}: {dict(zip(col_names, row))}")
else:
print("\n (表无数据)")
except Exception as e:
print(f" 查询失败: {e}")
# 按 1125暂时属性需求(1).xlsx 查询 METRIC_VALUE_INSTANCE一条=一个属性)
print("\n" + "=" * 80)
print("【METRIC_VALUE_INSTANCE】按需求属性查询xlsx 中一条 = 一个 METRIC_ID")
print("=" * 80)
try:
# 1. 从 xlsx 解析需求属性列表
req_attrs = _load_required_attrs(XLSX_PATH)
print(f"\n xlsx 需求属性 ({len(req_attrs)} 个): {req_attrs}")
# 2. 查询库中实际存在的 METRIC_IDdistinct
cursor.execute(
f'SELECT DISTINCT METRIC_ID FROM "{CONFIG["schema"]}"."METRIC_VALUE_INSTANCE" ORDER BY METRIC_ID'
)
db_metric_ids = [r[0] for r in cursor.fetchall()]
print(f"\n 库中已有 METRIC_ID ({len(db_metric_ids)} 个): {db_metric_ids or '(无数据)'}")
# 3. METRIC_PROFILE 对照METRIC_ID -> 中文名)
cursor.execute(
f'SELECT METRIC_ID, METRIC_NAME FROM "{CONFIG["schema"]}"."METRIC_PROFILE"'
)
profile_map = dict(cursor.fetchall())
if profile_map:
print("\n METRIC_PROFILE 对照:")
for mid, mname in sorted(profile_map.items()):
print(f" {mid} -> {mname}")
# 4. 交集:需求属性中在库里有的
in_both = [a for a in req_attrs if a in db_metric_ids]
# 需求有但库无
missing = [a for a in req_attrs if a not in db_metric_ids]
# 库有但需求未列
extra = [m for m in db_metric_ids if m not in req_attrs]
print(f"\n 需求与库交集 (可查): {in_both or ''}")
print(f" 需求有但库无: {missing or ''}")
print(f" 库有但需求未列: {extra or ''}")
# 5. 按属性查询示例 SQL
print("\n --- 按属性查询示例 SQL ---")
for attr in (in_both or req_attrs)[:5]: # 最多展示 5 个
sql = f'SELECT * FROM "{CONFIG["schema"]}"."METRIC_VALUE_INSTANCE" WHERE METRIC_ID = \'{attr}\''
print(f" -- {attr}: {sql}")
if len(in_both or req_attrs) > 5:
print(f" ... 其余属性同理,将 METRIC_ID = 'xxx' 替换即可")
except Exception as e:
print(f" 查询失败: {e}")
import traceback
traceback.print_exc()
cursor.execute(
"""
SELECT TABLE_NAME, COLUMN_NAME, DATA_TYPE
FROM DBA_TAB_COLUMNS
WHERE OWNER = ?
ORDER BY TABLE_NAME, COLUMN_ID
""",
(CONFIG["schema"],),
)
rows = cursor.fetchall()
print("\n" + "=" * 60)
print("所有列详情 (TABLE_NAME | COLUMN_NAME | DATA_TYPE)")
print("=" * 60)
cur_table = None
for table, col, dtype in rows:
if table != cur_table:
cur_table = table
print(f"\n--- {table} ---")
print(f" {col}: {dtype}")
cursor.close()
conn.close()
print("\n完成。请根据上述结构在 config 中编写 db.query。")
if __name__ == "__main__":
main()