2026-10-22 04:18:27 -06:00

55 lines
2.3 KiB
Python
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env python3
"""Snapshot a readable SQLite table to JSONL without modifying its source."""
import argparse
import json
import sqlite3
from pathlib import Path
def export(source, table, output):
source, output = Path(source).resolve(), Path(output).resolve()
if source == output or output.exists():
raise ValueError('输出文件已存在或与源文件相同,请使用新的输出路径')
with source.open('rb') as file:
if file.read(16) != b'SQLite format 3\x00':
raise ValueError('源文件不是明文 SQLite;此脚本不解密数据库')
db = sqlite3.connect(source.as_uri() + '?mode=ro', uri=True, timeout=15)
snapshot = sqlite3.connect(':memory:')
created = False
try:
# Backup API includes committed WAL contents; never copy only a live .db.
db.backup(snapshot)
snapshot.row_factory = sqlite3.Row
names = [r[0] for r in snapshot.execute("SELECT name FROM sqlite_master WHERE type='table'")]
if table not in names:
raise ValueError('消息表不存在,可用表:' + ', '.join(names))
quoted = '"' + table.replace('"', '""') + '"'
with output.open('x', encoding='utf-8') as file:
created = True
try:
output.chmod(0o600)
except OSError:
pass
for row in snapshot.execute('SELECT * FROM ' + quoted):
record = dict(row)
if any(isinstance(v, bytes) for v in record.values()):
raise ValueError('表中含二进制字段,需先解码/转换;不会把 BLOB 假装成消息正文')
file.write(json.dumps(record, ensure_ascii=False) + '\n')
except Exception:
if created and output.exists():
output.unlink() # Only the output file exclusively created by this invocation.
raise
finally:
db.close()
snapshot.close()
if __name__ == '__main__':
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('source', type=Path)
parser.add_argument('table')
parser.add_argument('output', type=Path)
args = parser.parse_args()
export(args.source, args.table, args.output)
print('Readable JSONL written to:', args.output.resolve())