#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""实测 crawl_xiantao.py 的插入到底报什么错（复现 IntegrityError）。"""
import sqlite3

DB = "/root/search.db"
TEST_URL = "https://www.xiantao.gov.cn/bmxxgk/shbj/zfxxgk/fdzdgknr/qtzdgknr_37950/gsgg/202609/t20260902_6006038.shtml"
SITE, SCRIPT, GROUP = "xiantao_gsgg", "crawl_xiantao.py", "湖北"

c = sqlite3.connect(DB, timeout=60)
c.execute("PRAGMA journal_mode=WAL")
cur = c.cursor()

print("=== ① gov_raw 的 id 机制与当前最大 id ===")
mx = cur.execute("SELECT MAX(id) FROM gov_raw").fetchone()[0]
print("  MAX(gov_raw.id) =", mx)
row = cur.execute("SELECT sql FROM sqlite_master WHERE name='gov_raw'").fetchone()[0]
print("  gov_raw 定义片段:", row[:300])
print()

print("=== ② 模拟脚本的两步插入（用 SAVEPOINT 保证不污染库）===")
cur.execute("SAVEPOINT t1")
try:
    r = cur.execute(
        "INSERT INTO gov_raw (title, summary, content, page_url, source_url, publish_date, site_name, script_name, group_name) VALUES (?,?,?,?,?,?,?,?,?)",
        ("__TEST__ 诊断用", "s", "c" * 300, TEST_URL, TEST_URL, "2026-09-02", SITE, SCRIPT, GROUP))
    rid = r.lastrowid
    print("  ✅ 第①条 gov_raw 插入成功, lastrowid =", rid)
    try:
        cur.execute("INSERT INTO gov_search (rowid, title, site_name, summary) VALUES (?,?,?,?)",
                    (rid, "__TEST__", SITE, "s"))
        print("  ✅ 第②条 gov_search 插入成功")
    except sqlite3.IntegrityError as e:
        print("  ❌ 第②条 gov_search 插入失败 → IntegrityError:", e)
        print("     ★ 这正是脚本被吞掉的那个异常：gov_raw 那条因此也不会被 commit")
    gs = cur.execute("SELECT COUNT(*) FROM gov_search WHERE rowid=?", (rid,)).fetchone()[0]
    print("  gov_search 里 rowid=%s 已存在几行: %d" % (rid, gs))
except sqlite3.IntegrityError as e:
    print("  ❌ 第①条就失败 → IntegrityError:", e)
finally:
    cur.execute("ROLLBACK TO t1")
    cur.execute("RELEASE t1")
    c.commit()

print()
print("=== ③ gov_raw 与 gov_search 的 rowid 是否一致（错位诊断）===")
n_raw = cur.execute("SELECT COUNT(*) FROM gov_raw").fetchone()[0]
n_fst = cur.execute("SELECT COUNT(*) FROM gov_search").fetchone()[0]
mx_fst = cur.execute("SELECT MAX(rowid) FROM gov_search").fetchone()[0]
print("  gov_raw 行数 %d  /  gov_search 行数 %d" % (n_raw, n_fst))
print("  MAX(gov_search.rowid) = %s" % mx_fst)
overlap = cur.execute("""SELECT COUNT(*) FROM (SELECT rowid FROM gov_search) s
                         WHERE s.rowid IN (SELECT id FROM gov_raw)""").fetchone()[0]
print("  两边 rowid 交集: %d" % overlap)
print()
print("  结论：若交集 < gov_search 行数，说明 FTS 里有孤立 rowid（gov_raw 已删但 FTS 残留）")
print("        脚本新插入拿到的 lastrowid 一旦撞上这些孤立 rowid，就会 IntegrityError")
c.close()
