feat(xexdb): re-land #35 onto main — import-thunk naming, FKs, zq.py fixes, RE symbols #39

Merged
fabi merged 4 commits from feat/xexdb-import-naming into main 2026-09-16 05:09:15 +00:00
Showing only changes of commit 38cc170491 - Show all commits

View File

@@ -38,18 +38,59 @@ Usage:
A command that needs a table the current DB predates prints what to regenerate
rather than a SQL error.
The database is found via `$SYLPH_XEXDB`, else `<repo root>/sylpheed.db`. It is a
build artefact, not a tracked file; if neither exists, zq.py says so and prints
the command that builds one.
"""
import duckdb, sys, signal
import duckdb, sys, os, pathlib, signal
# Output is routinely piped into `head`; without this Python prints a
# BrokenPipeError traceback when the reader closes early.
signal.signal(signal.SIGPIPE, signal.SIG_DFL)
DB = '/home/fabi/RE - Project Sylpheed/xenia-rs/sylpheed.db'
c = duckdb.connect(DB, read_only=True)
H = lambda x: '0x%08x' % x
REGEN = "sylph-xexdb dis <xex|iso> --db sylpheed.db --analyze sql"
REGEN = ("xenia-rs dis <xex|iso> --db sylpheed.db --analyze sql")
def _resolve_db():
"""Locate the database: `$SYLPH_XEXDB`, else `<repo root>/sylpheed.db`.
🔴 This used to be one hardcoded absolute path, and it pointed *inside*
`xenia-rs` -- a repository `docs/agents/CONSOLIDATION.md` archives in Phase 5
and drops in Phase 7. It resolved on exactly one machine and would have
started failing there too, with `duckdb` raising about a missing file rather
than anything saying why.
The database is a build artefact of several hundred MB and is not in the
repository, so there is nothing to fall back *to*: if neither location has
one, say so and print how to build it. A default that silently resolves to
the wrong database is worse than no default -- see issue #16.
"""
env = os.environ.get('SYLPH_XEXDB')
if env:
p = pathlib.Path(env).expanduser()
if not p.is_file():
sys.exit(f'$SYLPH_XEXDB is set but is not a file:\n {p}')
return p
# Relative to this script, not to the caller's cwd: `zq.py` is run from
# wherever the investigation happens to be.
p = pathlib.Path(__file__).resolve().parent.parent / 'sylpheed.db'
if p.is_file():
return p
sys.exit(
f'no database found.\n'
f' looked for: {p}\n'
f' set $SYLPH_XEXDB to an existing one, or build it with:\n'
f' {REGEN}'
)
# Resolved lazily enough that `zq.py` with no command still prints its usage on
# a machine that has no database yet.
_WANTS_DB = len(sys.argv) > 1 and sys.argv[1] not in ('-h', '--help', 'help')
DB = _resolve_db() if _WANTS_DB else None
c = duckdb.connect(str(DB), read_only=True) if DB is not None else None
H = lambda x: '0x%08x' % x
def _need(*tables):