2026-09-06 23:27:37 +08:00
|
|
|
|
"""sqlite 测试 DDL 单一事实源(B8 · B4 评审 P3-12 收敛 / B5 评审 P3-4 时区)。
|
|
|
|
|
|
|
|
|
|
|
|
以 VARCHAR/TEXT/INTEGER/REAL 近似 MySQL 的 ENUM/SMALLINT/JSON/DECIMAL,
|
|
|
|
|
|
枚举防线不在测试 DB 层(由 service 白名单保证,见 test_profile_l3 口径注释)。
|
|
|
|
|
|
时间默认值统一 `(datetime('now','localtime'))`:sqlite CURRENT_TIMESTAMP 为 UTC,
|
|
|
|
|
|
本地 23:00~24:00 跑测试时与 MySQL localtime 口径错位一个日界(B5 评审 P3-4)。
|
|
|
|
|
|
列集为各测试所需列的并集;新表/新列只改此处,禁止再回测试文件手写。
|
|
|
|
|
|
"""
|
|
|
|
|
|
|
|
|
|
|
|
from sqlalchemy import create_engine, text
|
|
|
|
|
|
from sqlalchemy.pool import StaticPool
|
|
|
|
|
|
|
|
|
|
|
|
_TS = "TIMESTAMP DEFAULT (datetime('now','localtime'))"
|
|
|
|
|
|
|
|
|
|
|
|
SQLITE_TABLES: dict[str, str] = {
|
|
|
|
|
|
# ---- Core 模拟库(只读侧) ----
|
|
|
|
|
|
"core_customer": """
|
|
|
|
|
|
CREATE TABLE core_customer (
|
|
|
|
|
|
customer_id VARCHAR(64) PRIMARY KEY, display_name VARCHAR(128), age INTEGER,
|
|
|
|
|
|
occupation VARCHAR(64), open_date DATE, is_active TINYINT DEFAULT 1)
|
|
|
|
|
|
""",
|
|
|
|
|
|
"core_customer_risk": """
|
|
|
|
|
|
CREATE TABLE core_customer_risk (
|
|
|
|
|
|
customer_id VARCHAR(64), risk_code VARCHAR(8), evaluated_at TIMESTAMP)
|
|
|
|
|
|
""",
|
|
|
|
|
|
"core_customer_advisor": """
|
|
|
|
|
|
CREATE TABLE core_customer_advisor (
|
|
|
|
|
|
advisor_id VARCHAR(64), customer_id VARCHAR(64), rel_status VARCHAR(16))
|
|
|
|
|
|
""",
|
|
|
|
|
|
"core_product": """
|
|
|
|
|
|
CREATE TABLE core_product (
|
|
|
|
|
|
product_id VARCHAR(64) PRIMARY KEY, product_name VARCHAR(128),
|
|
|
|
|
|
min_risk_code VARCHAR(8), product_type VARCHAR(32))
|
|
|
|
|
|
""",
|
2026-09-07 08:43:36 +08:00
|
|
|
|
"core_holding": """
|
|
|
|
|
|
CREATE TABLE core_holding (
|
|
|
|
|
|
customer_id VARCHAR(64), product_id VARCHAR(64),
|
|
|
|
|
|
market_value DECIMAL, quantity DECIMAL)
|
|
|
|
|
|
""",
|
2026-09-06 23:27:37 +08:00
|
|
|
|
"core_trade": """
|
|
|
|
|
|
CREATE TABLE core_trade (
|
|
|
|
|
|
trade_id VARCHAR(64) PRIMARY KEY, customer_id VARCHAR(64), product_id VARCHAR(64),
|
|
|
|
|
|
trade_type VARCHAR(16), amount DECIMAL, trade_status VARCHAR(16),
|
|
|
|
|
|
traded_at TIMESTAMP)
|
|
|
|
|
|
""",
|
|
|
|
|
|
# ---- agent 库 ----
|
|
|
|
|
|
"audit_log": f"""
|
|
|
|
|
|
CREATE TABLE audit_log (
|
|
|
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT, trace_id VARCHAR(64), event_type VARCHAR(64),
|
|
|
|
|
|
agent_type VARCHAR(16), actor_id VARCHAR(64), customer_id VARCHAR(64),
|
|
|
|
|
|
rule_id VARCHAR(64), input_summary TEXT, decision VARCHAR(64), risk_score INTEGER,
|
|
|
|
|
|
handler_id VARCHAR(64), handler_result VARCHAR(64), handler_comment VARCHAR(512),
|
|
|
|
|
|
created_at {_TS})
|
|
|
|
|
|
""",
|
2026-09-07 02:32:03 +08:00
|
|
|
|
"input_guard_log": f"""
|
|
|
|
|
|
CREATE TABLE input_guard_log (
|
|
|
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT, trace_id VARCHAR(64), session_id VARCHAR(64),
|
|
|
|
|
|
agent_type VARCHAR(16), actor_id VARCHAR(64), guard_type VARCHAR(24),
|
|
|
|
|
|
raw_excerpt VARCHAR(1024), action VARCHAR(16),
|
|
|
|
|
|
created_at {_TS})
|
|
|
|
|
|
""",
|
2026-09-07 02:41:42 +08:00
|
|
|
|
"agent_session": f"""
|
|
|
|
|
|
CREATE TABLE agent_session (
|
|
|
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT, session_id VARCHAR(64) UNIQUE,
|
|
|
|
|
|
trace_id VARCHAR(64), agent_type VARCHAR(16), actor_id VARCHAR(64),
|
|
|
|
|
|
actor_role VARCHAR(32), customer_id VARCHAR(64), advisor_id VARCHAR(64),
|
|
|
|
|
|
title VARCHAR(256), status VARCHAR(16) DEFAULT 'active',
|
|
|
|
|
|
created_at {_TS}, closed_at TIMESTAMP)
|
|
|
|
|
|
""",
|
|
|
|
|
|
"agent_message": f"""
|
|
|
|
|
|
CREATE TABLE agent_message (
|
|
|
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT, session_id VARCHAR(64),
|
|
|
|
|
|
trace_id VARCHAR(64), seq_no INTEGER, role VARCHAR(16),
|
|
|
|
|
|
content TEXT, has_disclaimer TINYINT DEFAULT 0, token_est INTEGER,
|
|
|
|
|
|
created_at {_TS})
|
|
|
|
|
|
""",
|
2026-09-07 08:43:36 +08:00
|
|
|
|
"agent_tool_call": f"""
|
|
|
|
|
|
CREATE TABLE agent_tool_call (
|
|
|
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT, session_id VARCHAR(64),
|
|
|
|
|
|
trace_id VARCHAR(64), message_id INTEGER, tool_name VARCHAR(128),
|
|
|
|
|
|
tool_input TEXT, tool_output TEXT, status VARCHAR(16),
|
|
|
|
|
|
error_code VARCHAR(64), latency_ms INTEGER,
|
|
|
|
|
|
created_at {_TS})
|
|
|
|
|
|
""",
|
2026-09-06 23:27:37 +08:00
|
|
|
|
"risk_alert": f"""
|
|
|
|
|
|
CREATE TABLE risk_alert (
|
|
|
|
|
|
alert_id VARCHAR(64) PRIMARY KEY, trace_id VARCHAR(64), customer_id VARCHAR(64),
|
|
|
|
|
|
trade_id VARCHAR(64), alert_type VARCHAR(16), triggered_rules TEXT,
|
|
|
|
|
|
risk_score INTEGER, status VARCHAR(24) DEFAULT 'pending_review', payload TEXT,
|
|
|
|
|
|
handler_id VARCHAR(64), handler_result VARCHAR(64), handler_comment VARCHAR(512),
|
|
|
|
|
|
created_at {_TS}, handled_at TIMESTAMP)
|
|
|
|
|
|
""",
|
|
|
|
|
|
"risk_suitability_log": f"""
|
|
|
|
|
|
CREATE TABLE risk_suitability_log (
|
|
|
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT, trace_id VARCHAR(64), customer_id VARCHAR(64),
|
|
|
|
|
|
product_id VARCHAR(64), customer_risk_level VARCHAR(8), product_risk_level VARCHAR(8),
|
|
|
|
|
|
is_matched TINYINT, is_blocked TINYINT, block_reason VARCHAR(512),
|
|
|
|
|
|
request_ref VARCHAR(64), profile_l1_version VARCHAR(32),
|
|
|
|
|
|
created_at {_TS})
|
|
|
|
|
|
""",
|
|
|
|
|
|
"customer_profile_l3": f"""
|
|
|
|
|
|
CREATE TABLE customer_profile_l3 (
|
|
|
|
|
|
customer_id VARCHAR(64) PRIMARY KEY, monitor_tier VARCHAR(16) NOT NULL,
|
|
|
|
|
|
risk_score INTEGER, score_dimensions TEXT, monitor_tags TEXT,
|
|
|
|
|
|
last_alert_id VARCHAR(64), computed_at TIMESTAMP NOT NULL,
|
|
|
|
|
|
updated_at {_TS})
|
|
|
|
|
|
""",
|
|
|
|
|
|
"risk_aml_list": f"""
|
|
|
|
|
|
CREATE TABLE risk_aml_list (
|
|
|
|
|
|
id INTEGER PRIMARY KEY AUTOINCREMENT, list_id VARCHAR(64), list_type VARCHAR(16),
|
|
|
|
|
|
full_name VARCHAR(128), id_no VARCHAR(32), bank_card_no VARCHAR(32),
|
|
|
|
|
|
match_threshold REAL, source VARCHAR(64), list_version VARCHAR(16),
|
|
|
|
|
|
effective_date DATE, is_active TINYINT DEFAULT 1, created_at {_TS})
|
|
|
|
|
|
""",
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
def create_sqlite_engine():
|
|
|
|
|
|
"""内存 sqlite + 全部表(StaticPool 单连接共享,同现有测试模式)。"""
|
|
|
|
|
|
engine = create_engine(
|
|
|
|
|
|
"sqlite://", poolclass=StaticPool, connect_args={"check_same_thread": False}
|
|
|
|
|
|
)
|
|
|
|
|
|
with engine.begin() as conn:
|
|
|
|
|
|
for ddl in SQLITE_TABLES.values():
|
|
|
|
|
|
conn.execute(text(ddl))
|
|
|
|
|
|
return engine
|