From c924d07b3e5ffa19e4b333da33147aecd2534d72 Mon Sep 17 00:00:00 2001 From: Vu Nguyen Date: Mon, 13 Apr 2026 22:30:56 -0500 Subject: [PATCH 1/2] fix(status): paginate metadata fetch to support large palaces `col.get(limit=total)` causes SQLite "too many SQL variables" on palaces with >10k drawers (#802) and on older versions the hardcoded limit=10000 silently truncated the count (#850). Paginate in 5k batches using offset and aggregate wing/room counts incrementally. Also use `col.count()` for the header instead of `len(metas)` so the displayed total is always correct. Tested on a 122,686-drawer palace. Fixes #850 Related: #802, #723 --- mempalace/miner.py | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/mempalace/miner.py b/mempalace/miner.py index 73fe0c4..0b9b5b0 100644 --- a/mempalace/miner.py +++ b/mempalace/miner.py @@ -821,17 +821,23 @@ def status(palace_path: str): print(" Run: mempalace init then mempalace mine ") return - # Count by wing and room + # Count by wing and room — paginate to avoid SQLite "too many SQL + # variables" error on large palaces (see #802, #850). total = col.count() - r = col.get(limit=total, include=["metadatas"]) if total else {"metadatas": []} - metas = r["metadatas"] - - wing_rooms = defaultdict(lambda: defaultdict(int)) - for m in metas: - wing_rooms[m.get("wing", "?")][m.get("room", "?")] += 1 + wing_rooms: dict = defaultdict(lambda: defaultdict(int)) + batch_size = 5000 + offset = 0 + while offset < total: + r = col.get(limit=batch_size, offset=offset, include=["metadatas"]) + batch = r["metadatas"] + if not batch: + break + for m in batch: + wing_rooms[m.get("wing", "?")][m.get("room", "?")] += 1 + offset += len(batch) print(f"\n{'=' * 55}") - print(f" MemPalace Status — {len(metas)} drawers") + print(f" MemPalace Status — {total} drawers") print(f"{'=' * 55}\n") for wing, rooms in sorted(wing_rooms.items()): print(f" WING: {wing}") From 3004ac4ee45e76eb06199fe7613ee90d3100b483 Mon Sep 17 00:00:00 2001 From: Vu Nguyen Date: Sun, 19 Apr 2026 01:29:25 -0500 Subject: [PATCH 2/2] fix(miner): port None-metadata guard into paginated status loop Upstream develop commit feba7e8 (2026-04-18) added `m = m or {}` to the single-shot `for m in metas:` loop after this branch already rewrote status() to paginate. Without porting the guard forward, merging this PR would silently drop jp's fix and crash again on palaces with null-metadata drawers. Addresses bensig's review on #851. --- mempalace/miner.py | 1 + 1 file changed, 1 insertion(+) diff --git a/mempalace/miner.py b/mempalace/miner.py index 0b9b5b0..5ab662e 100644 --- a/mempalace/miner.py +++ b/mempalace/miner.py @@ -833,6 +833,7 @@ def status(palace_path: str): if not batch: break for m in batch: + m = m or {} wing_rooms[m.get("wing", "?")][m.get("room", "?")] += 1 offset += len(batch)