#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""枚举 gov_raw 上的触发器与索引，定位 constraint failed 的真凶。"""
import sqlite3

c = sqlite3.connect("/root/search.db", timeout=60)
cur = c.cursor()

print("=== ① gov_raw 上的触发器 ===")
trg = list(cur.execute("SELECT name, sql FROM sqlite_master WHERE type='trigger' AND tbl_name='gov_raw'"))
if not trg:
    print("  （无）")
for n, s in trg:
    print("  --- %s ---" % n)
    print("  " + (s or "").replace("\n", "\n  "))
print()

print("=== ② 索引 ===")
for r in cur.execute("PRAGMA index_list(gov_raw)"):
    print("  %-40s unique=%s partial=%s" % (r[1], r[2], r[4] if len(r) > 4 else "?"))
print()

print("=== ③ 各索引的列 ===")
for r in cur.execute("PRAGMA index_list(gov_raw)"):
    cols = [x[2] for x in cur.execute("PRAGMA index_info(%s)" % r[1])]
    print("  %-40s %s" % (r[1], cols))
print()

print("=== ④ 逐列试插，找出是哪一列/哪个约束导致失败 ===")
cols = [x[1] for x in cur.execute("PRAGMA table_info(gov_raw)")]
print("  列数 %d: %s" % (len(cols), ", ".join(cols)))
vals = {"title": "__DIAG__", "summary": "s", "content": "c" * 300,
        "page_url": "https://example.invalid/__diag__", "source_url": "https://example.invalid/__diag__",
        "publish_date": "2026-09-22", "site_name": "diag", "script_name": "diag.py", "group_name": "diag"}
cur.execute("SAVEPOINT s1")
try:
    q = "INSERT INTO gov_raw (%s) VALUES (%s)" % (",".join(vals), ",".join("?" * len(vals)))
    cur.execute(q, tuple(vals.values()))
    print("  ✅ 同上次测试的列集插入成功（那说明上次失败与列无关）")
except Exception as e:
    print("  ❌ 失败: %s: %s" % (type(e).__name__, e))
    print("     尝试用的列: %s" % ", ".join(vals))
    print()
    print("  → 逐个移除列，看是否某一列触发约束：")
    for drop in list(vals):
        v2 = {k: v for k, v in vals.items() if k != drop}
        try:
            cur.execute("SAVEPOINT s2")
            cur.execute("INSERT INTO gov_raw (%s) VALUES (%s)" % (",".join(v2), ",".join("?" * len(v2))),
                        tuple(v2.values()))
            print("     ✅ 去掉 %-14s 后插入成功 ★ 问题在这一列" % drop)
            cur.execute("ROLLBACK TO s2"); cur.execute("RELEASE s2")
            break
        except Exception as e2:
            cur.execute("ROLLBACK TO s2"); cur.execute("RELEASE s2")
    else:
        print("     去掉任何单列都仍失败 → 问题不在列，而在表级约束/触发器")
finally:
    cur.execute("ROLLBACK TO s1"); cur.execute("RELEASE s1")
    c.commit()
c.close()
